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


      1 /*
      2  * 
      3  *
      4  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      5  * 
      6  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      7  *
      8  * File:
      9  *  oam.c
     10  *
     11  * Purpose:
     12  *  OAM implementation for Triumph3 family of devices.
     13  */
     14 
     15 #include <shared/bsl.h>
     16 
     17 #include <sal/core/libc.h>
     18 #include <soc/defs.h>
     19 #include <soc/drv.h>
     20 #include <soc/scache.h>
     21 #include <soc/profile_mem.h>
     22 #include <soc/hash.h>
     23 #include <soc/l3x.h>
     24 #include <soc/triumph3.h>
     25 #include <soc/ism_hash.h>
     26 
     27 #include <bcm/l3.h>
     28 #include <bcm/oam.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/triumph3.h>
     35 #include <bcm_int/esw/virtual.h>
     36 #include <bcm_int/esw_dispatch.h>
     37 
     38 #if defined(BCM_TRIUMPH3_SUPPORT)  && defined(INCLUDE_BHH)
     39 #include <bcm_int/esw/bhh.h>
     40 #include <bcm_int/esw/bhh_sdk_pack.h>
     41 #include <soc/uc.h>
     42 #endif /* BCM_TRIUMPH3_SUPPORT */
     43 #if defined(BCM_HURRICANE2_SUPPORT)
     44 #include <soc/hurricane2.h>
     45 #endif
     46 #if defined(BCM_GREYHOUND_SUPPORT)
     47 #include <soc/greyhound.h>
     48 #endif
     49 #if defined(BCM_HURRICANE3_SUPPORT)
     50 #include <soc/hurricane3.h>
     51 #endif
     52 #if defined(BCM_GREYHOUND2_SUPPORT)
     53 #include <soc/greyhound2.h>
     54 #endif
     55 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_HURRICANE2_SUPPORT)
     56 
     57 /*
     58  * Device OAM control structure.
     59  */
     60 _bcm_oam_control_t *_oam_control[SOC_MAX_NUM_DEVICES];
     61 
     62 /* * * * * * * * * * * * * * * * * * *
     63  *            OAM MACROS             *
     64  */
     65 /*
     66  * Macro:
     67  *     _BCM_OAM_IS_INIT (internal)
     68  * Purpose:
     69  *     Check that the unit is valid and confirm that the oam functions
     70  *     are initialized.
     71  * Parameters:
     72  *     unit - BCM device number
     73  * Notes:
     74  *     Results in return(BCM_E_UNIT), return(BCM_E_UNAVAIL), or
     75  *     return(BCM_E_INIT) if fails.
     76  */
     77 #define _BCM_OAM_IS_INIT(unit)                                               \
     78             do {                                                             \
     79                 if (!soc_feature(unit, soc_feature_oam)) {                   \
     80                     return (BCM_E_UNAVAIL);                                  \
     81                 }                                                            \
     82                 if (_oam_control[unit] == NULL) {                            \
     83                     LOG_ERROR(BSL_LS_BCM_OAM, \
     84                               (BSL_META_U(unit, \
     85                                           "OAM Error: Module not initialized\n"))); \
     86                     return (BCM_E_INIT);                                     \
     87                 }                                                            \
     88             } while (0)
     89 
     90 /*
     91  *Macro:
     92  *     _BCM_OAM_LOCK
     93  * Purpose:
     94  *     Lock take the OAM control mutex
     95  * Parameters:
     96  *     control - Pointer to OAM control structure.
     97  */
     98 #define _BCM_OAM_LOCK(control) \
     99             sal_mutex_take((control)->oc_lock, sal_mutex_FOREVER)
    100 
    101 /*
    102  * Macro:
    103  *     _BCM_OAM_UNLOCK
    104  * Purpose:
    105  *     Lock take the OAM control mutex
    106  * Parameters:
    107  *     control - Pointer to OAM control structure.
    108  */
    109 #define _BCM_OAM_UNLOCK(control) \
    110             sal_mutex_give((control)->oc_lock);
    111 /*
    112  * Macro:
    113  *     _BCM_OAM_HASH_DATA_CLEAR
    114  * Purpose:
    115  *      Clear hash data memory occupied by one endpoint.
    116  * Parameters:
    117  *     _ptr_    - Pointer to endpoint hash data memory. 
    118  */
    119 #define _BCM_OAM_HASH_DATA_CLEAR(_ptr_) \
    120             sal_memset(_ptr_, 0, sizeof(_bcm_oam_hash_data_t));
    121 
    122 /*
    123  * Macro:
    124  *     _BCM_OAM_HASH_DATA_HW_IDX_INIT
    125  * Purpose:
    126  *     Initialize hardware indices to invalid index for an endpoint hash data.
    127  * Parameters:
    128  *     _ptr_    - Pointer to endpoint hash data memory. 
    129  */
    130 #define _BCM_OAM_HASH_DATA_HW_IDX_INIT(_ptr_)                             \
    131             do {                                                          \
    132                     (_ptr_)->group_index = (_BCM_OAM_INVALID_INDEX);      \
    133                     (_ptr_)->remote_index = (_BCM_OAM_INVALID_INDEX);     \
    134                     (_ptr_)->profile_index = (_BCM_OAM_INVALID_INDEX);    \
    135                     (_ptr_)->pri_map_index = (_BCM_OAM_INVALID_INDEX);    \
    136                     (_ptr_)->lm_counter_index = (_BCM_OAM_INVALID_INDEX); \
    137                     (_ptr_)->local_tx_index = (_BCM_OAM_INVALID_INDEX);   \
    138                     (_ptr_)->local_rx_index = (_BCM_OAM_INVALID_INDEX);   \
    139             } while (0)
    140 /*
    141  * Macro:
    142  *     _BCM_OAM_ALLOC
    143  * Purpose:
    144  *      Generic memory allocation routine.
    145  * Parameters:
    146  *    _ptr_     - Pointer to allocated memory.
    147  *    _ptype_   - Pointer type.
    148  *    _size_    - Size of heap memory to be allocated.
    149  *    _descr_   - Information about this memory allocation.
    150  */
    151 #define _BCM_OAM_ALLOC(_ptr_,_ptype_,_size_,_descr_)                     \
    152             do {                                                         \
    153                 if (NULL == (_ptr_)) {                                   \
    154                    (_ptr_) = (_ptype_ *) sal_alloc((_size_), (_descr_)); \
    155                 }                                                        \
    156                 if((_ptr_) != NULL) {                                    \
    157                     sal_memset((_ptr_), 0, (_size_));                    \
    158                 }  else {                                                \
    159                     LOG_ERROR(BSL_LS_BCM_OAM, \
    160                               (BSL_META("OAM Error: Allocation failure %s\n"), \
    161                                (_descr_)));                                 \
    162                 }                                                        \
    163             } while (0)
    164 
    165 /*
    166  * Macro:
    167  *     _BCM_OAM_GROUP_INDEX_VALIDATE
    168  * Purpose:
    169  *     Validate OAM Group ID value.
    170  * Parameters:
    171  *     _group_ - Group ID value.
    172  */
    173 #define _BCM_OAM_GROUP_INDEX_VALIDATE(_group_)                               \
    174             do {                                                             \
    175                 if ((_group_) < 0 || (_group_) >= oc->group_count) {         \
    176                     LOG_ERROR(BSL_LS_BCM_OAM, \
    177                               (BSL_META("OAM Error: Invalid Group ID = %d.\n"), \
    178                                _group_));                                 \
    179                     return (BCM_E_PARAM);                                    \
    180                 }                                                            \
    181             } while (0);
    182 
    183 /*
    184  * Macro:
    185  *     _BCM_OAM_EP_INDEX_VALIDATE
    186  * Purpose:
    187  *     Validate OAM Endpoint ID value.
    188  * Parameters:
    189  *     _ep_ - Endpoint ID value.
    190  */
    191 #define _BCM_OAM_EP_INDEX_VALIDATE(_ep_)                               \
    192             do {                                                       \
    193                 if ((_ep_) < 0 || (_ep_) >= oc->ep_count) {            \
    194                     LOG_ERROR(BSL_LS_BCM_OAM, \
    195                               (BSL_META("OAM Error: Invalid Endpoint ID" \
    196                                " = %d.\n"), _ep_));                  \
    197                     return (BCM_E_PARAM);                              \
    198                 }                                                      \
    199             } while (0);
    200 
    201 /*
    202  * Macro:
    203  *     _BCM_OAM_RMEP_INDEX_VALIDATE
    204  * Purpose:
    205  *     Validate OAM Endpoint ID value.
    206  * Parameters:
    207  *     _ep_ - Endpoint ID value.
    208  */
    209 #define _BCM_OAM_RMEP_INDEX_VALIDATE(_ep_)                              \
    210             do {                                                        \
    211                 if ((_ep_) < 0 || (_ep_) >= oc->rmep_count) {           \
    212                     LOG_ERROR(BSL_LS_BCM_OAM, \
    213                               (BSL_META("OAM Error: Invalid RMEP Index"   \
    214                                " = %d.\n"), _ep_));                   \
    215                     return (BCM_E_PARAM);                               \
    216                 }                                                       \
    217             } while (0);
    218 
    219 /*
    220  * Macro:
    221  *     _BCM_OAM_KEY_PACK
    222  * Purpose:
    223  *     Pack the hash table look up key fields.
    224  * Parameters:
    225  *     _dest_ - Hash key buffer.
    226  *     _src_  - Hash key field to be packed.
    227  *     _size_ - Hash key field size in bytes.
    228  */
    229 #define _BCM_OAM_KEY_PACK(_dest_,_src_,_size_)            \
    230             do {                                          \
    231                 sal_memcpy((_dest_), (_src_), (_size_));  \
    232                 (_dest_) += (_size_);                     \
    233             } while (0)
    234 /*
    235  * Macro:
    236  *     _BCM_TR3_OAM_MOD_PORT_TO_GLP
    237  * Purpose:
    238  *     Construct hardware SGLP value from module ID, port ID and Trunk ID value.
    239  * Parameters:
    240  *     _modid_ - Module ID.
    241  *     _port_  - Port ID.
    242  *     _trunk_ - Trunk (1 - TRUE/0 - FALSE).
    243  *     _tgid_  - Trunk ID.
    244  */
    245 #define _BCM_TR3_OAM_MOD_PORT_TO_GLP(_u_, _m_, _p_, _t_, _tgid_, _glp_)     \
    246     do {                                                                    \
    247         if ((_tgid_) != -1) {                                               \
    248             (_glp_) = (((0x1 & (_t_)) << SOC_TRUNK_BIT_POS(_u_))            \
    249                 | ((soc_mem_index_count((_u_), TRUNK_GROUPm) - 1)           \
    250                 & (_tgid_)));                                               \
    251         } else {                                                            \
    252             (_glp_) = (((0x1 & (_t_)) << SOC_TRUNK_BIT_POS(_u_))            \
    253                 | ((SOC_MODID_MAX(_u_) & (_m_))                             \
    254                 << (_shr_popcount((unsigned int) SOC_PORT_ADDR_MAX(_u_)))   \
    255                 | (SOC_PORT_ADDR_MAX(_u_) & (_p_))));                       \
    256         }                                                                   \
    257         LOG_DEBUG(BSL_LS_BCM_OAM, \
    258                   (BSL_META("u:%d m:%d p:%d t:%d tgid:%d glp:%x\n"),        \
    259                    _u_, _m_, _p_, _t_, _tgid_, _glp_));                            \
    260     } while (0)
    261 
    262 /* 
    263  * LMEPm DESTf format mod_id[15:8] port_id[7:0]
    264  */
    265 #define _BCM_OAM_LMEP_DEST_MODID_SHIFT  (8)
    266 
    267 /*
    268  * Macro:
    269  *     _BCM_TR3_OAM_MOD_PORT_TO_DGLP
    270  * Purpose:
    271  *     Construct hardware DGLP value from module ID, port ID and Trunk ID value.
    272  *     Add one to MOD shift as its 8 bit port and 8 bit mod in H/w 
    273  * Parameters:
    274  *     _modid_ - Module ID.
    275  *     _port_  - Port ID.
    276  *     _trunk_ - Trunk (1 - TRUE/0 - FALSE).
    277  *     _tgid_  - Trunk ID.
    278  */
    279 #define _BCM_TR3_OAM_MOD_PORT_TO_DGLP(_u_, _m_, _p_, _t_, _tgid_, _glp_)    \
    280     do {                                                                    \
    281         if ((_tgid_) != -1) {                                               \
    282             (_glp_) = (((0x1 & (_t_)) << SOC_TRUNK_BIT_POS(_u_))            \
    283                 | ((soc_mem_index_count((_u_), TRUNK_GROUPm) - 1)           \
    284                 & (_tgid_)));                                               \
    285         } else {                                                            \
    286             (_glp_) = (((0x1 & (_t_)) << SOC_TRUNK_BIT_POS(_u_))            \
    287                 | ((SOC_MODID_MAX(_u_) & (_m_)) <<                          \
    288                 (_BCM_OAM_LMEP_DEST_MODID_SHIFT)                            \
    289                 | (SOC_PORT_ADDR_MAX(_u_) & (_p_))));                       \
    290         }                                                                   \
    291         LOG_DEBUG(BSL_LS_BCM_OAM, \
    292                   (BSL_META("u:%d m:%d p:%d t:%d tgid:%d glp:%x\n"), \
    293                    _u_, _m_, _p_, _t_, _tgid_, _glp_));                            \
    294     } while (0)
    295 
    296 /*
    297  * Macro:
    298  *     _BCM_OAM_GLP_XXX
    299  * Purpose:
    300  *     Get components of generic logical port value.
    301  * Parameters:
    302  *     _glp_ - Generic logical port.
    303  */
    304 #define _BCM_OAM_GLP_TRUNK_BIT_GET(_u_,_glp_) \
    305 	(0x1 & ((_glp_) >> SOC_TRUNK_BIT_POS(_u_)))
    306 
    307 #define _BCM_OAM_GLP_TRUNK_ID_GET(_u_,_glp_)  \
    308 	((soc_mem_index_count((_u_), TRUNK_GROUPm) - 1) & (_glp_))
    309 
    310 #define _BCM_OAM_GLP_MODULE_ID_GET(_u_,_glp_) \
    311 	(SOC_MODID_MAX(_u_)& \
    312 	((_glp_) >> _shr_popcount((unsigned int)SOC_PORT_ADDR_MAX(unit))))
    313 
    314 #define _BCM_OAM_GLP_PORT_GET(_u_,_glp_)      \
    315 	(SOC_PORT_ADDR_MAX(_u_) & (_glp_))
    316 /* To recover Module Id from H/w DGLP field */
    317 #define _BCM_OAM_DGLP_MODULE_ID_GET(_glp_) (0xFF & ((_glp_) >> \
    318             _BCM_OAM_LMEP_DEST_MODID_SHIFT))
    319 
    320 /*
    321  * Macro:
    322  *     _BCM_OAM_EP_LEVEL_XXX
    323  * Purpose:
    324  *     Maintenance domain level bit count and level max value.   
    325  * Parameters:
    326  *     _glp_ - Generic logical port.
    327  */
    328 #define _BCM_OAM_EP_LEVEL_COUNT (1 << (_BCM_OAM_EP_LEVEL_BIT_COUNT))
    329 #define _BCM_OAM_EP_LEVEL_MAX (_BCM_OAM_EP_LEVEL_COUNT - 1)
    330 
    331 /*
    332  * Macro:
    333  *     BCM_WB_XXX
    334  * Purpose:
    335  *    OAM module scache version information.
    336  * Parameters:
    337  *    (major number, minor number)
    338  */
    339 #ifdef BCM_WARM_BOOT_SUPPORT
    340 #define BCM_WB_VERSION_1_0      SOC_SCACHE_VERSION(1,0)
    341 #define BCM_WB_VERSION_1_1      SOC_SCACHE_VERSION(1,1)
    342 #define BCM_WB_VERSION_1_2      SOC_SCACHE_VERSION(1,2)
    343 #define BCM_WB_VERSION_1_3      SOC_SCACHE_VERSION(1,3)
    344 #define BCM_WB_VERSION_1_4      SOC_SCACHE_VERSION(1,4)
    345 #define BCM_WB_DEFAULT_VERSION  BCM_WB_VERSION_1_4
    346 #endif
    347 /* * * * * * * * * * * * * * * * * * * * * * * * *
    348  *         OAM function prototypes               *
    349  */
    350 #ifdef BCM_WARM_BOOT_SUPPORT
    351 STATIC int
    352 _bcm_tr3_oam_bhh_hw_config_scache_size_get (int unit);
    353 #endif
    354 
    355 /* * * * * * * * * * * * * * * * * * * * * * * * *
    356  *         OAM global data initialization      *
    357  */
    358 #if defined(BCM_TRIUMPH3_SUPPORT) && defined(INCLUDE_BHH)
    359 
    360 #define BHH_COSQ_INVALID          0xFFFF
    361 
    362 /*
    363  * Macro:
    364  *     _BCM_OAM_BHH_IS_VALID (internal)
    365  * Purpose:
    366  *     Check that the BHH feature is available on this unit
    367  * Parameters:
    368  *     unit - BCM device number
    369  * Notes:
    370  *     Results in return(BCM_E_UNAVAIL), 
    371  */
    372 #define _BCM_OAM_BHH_IS_VALID(unit)                                          \
    373             do {                                                             \
    374                 if (!soc_feature(unit, soc_feature_bhh)) {                   \
    375                     return (BCM_E_UNAVAIL);                                  \
    376                 }                                                            \
    377             } while (0)
    378 
    379 #define BCM_OAM_BHH_GET_UKERNEL_EP(ep) \
    380         (ep - _BCM_OAM_BHH_ENDPOINT_OFFSET)
    381 
    382 #define BCM_OAM_BHH_GET_SDK_EP(ep) \
    383         (ep + _BCM_OAM_BHH_ENDPOINT_OFFSET)
    384 
    385 #define BCM_OAM_BHH_VALIDATE_EP(_ep_) \
    386             do {                                                       \
    387                 if (((_ep_) < _BCM_OAM_BHH_ENDPOINT_OFFSET) ||         \
    388                     ((_ep_) >= (_BCM_OAM_BHH_ENDPOINT_OFFSET           \
    389                                          + oc->bhh_endpoint_count))) { \
    390                     LOG_ERROR(BSL_LS_BCM_OAM, \
    391                               (BSL_META("OAM Error: Invalid Endpoint ID" \
    392                                " = %d.\n"), _ep_));                  \
    393                     _BCM_OAM_UNLOCK(oc);                               \
    394                     return (BCM_E_PARAM);                              \
    395                 }                                                      \
    396             } while (0);
    397 
    398 #define BCM_OAM_BHH_ABS(x)   (((x) < 0) ? (-(x)) : (x))
    399 
    400 STATIC int
    401 _bcm_tr3_oam_bhh_session_hw_delete(int unit, _bcm_oam_hash_data_t *h_data_p);
    402 STATIC int
    403 _bcm_tr3_oam_bhh_msg_send_receive(int unit, uint8 s_subclass,
    404                                     uint16 s_len, uint32 s_data,
    405                                     uint8 r_subclass, uint16 *r_len, sal_usecs_t timeout);
    406 STATIC int
    407 _bcm_tr3_oam_bhh_hw_init(int unit);
    408 STATIC void
    409 _bcm_tr3_oam_bhh_callback_thread(void *param);
    410 STATIC int
    411 _bcm_tr3_oam_bhh_event_mask_set(int unit);
    412 STATIC int
    413 bcm_tr3_oam_bhh_endpoint_create(int unit, 
    414                                 bcm_oam_endpoint_info_t *endpoint_info,
    415                                 _bcm_oam_hash_key_t  *hash_key);
    416 STATIC int
    417 _bcm_tr3_oam_bhh_fp_init(int unit);
    418 
    419 static int tr3_oam_mpls_tp_ach_channel_type = SHR_BHH_ACH_CHANNEL_TYPE;
    420 #endif /* INCLUDE_BHH */
    421 
    422 /*
    423  * Triumph3 device OAM CCM intervals array initialization..
    424  */
    425 static uint32 _tr3_ccm_intervals[] =
    426 {
    427     BCM_OAM_ENDPOINT_CCM_PERIOD_DISABLED,
    428     BCM_OAM_ENDPOINT_CCM_PERIOD_3MS,
    429     BCM_OAM_ENDPOINT_CCM_PERIOD_10MS,
    430     BCM_OAM_ENDPOINT_CCM_PERIOD_100MS,
    431     BCM_OAM_ENDPOINT_CCM_PERIOD_1S,
    432     BCM_OAM_ENDPOINT_CCM_PERIOD_10S,
    433     BCM_OAM_ENDPOINT_CCM_PERIOD_1M,
    434     BCM_OAM_ENDPOINT_CCM_PERIOD_10M,
    435     _BCM_OAM_ENDPOINT_CCM_PERIOD_UNDEFINED
    436 };
    437 
    438 /*   
    439  * OAM hardware interrupts to software events mapping array initialization.
    440  * _tr3_oam_interrupts[] =
    441  *     {Interrupt status register, Remote MEP index field, MA index field,
    442  *          CCM_INTERRUPT_CONTROLr - Interrupt status Field,
    443  *          OAM event type}. 
    444  */
    445 static _bcm_oam_interrupt_t _tr3_oam_interrupts[] =
    446 {
    447     /* 1. Port down interrupt. */
    448     {ANY_RMEP_TLV_PORT_DOWN_STATUSr, FIRST_RMEP_INDEXf, INVALIDf,
    449         ANY_RMEP_TLV_PORT_DOWN_INT_ENABLEf,
    450         bcmOAMEventEndpointPortDown},
    451 
    452     /* 2. Port up interrupt. */
    453     {ANY_RMEP_TLV_PORT_UP_STATUSr, FIRST_RMEP_INDEXf, INVALIDf,
    454         ANY_RMEP_TLV_PORT_UP_INT_ENABLEf,
    455         bcmOAMEventEndpointPortUp},
    456 
    457     /* 3. Interface down interrupt. */
    458     {ANY_RMEP_TLV_INTERFACE_DOWN_STATUSr, FIRST_RMEP_INDEXf, INVALIDf,
    459         ANY_RMEP_TLV_INTERFACE_UP_TO_DOWN_TRANSITION_INT_ENABLEf,
    460         bcmOAMEventEndpointInterfaceDown},
    461 
    462     /* 4. Interface up interrupt. */
    463     {ANY_RMEP_TLV_INTERFACE_UP_STATUSr, FIRST_RMEP_INDEXf, INVALIDf,
    464         ANY_RMEP_TLV_INTERFACE_DOWN_TO_UP_TRANSITION_INT_ENABLEf,
    465         bcmOAMEventEndpointInterfaceUp},
    466 
    467     /* 5. Interface TLV Testing to Up interrupt. */
    468     {ANY_RMEP_TLV_INTERFACE_UP_STATUSr, FIRST_RMEP_INDEXf, INVALIDf,
    469         ANY_RMEP_TLV_INTERFACE_TESTING_TO_UP_TRANSITION_INT_ENABLEf,
    470         bcmOAMEventEndpointInterfaceTestingToUp},
    471 
    472     /* 6. Interface TLV Unknown to Up interrupt. */
    473     {ANY_RMEP_TLV_INTERFACE_UP_STATUSr, FIRST_RMEP_INDEXf, INVALIDf,
    474         ANY_RMEP_TLV_INTERFACE_UNKNOWN_TO_UP_TRANSITION_INT_ENABLEf,
    475         bcmOAMEventEndpointInterfaceUnknownToUp},
    476 
    477     /* 7. Interface TLV Dormant to Up interrupt. */
    478     {ANY_RMEP_TLV_INTERFACE_UP_STATUSr, FIRST_RMEP_INDEXf, INVALIDf,
    479         ANY_RMEP_TLV_INTERFACE_DORMANT_TO_UP_TRANSITION_INT_ENABLEf,
    480         bcmOAMEventEndpointInterfaceDormantToUp},
    481 
    482     /* 8. Interface TLV Not present to Up interrupt. */
    483     {ANY_RMEP_TLV_INTERFACE_UP_STATUSr, FIRST_RMEP_INDEXf, INVALIDf,
    484         ANY_RMEP_TLV_INTERFACE_NOTPRESENT_TO_UP_TRANSITION_INT_ENABLEf,
    485         bcmOAMEventEndpointInterfaceNotPresentToUp},
    486 
    487     /* 9. Interface Link Layer Down to Up interrupt. */
    488     {ANY_RMEP_TLV_INTERFACE_UP_STATUSr, FIRST_RMEP_INDEXf, INVALIDf,
    489         ANY_RMEP_TLV_INTERFACE_LLDOWN_TO_UP_TRANSITION_INT_ENABLEf,
    490         bcmOAMEventEndpointInterfaceLLDownToUp},
    491 
    492     /* 10. Interface up to testing transition interrupt. */
    493     {ANY_RMEP_TLV_INTERFACE_DOWN_STATUSr, FIRST_RMEP_INDEXf, INVALIDf,
    494         ANY_RMEP_TLV_INTERFACE_UP_TO_TESTING_TRANSITION_INT_ENABLEf,
    495         bcmOAMEventEndpointInterfaceTesting},
    496 
    497     /* 11. Interface up to unknown transition interrupt. */
    498     {ANY_RMEP_TLV_INTERFACE_DOWN_STATUSr, FIRST_RMEP_INDEXf, INVALIDf,
    499         ANY_RMEP_TLV_INTERFACE_UP_TO_UNKNOWN_TRANSITION_INT_ENABLEf,
    500         bcmOAMEventEndpointInterfaceUnkonwn},
    501 
    502     /* 12. Interface up to dormant transition interrupt. */
    503     {ANY_RMEP_TLV_INTERFACE_DOWN_STATUSr, FIRST_RMEP_INDEXf, INVALIDf,
    504         ANY_RMEP_TLV_INTERFACE_UP_TO_DORMANT_TRANSITION_INT_ENABLEf,
    505         bcmOAMEventEndpointInterfaceDormant},
    506 
    507     /* 13. Interface up to not present transition interrupt. */
    508     {ANY_RMEP_TLV_INTERFACE_DOWN_STATUSr, FIRST_RMEP_INDEXf, INVALIDf,
    509         ANY_RMEP_TLV_INTERFACE_UP_TO_NOTPRESENT_TRANSITION_INT_ENABLEf,
    510         bcmOAMEventEndpointInterfaceNotPresent},
    511 
    512     /* 14. Interface up to Link Layer Down transition interrupt. */
    513     {ANY_RMEP_TLV_INTERFACE_DOWN_STATUSr, FIRST_RMEP_INDEXf, INVALIDf,
    514         ANY_RMEP_TLV_INTERFACE_UP_TO_LLDOWN_TRANSITION_INT_ENABLEf,
    515         bcmOAMEventEndpointInterfaceLLDown},
    516 
    517     /* 15. Low MDL or unexpected MAID interrupt. */
    518     {XCON_CCM_DEFECT_STATUSr, INVALIDf, FIRST_MA_INDEXf,
    519         XCON_CCM_DEFECT_INT_ENABLEf,
    520         bcmOAMEventGroupCCMxcon},
    521 
    522     /*
    523      * 16. Remote MEP lookup failed or CCM interval mismatch during Remote MEP
    524      *    lookup interrupt.
    525      */
    526     {ERROR_CCM_DEFECT_STATUSr, INVALIDf, FIRST_MA_INDEXf,
    527         ERROR_CCM_DEFECT_INT_ENABLEf,
    528         bcmOAMEventGroupCCMError},
    529 
    530     /*
    531      * 17. Some Remote defect indicator interrupt - aggregated health of remote
    532      *    MEPs.
    533      */
    534     {SOME_RDI_DEFECT_STATUSr, FIRST_RMEP_INDEXf, FIRST_MA_INDEXf,
    535         SOME_RDI_DEFECT_INT_ENABLEf,
    536         bcmOAMEventGroupRemote},
    537 
    538     /* 18. Aggregate health of remote MEP state machines interrupt. */
    539     {SOME_RMEP_CCM_DEFECT_STATUSr, FIRST_RMEP_INDEXf, FIRST_MA_INDEXf,
    540         SOME_RMEP_CCM_DEFECT_INT_ENABLEf,
    541         bcmOAMEventGroupCCMTimeout},
    542 
    543     /* Invalid Interrupt - Always Last */
    544     {INVALIDr, INVALIDf, 0, bcmOAMEventCount}
    545 };
    546 
    547 /*
    548  * 0AM Group faults array initialization.
    549  */
    550 static _bcm_oam_fault_t _tr3_oam_group_faults[] =
    551 {
    552     {CURRENT_XCON_CCM_DEFECTf, STICKY_XCON_CCM_DEFECTf,
    553         BCM_OAM_GROUP_FAULT_CCM_XCON, 0x08},
    554 
    555     {CURRENT_ERROR_CCM_DEFECTf, STICKY_ERROR_CCM_DEFECTf,
    556         BCM_OAM_GROUP_FAULT_CCM_ERROR, 0x04},
    557 
    558     {CURRENT_SOME_RMEP_CCM_DEFECTf, STICKY_SOME_RMEP_CCM_DEFECTf,
    559         BCM_OAM_GROUP_FAULT_CCM_TIMEOUT, 0x02},
    560 
    561     {CURRENT_SOME_RDI_DEFECTf, STICKY_SOME_RDI_DEFECTf,
    562         BCM_OAM_GROUP_FAULT_REMOTE, 0x01},
    563 
    564     {0, 0, 0, 0}
    565 };
    566 
    567 /*
    568  * 0AM Endpoint faults array initialization.
    569  */
    570 static _bcm_oam_fault_t _tr3_oam_endpoint_faults[] =
    571 {
    572     {CURRENT_RMEP_PORT_STATUS_DEFECTf,
    573         STICKY_RMEP_PORT_STATUS_DEFECTf,
    574         BCM_OAM_ENDPOINT_FAULT_PORT_DOWN, 0x08},
    575 
    576     {CURRENT_RMEP_INTERFACE_STATUS_DEFECTf,
    577         STICKY_RMEP_INTERFACE_STATUS_DEFECTf,
    578         BCM_OAM_ENDPOINT_FAULT_INTERFACE_DOWN, 0x04},
    579 
    580     {CURRENT_RMEP_CCM_DEFECTf,
    581         STICKY_RMEP_CCM_DEFECTf,
    582         BCM_OAM_ENDPOINT_FAULT_CCM_TIMEOUT, 0x20},
    583 
    584     {CURRENT_RMEP_LAST_RDIf,
    585         STICKY_RMEP_LAST_RDIf,
    586         BCM_OAM_ENDPOINT_FAULT_REMOTE, 0x10},
    587 
    588     {0, 0, 0, 0}
    589 };
    590 
    591 typedef struct _bcm_tr3_oam_intr_en_fields_s {
    592     soc_field_t field;
    593     uint32      value;
    594 } _bcm_tr3_oam_intr_en_fields_t;
    595  
    596 static _bcm_tr3_oam_intr_en_fields_t _tr3_oam_intr_en_fields[bcmOAMEventCount] =
    597 {
    598     /*
    599      * Note:
    600      * The order of hardware field names in the below initialization
    601      * code must match the event enum order in bcm_oam_event_type_t.
    602      */
    603     { ANY_RMEP_TLV_PORT_DOWN_INT_ENABLEf, 1},
    604     { ANY_RMEP_TLV_PORT_UP_INT_ENABLEf, 1},
    605     { ANY_RMEP_TLV_INTERFACE_UP_TO_DOWN_TRANSITION_INT_ENABLEf, 1},
    606     { ANY_RMEP_TLV_INTERFACE_DOWN_TO_UP_TRANSITION_INT_ENABLEf, 1},
    607     { ANY_RMEP_TLV_INTERFACE_TESTING_TO_UP_TRANSITION_INT_ENABLEf, 1},
    608     { ANY_RMEP_TLV_INTERFACE_UNKNOWN_TO_UP_TRANSITION_INT_ENABLEf, 1},
    609     { ANY_RMEP_TLV_INTERFACE_DORMANT_TO_UP_TRANSITION_INT_ENABLEf, 1},
    610     { ANY_RMEP_TLV_INTERFACE_NOTPRESENT_TO_UP_TRANSITION_INT_ENABLEf, 1},
    611     { ANY_RMEP_TLV_INTERFACE_LLDOWN_TO_UP_TRANSITION_INT_ENABLEf, 1},
    612     { ANY_RMEP_TLV_INTERFACE_UP_TO_TESTING_TRANSITION_INT_ENABLEf, 1},
    613     { ANY_RMEP_TLV_INTERFACE_UP_TO_UNKNOWN_TRANSITION_INT_ENABLEf, 1},
    614     { ANY_RMEP_TLV_INTERFACE_UP_TO_DORMANT_TRANSITION_INT_ENABLEf, 1},
    615     { ANY_RMEP_TLV_INTERFACE_UP_TO_NOTPRESENT_TRANSITION_INT_ENABLEf, 1},
    616     { ANY_RMEP_TLV_INTERFACE_UP_TO_LLDOWN_TRANSITION_INT_ENABLEf, 1},
    617     { XCON_CCM_DEFECT_INT_ENABLEf, 1},
    618     { ERROR_CCM_DEFECT_INT_ENABLEf, 1},
    619     { SOME_RDI_DEFECT_INT_ENABLEf, 1},
    620     { SOME_RMEP_CCM_DEFECT_INT_ENABLEf, 1},
    621     { INVALIDf, 0},
    622     { INVALIDf, 0},
    623     { INVALIDf, 0},
    624     { INVALIDf, 0},
    625     { INVALIDf, 0},
    626     { INVALIDf, 0},
    627     { INVALIDf, 0},
    628     { INVALIDf, 0},
    629     { INVALIDf, 0},
    630     { INVALIDf, 0},
    631     { INVALIDf, 0},
    632     { INVALIDf, 0},
    633     { INVALIDf, 0},
    634     { INVALIDf, 0},
    635     { INVALIDf, 0},
    636     { INVALIDf, 0},
    637     { INVALIDf, 0},
    638     { INVALIDf, 0},
    639     { INVALIDf, 0},
    640     { INVALIDf, 0},
    641     { INVALIDf, 0},
    642     { INVALIDf, 0},
    643     { INVALIDf, 0},
    644     { INVALIDf, 0},
    645     { INVALIDf, 0},
    646     { INVALIDf, 0}
    647 };
    648 
    649 /* For Ethernet OAM Loss & Delay Measurement */
    650 typedef struct _bcm_oam_lm_dm_search_data_type_s {
    651     bcm_oam_endpoint_type_t match_type; /* Endpoint Type. */
    652     bcm_oam_endpoint_t  match_ep_id; /* Current Endpoint ID, being added. */
    653     bcm_vlan_t          match_vlan; /* Vlan on which the EP is added. */
    654     uint32              match_gport; /* Gport on which the EP is added. */
    655     int                 match_count; /* No. of existing matching EPs
    656                                         (exluding the current). */
    657     uint8               highest_level; /* Highest level of EP on vlan port. */
    658     bcm_oam_endpoint_t  highest_level_ep_id; /* Existing matching EP id. */
    659 } _bcm_oam_lm_dm_search_data_type_t;
    660 
    661 static _bcm_oam_lm_dm_search_data_type_t _bcm_oam_lm_dm_search_data;
    662 
    663 STATIC int _bcm_tr3_oam_loss_delay_measurement_delete(int unit, 
    664             _bcm_oam_control_t *oc, _bcm_oam_hash_data_t *hash_data);
    665 
    666             
    667 /* * * * * * * * * * * * * * * * * * * * * * * * *
    668  *            Static local functions             *
    669  */
    670 /*
    671  * Function:
    672  *     _bcm_tr3_oam_ccm_msecs_to_hw_encode
    673  * Purpose:
    674  *     Quanitze CCM interval from msecs to hardware encoding.
    675  * Parameters:
    676  *     period -  (IN) CCM interval in milli seconds.
    677  * Retruns:
    678  *     Hardware encoding for the specified CCM interval value.
    679  */
    680 STATIC int
    681 _bcm_tr3_oam_ccm_msecs_to_hw_encode(int period)
    682 {
    683     int q_period = 0; /* Quantized CCM period value. */
    684 
    685     if (0 == period) {
    686         return (q_period);
    687     }
    688 
    689     /* Find closest supported period */
    690     for (q_period = 1; _tr3_ccm_intervals[q_period]
    691             != _BCM_OAM_ENDPOINT_CCM_PERIOD_UNDEFINED; ++q_period) {
    692         if (period < _tr3_ccm_intervals[q_period]) {
    693             break;
    694         }
    695     }
    696 
    697     if (_tr3_ccm_intervals[q_period]
    698         == _BCM_OAM_ENDPOINT_CCM_PERIOD_UNDEFINED) {
    699         /* Use the highest defined value */
    700         --q_period;
    701     } else {
    702         if ((period - _tr3_ccm_intervals[q_period - 1])
    703                 < (_tr3_ccm_intervals[q_period] - period)) {
    704             /* Closer to the lower value */
    705             --q_period;
    706         }
    707     }
    708 
    709     return q_period;
    710 }
    711 
    712 #if defined(BCM_WARM_BOOT_SUPPORT)
    713 /*
    714  * Function:
    715  *     _bcm_tr3_oam_ccm_hw_encode_to_msecs
    716  * Purpose:
    717  *     Get CCM interval in msecs for a given hardware encoded value.
    718  * Parameters:
    719  *     encode -  (IN) CCM interval hardware encoding.
    720  * Retruns:
    721  *     CCM interval in msecs.
    722  */
    723 STATIC int
    724 _bcm_tr3_oam_ccm_hw_encode_to_msecs(int encode)
    725 {
    726     return (_tr3_ccm_intervals[encode]);
    727 }
    728 #endif
    729 
    730 /*
    731  * Function:
    732  *     _bcm_tr3_oam_opcode_profile_entry_set
    733  * Purpose:
    734  *     Program the OAM opcode control profile fields.
    735  * Parameters:
    736  *     unit  - (IN) BCM device number
    737  *     flags - (IN) Bitmap of opcode control settings.
    738  *     entry - (IN/OUT) Pointer to opcode control profile table entry buffer.
    739  * Retruns:
    740  *     BCM_E_XXX
    741  */
    742 STATIC int
    743 _bcm_tr3_oam_opcode_profile_entry_set(int unit,
    744                                       uint32 flags,
    745                                       uint32 *entry)
    746 {
    747     uint32 ep_opcode;        /* Endpoint opcode flag bits. */
    748     uint32 opcode_count = 0; /* Number of bits set.        */
    749     int    bp;               /* bit position.              */
    750 
    751     /* Validate opcode flag bits. */
    752     if (flags & ~(_BCM_TR3_OAM_OPCODE_MASK)) {
    753         return (BCM_E_PARAM);
    754     }
    755 
    756     /* Get number of valid opcodes supported. */
    757     opcode_count = _shr_popcount(_BCM_TR3_OAM_OPCODE_MASK);
    758 
    759     /*
    760      * Iterate over opcode flag bits and set corresponding fields
    761      * in entry buffer.
    762      */
    763     for (bp = 0; bp < opcode_count; bp++) {
    764         ep_opcode = (flags & (1 << bp));
    765 
    766         switch (ep_opcode) {
    767             case BCM_OAM_OPCODE_CCM_IN_HW:
    768                 soc_OAM_OPCODE_CONTROL_PROFILEm_field32_set(unit, entry,
    769                                                             CCM_PROCESS_IN_HWf,
    770                                                             1);
    771                 break;
    772 
    773             case BCM_OAM_OPCODE_CCM_COPY_TO_CPU:
    774                 soc_OAM_OPCODE_CONTROL_PROFILEm_field32_set(unit, entry,
    775                                                             CCM_COPYTO_CPUf, 1);
    776                 break;
    777 
    778             case BCM_OAM_OPCODE_CCM_DROP:
    779                 soc_OAM_OPCODE_CONTROL_PROFILEm_field32_set(unit, entry,
    780                                                             CCM_DROPf, 1);
    781                 break;
    782 
    783             case BCM_OAM_OPCODE_LBM_IN_HW:
    784                 soc_OAM_OPCODE_CONTROL_PROFILEm_field32_set(unit, entry,
    785                                                             LBM_UC_PROCESS_IN_HWf,
    786                                                             1);
    787                 break;
    788 
    789             case BCM_OAM_OPCODE_LBM_UC_COPY_TO_CPU:
    790                 soc_OAM_OPCODE_CONTROL_PROFILEm_field32_set(unit, entry,
    791                                                             LBM_UC_COPYTO_CPUf,
    792                                                             1);
    793                 break;
    794 
    795             case BCM_OAM_OPCODE_LBM_MC_COPY_TO_CPU:
    796                 soc_OAM_OPCODE_CONTROL_PROFILEm_field32_set(unit, entry,
    797                                                             LBM_MC_COPYTO_CPUf,
    798                                                             1);
    799                 break;
    800 
    801             case BCM_OAM_OPCODE_LBM_MC_DROP:
    802                 soc_OAM_OPCODE_CONTROL_PROFILEm_field32_set(unit, entry,
    803                                                             LBM_MC_DROPf, 1);
    804                 break;
    805 
    806             case BCM_OAM_OPCODE_LBR_COPY_TO_CPU:
    807                 soc_OAM_OPCODE_CONTROL_PROFILEm_field32_set(unit, entry,
    808                                                             LBR_COPYTO_CPUf, 1);
    809                 break;
    810 
    811             case BCM_OAM_OPCODE_LBR_DROP:
    812                 soc_OAM_OPCODE_CONTROL_PROFILEm_field32_set(unit, entry,
    813                                                             LBR_DROPf, 1);
    814                 break;
    815 
    816             case BCM_OAM_OPCODE_LTM_COPY_TO_CPU:
    817                 soc_OAM_OPCODE_CONTROL_PROFILEm_field32_set(unit, entry,
    818                                                             LTM_COPYTO_CPUf, 1);
    819                 break;
    820 
    821             case BCM_OAM_OPCODE_LTM_DROP:
    822                 soc_OAM_OPCODE_CONTROL_PROFILEm_field32_set(unit, entry,
    823                                                             LTM_DROPf, 1);
    824                 break;
    825 
    826             case BCM_OAM_OPCODE_LTR_COPY_TO_CPU:
    827                 soc_OAM_OPCODE_CONTROL_PROFILEm_field32_set(unit, entry,
    828                                                             LTR_COPYTO_CPUf, 1);
    829                 break;
    830 
    831             case BCM_OAM_OPCODE_LTR_DROP:
    832                 soc_OAM_OPCODE_CONTROL_PROFILEm_field32_set(unit, entry,
    833                                                             LTR_DROPf, 1);
    834                 break;
    835 
    836             case BCM_OAM_OPCODE_LMEP_PKT_FWD:
    837                 soc_OAM_OPCODE_CONTROL_PROFILEm_field32_set(unit, entry,
    838                                                             FWD_LMEP_PKTf, 1);
    839                 break;
    840 
    841             case BCM_OAM_OPCODE_OTHER_COPY_TO_CPU:
    842                 soc_OAM_OPCODE_CONTROL_PROFILEm_field32_set
    843                     (unit, entry, OTHER_OPCODE_COPYTO_CPUf, 1);
    844                 break;
    845 
    846             case BCM_OAM_OPCODE_OTHER_DROP:
    847                 soc_OAM_OPCODE_CONTROL_PROFILEm_field32_set(unit, entry,
    848                                                             OTHER_OPCODE_DROPf,
    849                                                             1);
    850                 break;
    851 
    852             case BCM_OAM_OPCODE_LBM_UC_DROP:
    853                 soc_OAM_OPCODE_CONTROL_PROFILEm_field32_set(unit, entry,
    854                                                             LBM_UC_DROPf, 1);
    855                 break;
    856 
    857             default:
    858                 break;
    859         }
    860     }
    861 
    862     return (BCM_E_NONE);
    863 }
    864 
    865 /*
    866  * Function:
    867  *     _bcm_tr3_oam_opcode_profile_entry_set
    868  * Purpose:
    869  *     Setup default OAM opcode control profile settings for an entry.
    870  * Parameters:
    871  *     unit  - (IN) BCM device number
    872  *     entry - (IN/OUT) Pointer to opcode control profile table entry buffer.
    873  * Retruns:
    874  *     BCM_E_XXX
    875  */
    876 int
    877 _bcm_tr3_oam_opcode_profile_entry_init(int unit,
    878                                        uint32 *entry)
    879 {
    880     uint32 opcode; /* Opcode flag bits.        */
    881     int    rv;     /* Operation return status. */
    882 
    883     opcode =  (BCM_OAM_OPCODE_CCM_COPY_TO_CPU |
    884                     BCM_OAM_OPCODE_CCM_DROP |
    885                     BCM_OAM_OPCODE_LBM_UC_COPY_TO_CPU |
    886                     BCM_OAM_OPCODE_LBM_UC_DROP |
    887                     BCM_OAM_OPCODE_LBM_MC_COPY_TO_CPU |
    888                     BCM_OAM_OPCODE_LBM_MC_DROP |
    889                     BCM_OAM_OPCODE_LBR_COPY_TO_CPU |
    890                     BCM_OAM_OPCODE_LBR_DROP |
    891                     BCM_OAM_OPCODE_LTM_COPY_TO_CPU |
    892                     BCM_OAM_OPCODE_LTM_DROP |
    893                     BCM_OAM_OPCODE_LTR_COPY_TO_CPU |
    894                     BCM_OAM_OPCODE_LTR_DROP |
    895                     BCM_OAM_OPCODE_OTHER_COPY_TO_CPU |
    896                     BCM_OAM_OPCODE_OTHER_DROP);
    897 
    898     rv = _bcm_tr3_oam_opcode_profile_entry_set(unit, opcode, entry);
    899 
    900     return (rv);
    901 }
    902 
    903 /*
    904  * Function:
    905  *     _bcm_oam_ep_hash_key_construct
    906  * Purpose:
    907  *     Construct hash table key for a given endpoint information.
    908  * Parameters:
    909  *     unit    - (IN) BCM device number
    910  *     oc      - (IN) Pointer to OAM control structure.
    911  *     ep_info - (IN) Pointer to endpoint information structure.
    912  *     key     - (IN/OUT) Pointer to hash key buffer.
    913  * Retruns:
    914  *     None
    915  */
    916 STATIC void
    917 _bcm_oam_ep_hash_key_construct(int unit,
    918                                _bcm_oam_control_t *oc,
    919                                bcm_oam_endpoint_info_t *ep_info,
    920                                _bcm_oam_hash_key_t *key)
    921 {
    922     uint8  *loc = *key;
    923     uint32 direction = 1;
    924 
    925     sal_memset(key, 0, sizeof(_bcm_oam_hash_key_t));
    926 
    927     if (NULL != ep_info) {
    928 
    929         _BCM_OAM_KEY_PACK(loc, &ep_info->group, sizeof(ep_info->group));
    930 
    931         _BCM_OAM_KEY_PACK(loc, &ep_info->name, sizeof(ep_info->name));
    932 
    933         _BCM_OAM_KEY_PACK(loc, &ep_info->gport, sizeof(ep_info->gport));
    934 
    935         _BCM_OAM_KEY_PACK(loc, &ep_info->level, sizeof(ep_info->level));
    936 
    937         _BCM_OAM_KEY_PACK(loc, &ep_info->vlan, sizeof(ep_info->vlan));
    938 
    939         _BCM_OAM_KEY_PACK(loc, &direction, sizeof(direction));
    940     }
    941 
    942     /* End address should not exceed size of _bcm_oam_hash_key_t. */
    943     assert ((int) (loc - *key) <= sizeof(_bcm_oam_hash_key_t));
    944 }
    945 
    946 #ifdef BCM_HURRICANE2_SUPPORT 
    947 /*
    948  * Function:
    949  *     _bcm_hu2_oam_lmep_key_construct
    950  * Purpose:
    951  *     Construct LMEP view lookup key for a given endpoint.
    952  * Parameters:
    953  *     unit     - (IN) BCM device number
    954  *     h_data_p - (IN) Pointer to endpoint hash data memory.
    955  *     l3_key_p - (IN/OUT) Pointer to entry buffer.
    956  * Retruns:
    957  *     None
    958  */
    959 STATIC void
    960 _bcm_hu2_oam_lmep_key_construct(int unit,
    961                                 const _bcm_oam_hash_data_t *h_data_p,
    962                                 l3_entry_ipv4_unicast_entry_t *l3_key_p)
    963 {
    964     /* Set the search key type. */
    965     soc_L3_ENTRY_IPV4_UNICASTm_field32_set
    966         (unit, l3_key_p, KEY_TYPEf, SOC_MEM_KEY_L3_ENTRY_LMEP);
    967 
    968     /* Set VLAN ID in search key. */
    969     soc_L3_ENTRY_IPV4_UNICASTm_field32_set
    970         (unit, l3_key_p, LMEP__VIDf, h_data_p->vlan);
    971 
    972 
    973     /* SGLP contains generic logical port. */
    974     soc_L3_ENTRY_IPV4_UNICASTm_field32_set
    975         (unit, l3_key_p, LMEP__SGLPf, h_data_p->sglp);
    976 
    977 }
    978 
    979 /*
    980  * Function:
    981  *     _bcm_hu2_oam_rmep_key_construct
    982  * Purpose:
    983  *     Construct RMEP view lookup key for a given endpoint.
    984  * Parameters:
    985  *     unit     - (IN) BCM device number
    986  *     h_data_p - (IN) Pointer to endpoint hash data memory.
    987  *     l3_key_p - (IN/OUT) Pointer to entry buffer.
    988  * Retruns:
    989  *     None
    990  */
    991 STATIC void
    992 _bcm_hu2_oam_rmep_key_construct(int unit,
    993                             const _bcm_oam_hash_data_t *h_data_p,
    994                             l3_entry_ipv4_unicast_entry_t *l3_key_p)
    995 {
    996 
    997     /* Set the search key type. */
    998     soc_L3_ENTRY_IPV4_UNICASTm_field32_set
    999         (unit, l3_key_p, KEY_TYPEf, SOC_MEM_KEY_L3_ENTRY_RMEP);
   1000 
   1001     /* Set endpoint name. */
   1002     soc_L3_ENTRY_IPV4_UNICASTm_field32_set
   1003         (unit, l3_key_p, RMEP__MEPIDf, h_data_p->name);
   1004 
   1005     /* Set the maintenance domain level. */
   1006     soc_L3_ENTRY_IPV4_UNICASTm_field32_set
   1007         (unit, l3_key_p, RMEP__MDLf, h_data_p->level);
   1008 
   1009     /*
   1010      * Set endpoint port on which remote device CCM packets will be received.
   1011      */
   1012      /* SGLP contains generic logical port. */
   1013     soc_L3_ENTRY_IPV4_UNICASTm_field32_set
   1014          (unit, l3_key_p, RMEP__SGLPf, h_data_p->sglp);
   1015 
   1016      /* Set VLAN ID in search key. */
   1017     soc_L3_ENTRY_IPV4_UNICASTm_field32_set
   1018             (unit, l3_key_p, RMEP__VIDf, h_data_p->vlan);
   1019 }
   1020 #endif /* BCM_HURRICANE2_SUPPORT */
   1021 
   1022 #ifdef BCM_TRIUMPH3_SUPPORT 
   1023 /*
   1024  * Function:
   1025  *     _bcm_oam_lmep_key_construct
   1026  * Purpose:
   1027  *     Construct LMEP view lookup key for a given endpoint.
   1028  * Parameters:
   1029  *     unit     - (IN) BCM device number
   1030  *     h_data_p - (IN) Pointer to endpoint hash data memory.
   1031  *     l3_key_p - (IN/OUT) Pointer to entry buffer.
   1032  * Retruns:
   1033  *     None
   1034  */
   1035 STATIC void
   1036 _bcm_oam_lmep_key_construct(int unit,
   1037                             const _bcm_oam_hash_data_t *h_data_p,
   1038                             l3_entry_1_entry_t *l3_key_p)
   1039 {
   1040     /* Set the search key type. */
   1041     soc_L3_ENTRY_1m_field32_set
   1042         (unit, l3_key_p, KEY_TYPEf, SOC_MEM_KEY_L3_ENTRY_1_LMEP_LMEP);
   1043 
   1044     /* Set VLAN ID in search key. */
   1045     soc_L3_ENTRY_1m_field32_set
   1046         (unit, l3_key_p, LMEP__VIDf, h_data_p->vlan);
   1047 
   1048     /* Set port type status in the search key. */
   1049     if (BCM_GPORT_IS_MIM_PORT(h_data_p->gport)
   1050         || BCM_GPORT_IS_MPLS_PORT(h_data_p->gport)) {
   1051 
   1052         if (h_data_p->flags & BCM_OAM_ENDPOINT_PBB_TE) {
   1053             /* SOURCE_TYPEf is '1' for virtual ports. */
   1054             soc_L3_ENTRY_1m_field32_set
   1055                 (unit, l3_key_p, LMEP__SOURCE_TYPEf, 1);
   1056         }
   1057 
   1058         /* SGLP field contains virtual port. */
   1059         soc_L3_ENTRY_1m_field32_set
   1060             (unit, l3_key_p, LMEP__SGLPf, h_data_p->vp);
   1061 
   1062     } else {
   1063 
   1064         /* SGLP contains generic logical port. */
   1065         soc_L3_ENTRY_1m_field32_set
   1066             (unit, l3_key_p, LMEP__SGLPf, h_data_p->sglp);
   1067 
   1068         /* SGLP field contains generic logical port value. */
   1069         soc_L3_ENTRY_1m_field32_set
   1070                 (unit, l3_key_p, LMEP__SOURCE_TYPEf, 0);
   1071     }
   1072 }
   1073 
   1074 /*
   1075  * Function:
   1076  *     _bcm_oam_rmep_key_construct
   1077  * Purpose:
   1078  *     Construct RMEP view lookup key for a given endpoint.
   1079  * Parameters:
   1080  *     unit     - (IN) BCM device number
   1081  *     h_data_p - (IN) Pointer to endpoint hash data memory.
   1082  *     l3_key_p - (IN/OUT) Pointer to entry buffer.
   1083  * Retruns:
   1084  *     None
   1085  */
   1086 STATIC void
   1087 _bcm_oam_rmep_key_construct(int unit,
   1088                             const _bcm_oam_hash_data_t *h_data_p,
   1089                             l3_entry_1_entry_t *l3_key_p)
   1090 {
   1091 
   1092     /* Set the search key type. */
   1093     soc_L3_ENTRY_1m_field32_set
   1094         (unit, l3_key_p, KEY_TYPEf, SOC_MEM_KEY_L3_ENTRY_1_RMEP_RMEP);
   1095 
   1096     /* Set endpoint name. */
   1097     soc_L3_ENTRY_1m_field32_set
   1098         (unit, l3_key_p, RMEP__MEPIDf, h_data_p->name);
   1099 
   1100     /* Set the maintenance domain level. */
   1101     soc_L3_ENTRY_1m_field32_set
   1102         (unit, l3_key_p, RMEP__MDLf, h_data_p->level);
   1103 
   1104     /*
   1105      * Set endpoint port on which remote device CCM packets will be received.
   1106      * Port value could be SVP or SGLP.
   1107      */
   1108     if (BCM_GPORT_IS_MIM_PORT(h_data_p->gport)
   1109         || BCM_GPORT_IS_MPLS_PORT(h_data_p->gport)) {
   1110 
   1111         if (h_data_p->flags & BCM_OAM_ENDPOINT_PBB_TE) {
   1112             soc_L3_ENTRY_1m_field32_set
   1113                 (unit, l3_key_p, RMEP__SOURCE_TYPEf, 1);
   1114         }
   1115 
   1116         /* SGLP contains virtual port. */
   1117         soc_L3_ENTRY_1m_field32_set
   1118             (unit, l3_key_p, RMEP__SGLPf, h_data_p->vp);
   1119 
   1120         /* Set VLAN ID in search key. */
   1121         soc_L3_ENTRY_1m_field32_set
   1122             (unit, l3_key_p, RMEP__VIDf, 0);
   1123     } else {
   1124 
   1125         /* SGLP contains generic logical port. */
   1126         soc_L3_ENTRY_1m_field32_set
   1127             (unit, l3_key_p, RMEP__SGLPf, h_data_p->sglp);
   1128 
   1129         /* Set VLAN ID in search key. */
   1130         soc_L3_ENTRY_1m_field32_set
   1131             (unit, l3_key_p, RMEP__VIDf, h_data_p->vlan);
   1132     }
   1133 }
   1134 #endif /* BCM_TRIUMPH3_SUPPORT */
   1135 
   1136 #if defined(KEY_PRINT)
   1137 /*
   1138  * Function:
   1139  *     _bcm_oam_hash_key_print
   1140  * Purpose:
   1141  *     Print the contents of a hash key buffer. 
   1142  * Parameters:
   1143  *     hash_key - (IN) Pointer to hash key buffer.
   1144  * Retruns:
   1145  *     None
   1146  */
   1147 STATIC void
   1148 _bcm_oam_hash_key_print(_bcm_oam_hash_key_t *hash_key)
   1149 {
   1150     int i;
   1151     LOG_CLI((BSL_META_U(unit,
   1152                         "HASH KEY:")));
   1153     for(i = 0; i < _OAM_HASH_KEY_SIZE; i++) {
   1154         LOG_CLI((BSL_META_U(unit,
   1155                             ":%u"), *(hash_key[i])));
   1156     }
   1157     LOG_CLI((BSL_META_U(unit,
   1158                         "\n")));
   1159 }
   1160 #endif
   1161 
   1162 /*
   1163  * Function:
   1164  *     _bcm_oam_control_get
   1165  * Purpose:
   1166  *     Lookup a OAM control config from a bcm device id.
   1167  * Parameters:
   1168  *     unit -  (IN)BCM unit number.
   1169  *     oc   -  (OUT) OAM control structure.
   1170  * Retruns:
   1171  *     BCM_E_XXX
   1172  */
   1173 STATIC int
   1174 _bcm_oam_control_get(int unit, _bcm_oam_control_t **oc)
   1175 {
   1176     if (NULL == oc) {
   1177         return (BCM_E_PARAM);
   1178     }
   1179 
   1180     /* Ensure oam module is initialized. */
   1181     _BCM_OAM_IS_INIT(unit);
   1182 
   1183     *oc = _oam_control[unit];
   1184 
   1185     return (BCM_E_NONE);
   1186 }
   1187 
   1188 /*
   1189  * Function:
   1190  *     _bcm_oam_group_endpoint_count_init
   1191  * Purpose:
   1192  *     Retrieves and initializes endpoint count information for this device.
   1193  * Parameters:
   1194  *     unit -  (IN) BCM unit number.
   1195  *     oc   -  (IN) Pointer to device OAM control structure.
   1196  * Retruns:
   1197  *     BCM_E_XXX
   1198  */
   1199 STATIC int
   1200 _bcm_oam_group_endpoint_count_init(int unit, _bcm_oam_control_t *oc)
   1201 {
   1202     /* Input parameter check. */
   1203     if (NULL == oc) {
   1204         return (BCM_E_PARAM);
   1205     }
   1206 
   1207     /*
   1208      * Get endpoint hardware table index count values and
   1209      * initialize device OAM control structure members variables.
   1210      */
   1211     oc->rmep_count = soc_mem_index_count(unit, RMEPm);
   1212     oc->lmep_count = soc_mem_index_count(unit, LMEPm);
   1213     oc->ma_idx_count = soc_mem_index_count(unit, MA_INDEXm);
   1214 
   1215     /* Max number of endpoints supported by the device. */
   1216     oc->ep_count = (oc->rmep_count + oc->lmep_count + oc->ma_idx_count);
   1217 
   1218     LOG_DEBUG(BSL_LS_BCM_OAM,
   1219               (BSL_META_U(unit,
   1220                           "OAM Info: Total No. endpoint Count = %d.\n"),
   1221                oc->ep_count));
   1222 
   1223     /* Max number of MA Groups supported by device. */
   1224     oc->group_count = soc_mem_index_count(unit, MA_STATEm);
   1225     LOG_DEBUG(BSL_LS_BCM_OAM,
   1226               (BSL_META_U(unit,
   1227                           "OAM Info: Total No. Group Count = %d.\n"),
   1228                oc->group_count));
   1229 
   1230     return (BCM_E_NONE);
   1231 }
   1232 
   1233 #ifdef BCM_HURRICANE2_SUPPORT
   1234 /*
   1235  * Function:
   1236  *     _bcm_hu2_oam_ccm_rx_timeout_enable
   1237  * Purpose:
   1238  *     Enable CCM Timer operations for endpoint state table.
   1239  * Parameters:
   1240  *     unit -  (IN) BCM unit number.
   1241  *     state - () Enable/Disable.
   1242  * Retruns:
   1243  *     BCM_E_XXX
   1244  * Note:
   1245  *     RMEP_MA_STATE_REFRESH_INDEXr - CPU access for debug only.
   1246  */
   1247 STATIC int
   1248 _bcm_hu2_oam_ccm_rx_timeout_set(int unit, uint8 state)
   1249 {
   1250     int     rv;       /* Opreation return status.   */
   1251     uint32  rval = 0; /* Register value.            */
   1252 
   1253     BCM_IF_ERROR_RETURN(READ_IARB_OAM_REFRESH_CONTROLr(unit, &rval));
   1254     
   1255     soc_reg_field_set(unit, IARB_OAM_REFRESH_CONTROLr, &rval,
   1256         REFRESH_ENABLEf, state ? 1 : 0);
   1257 
   1258     rv = WRITE_IARB_OAM_REFRESH_CONTROLr(unit, rval);
   1259 
   1260     return (rv);
   1261 }
   1262 #endif /* BCM_HURRICANE2_SUPPORT */
   1263 
   1264 /*
   1265  * Function:
   1266  *     _bcm_oam_ccm_rx_timeout_enable
   1267  * Purpose:
   1268  *     Enable CCM Timer operations for endpoint state table.
   1269  * Parameters:
   1270  *     unit -  (IN) BCM unit number.
   1271  *     state - () Enable/Disable.
   1272  * Retruns:
   1273  *     BCM_E_XXX
   1274  * Note:
   1275  *     RMEP_MA_STATE_REFRESH_INDEXr - CPU access for debug only.
   1276  */
   1277 STATIC int
   1278 _bcm_oam_ccm_rx_timeout_set(int unit, uint8 state)
   1279 {
   1280     int     rv;       /* Opreation return status.   */
   1281     uint32  rval = 0; /* Register value.            */
   1282 
   1283     /* Enable timer instructions to RMEP/MA_STATE Table. */
   1284     soc_reg_field_set(unit, OAM_TIMER_CONTROLr, &rval,
   1285                       TIMER_ENABLEf, state ? 1 : 0);
   1286 
   1287     /* Set Clock granularity to 250us ticks - 1. */
   1288     soc_reg_field_set(unit, OAM_TIMER_CONTROLr, &rval,
   1289                       CLK_GRANf, 1);
   1290 
   1291     rv = WRITE_OAM_TIMER_CONTROLr(unit, rval);
   1292     if (BCM_FAILURE(rv)) {
   1293         LOG_ERROR(BSL_LS_BCM_OAM,
   1294                   (BSL_META_U(unit,
   1295                               "OAM Error: Timer enable - Failed.\n")));
   1296         return (rv);
   1297     }
   1298 
   1299     BCM_IF_ERROR_RETURN(READ_AUX_ARB_CONTROL_2r(unit, &rval));
   1300     
   1301     soc_reg_field_set(unit, AUX_ARB_CONTROL_2r, &rval,
   1302         OAM_REFRESH_ENABLEf, state ? 1 : 0);
   1303 
   1304     BCM_IF_ERROR_RETURN(WRITE_AUX_ARB_CONTROL_2r(unit, rval));
   1305 
   1306     return (rv);
   1307 }
   1308 
   1309 /*
   1310  * Function:
   1311  *     _bcm_oam_ccm_tx_config_enable
   1312  * Purpose:
   1313  *     Enable transmission of OAM PDUs on local endpoint.
   1314  * Parameters:
   1315  *     unit -  (IN) BCM unit number.
   1316  *     state - (IN) Enable/Disable
   1317  * Retruns:
   1318  *     BCM_E_XXX
   1319  */
   1320 STATIC int
   1321 _bcm_oam_ccm_tx_config_set(int unit, uint8 state)
   1322 {
   1323     int     rv;       /* Opreation return status.   */
   1324     uint32  rval = 0; /* Register value.            */
   1325 
   1326     /* Enable OAM LMEP Tx. */
   1327     soc_reg_field_set(unit, OAM_TX_CONTROLr, &rval,
   1328                       TX_ENABLEf, state ? 1 : 0);
   1329 
   1330     /* Enable CMIC buffer. */
   1331     soc_reg_field_set(unit, OAM_TX_CONTROLr, &rval,
   1332                       CMIC_BUF_ENABLEf, state ? 1 : 0);
   1333 
   1334     rv = WRITE_OAM_TX_CONTROLr(unit, rval);
   1335     if (BCM_FAILURE(rv)) {
   1336         LOG_ERROR(BSL_LS_BCM_OAM,
   1337                   (BSL_META_U(unit,
   1338                               "OAM Error: Tx config enable - Failed.\n")));
   1339     }
   1340     return (rv);
   1341 }
   1342 
   1343 /*
   1344  * Function:
   1345  *     _bcm_oam_misc_config
   1346  * Purpose:
   1347  *     Miscellaneous OAM configurations:
   1348  *         1. Disable L2 learning for OAM MAC address.
   1349  *         2. Enable flooding of mcast packets on the vlan.
   1350  *         3. Enable IFP lookup on the CPU port. 
   1351  * Parameters:
   1352  *     unit -  (IN) BCM unit number.
   1353  * Retruns:
   1354  *     BCM_E_XXX
   1355  */
   1356 STATIC int
   1357 _bcm_oam_misc_config(int unit)
   1358 {
   1359     int     rv;       /* Opreation return status.   */
   1360     uint32  rval = 0; /* Register value.            */
   1361 
   1362     /* Disable L2 learning of OAM packets. */
   1363     soc_reg_field_set(unit, LMEP_COMMONr, &rval,
   1364                       L3f, 1);
   1365 
   1366     /* PFM 0: Flood MCAST packets on the vlan. */
   1367     soc_reg_field_set(unit, LMEP_COMMONr, &rval,
   1368                       PFMf, 0);
   1369 
   1370     rv = WRITE_LMEP_COMMONr(unit, rval);
   1371     if (BCM_FAILURE(rv)) {
   1372         LOG_ERROR(BSL_LS_BCM_OAM,
   1373                   (BSL_META_U(unit,
   1374                               "OAM Error: Misc config - Failed.\n")));
   1375         return (rv);
   1376     }
   1377 
   1378     /*
   1379      * Enable ingress FP for CPU port so LM/DM packets sent from CPU
   1380      * can be processed.
   1381      */
   1382     rv = bcm_esw_port_control_set(unit, CMIC_PORT(unit),
   1383                                   bcmPortControlFilterIngress, 1);
   1384     if (BCM_FAILURE(rv)) {
   1385         LOG_ERROR(BSL_LS_BCM_OAM,
   1386                   (BSL_META_U(unit,
   1387                               "OAM Error: bcm_esw_port_control_set"
   1388                                " - Failed.\n")));
   1389         return (rv);
   1390     }
   1391     return (rv);
   1392 
   1393 }
   1394 
   1395 /*
   1396  * Function:
   1397  *     _bcm_oam_profile_tables_init
   1398  * Purpose:
   1399  *     Create ingress service priority mapping profile table and setup a
   1400  *     default profile. Create OAM opcode control profile table. 
   1401  * Parameters:
   1402  *     unit -  (IN) BCM unit number.
   1403  *     oc   -  (IN) Pointer to OAM control structure.
   1404  * Retruns:
   1405  *     BCM_E_XXX
   1406  */
   1407 STATIC int
   1408 _bcm_oam_profile_tables_init(int unit, _bcm_oam_control_t *oc)
   1409 {
   1410     int         rv;            /* Opreation return status.    */
   1411     soc_mem_t   mem;           /* Profiled table memory.      */
   1412     int         entry_words;   /* Profile table word size.    */
   1413     int         pri;           /* Priority                    */
   1414     void        *entries[1];   /* Profile entry. */
   1415     uint32      profile_index; /* Profile table index. */
   1416     ing_service_pri_map_entry_t pri_ent[BCM_OAM_INTPRI_MAX]; /* profile */
   1417                                                              /* entry */
   1418 
   1419     /* Ingress Service Priority Map profile table initialization. */
   1420     soc_profile_mem_t_init(&oc->ing_service_pri_map);
   1421 
   1422     entry_words = (sizeof(ing_service_pri_map_entry_t) / sizeof(uint32));
   1423 
   1424     mem = ING_SERVICE_PRI_MAPm;
   1425     rv = soc_profile_mem_create(unit, &mem, &entry_words, 1,
   1426                                 &oc->ing_service_pri_map);
   1427     if (BCM_FAILURE(rv)) {
   1428         LOG_ERROR(BSL_LS_BCM_OAM,
   1429                   (BSL_META_U(unit,
   1430                               "OAM Error: service map profile - Failed.\n")));
   1431         return (rv);
   1432     }
   1433 
   1434     /*
   1435      * Initialize ingress priority map profile table.
   1436      * All priorities priorities map to priority:'0'.
   1437      */
   1438     for (pri = 0; pri < BCM_OAM_INTPRI_MAX; pri++)
   1439     {
   1440         /* Clear ingress service pri map profile entry. */
   1441         sal_memcpy(&pri_ent[pri], soc_mem_entry_null(unit, mem),
   1442                    soc_mem_entry_words(unit, mem) * sizeof(uint32));
   1443 
   1444         if (SOC_MEM_FIELD_VALID(unit, mem, OFFSET_VALIDf)) {
   1445             soc_mem_field32_set(unit, mem, &pri_ent[pri], OFFSET_VALIDf, 1);
   1446         }
   1447     }
   1448 
   1449     
   1450     entries[0] = &pri_ent;
   1451     rv = soc_profile_mem_add(unit, &oc->ing_service_pri_map,
   1452                              (void *) &entries, BCM_OAM_INTPRI_MAX,
   1453                              &profile_index);
   1454     if (BCM_FAILURE(rv)) {
   1455         LOG_ERROR(BSL_LS_BCM_OAM,
   1456                   (BSL_META_U(unit,
   1457                               "OAM Error: service map init - Failed.\n")));
   1458         return (rv);
   1459     }
   1460 
   1461     /* OAM Opcode Control profile table initialization. */
   1462     soc_profile_mem_t_init(&oc->oam_opcode_control_profile);
   1463 
   1464     entry_words = sizeof(oam_opcode_control_profile_entry_t)
   1465                          / sizeof(uint32);
   1466 
   1467     mem = OAM_OPCODE_CONTROL_PROFILEm;
   1468     rv = soc_profile_mem_create(unit, &mem, &entry_words, 1,
   1469                                 &oc->oam_opcode_control_profile);
   1470     if (BCM_FAILURE(rv)) {
   1471         LOG_ERROR(BSL_LS_BCM_OAM,
   1472                   (BSL_META_U(unit,
   1473                               "OAM Error: opcode control profile - Failed.\n")));
   1474         return (rv);
   1475     }
   1476 
   1477     return (rv);
   1478 }
   1479 
   1480 /*
   1481  * Function:
   1482  *     _bcm_tr3_oam_control_free
   1483  * Purpose:
   1484  *     Free OAM control structure resources allocated by this unit.
   1485  * Parameters:
   1486  *     unit -  (IN) BCM unit number.
   1487  *     oc   -  (IN) Pointer to OAM control structure.
   1488  * Retruns:
   1489  *     BCM_E_XXX
   1490  */
   1491 STATIC int
   1492 _bcm_tr3_oam_control_free(int unit, _bcm_oam_control_t *oc)
   1493 {
   1494     int status = 0;
   1495 
   1496     _oam_control[unit] = NULL;
   1497 
   1498     if (NULL == oc) {
   1499         /* Module already un-initialized. */
   1500         return (BCM_E_NONE);
   1501     }
   1502 
   1503     /* Free protection mutex. */
   1504     if (NULL != oc->oc_lock) {
   1505         sal_mutex_destroy(oc->oc_lock);
   1506     }
   1507 
   1508     /* Free hash data storage memory. */
   1509     if (NULL != oc->oam_hash_data) {
   1510         sal_free(oc->oam_hash_data);
   1511     }
   1512 
   1513     /* Destory endpoint hash table. */
   1514     if (NULL != oc->ma_mep_htbl) {
   1515         status = shr_htb_destroy(&oc->ma_mep_htbl, NULL);
   1516         if (BCM_FAILURE(status)) {
   1517             LOG_ERROR(BSL_LS_BCM_OAM,
   1518                       (BSL_META_U(unit,
   1519                                   "Freeing ma_mep_htbl failed\n")));
   1520         }
   1521     }
   1522 
   1523     /* Destory group indices list. */
   1524     if (NULL != oc->group_pool) {
   1525         shr_idxres_list_destroy(oc->group_pool);
   1526         oc->group_pool = NULL;
   1527     }
   1528 
   1529     /* Destroy endpoint indices list. */
   1530     if (NULL != oc->mep_pool) {
   1531         shr_idxres_list_destroy(oc->mep_pool);
   1532         oc->mep_pool = NULL;
   1533     }
   1534 
   1535     /* Destroy local endpoint indices list. */
   1536     if (NULL != oc->lmep_pool) {
   1537         shr_idxres_list_destroy(oc->lmep_pool);
   1538         oc->lmep_pool = NULL;
   1539     }
   1540 
   1541     /* Destroy remote endpoint indices list. */
   1542     if (NULL != oc->rmep_pool) {
   1543         shr_idxres_list_destroy(oc->rmep_pool);
   1544         oc->rmep_pool = NULL;
   1545     }
   1546 
   1547     /* Destroy group indices list. */
   1548     if (NULL != oc->ma_idx_pool) {
   1549         shr_idxres_list_destroy(oc->ma_idx_pool);
   1550         oc->ma_idx_pool = NULL;
   1551     }
   1552 
   1553     /* Destroy lm counter indices list. */
   1554     if (NULL != oc->lm_counter_pool) {
   1555         shr_idxres_list_destroy(oc->lm_counter_pool);
   1556         oc->lm_counter_pool = NULL;
   1557     }
   1558 
   1559     if (soc_feature(unit, soc_feature_bhh)) {
   1560 #if defined(BCM_TRIUMPH3_SUPPORT) && defined(INCLUDE_BHH)
   1561         /* Destroy bhh indices list. */
   1562         if (NULL != oc->bhh_pool) {
   1563             shr_idxres_list_destroy(oc->bhh_pool);
   1564             oc->bhh_pool = NULL;
   1565         }
   1566         if (NULL != oc->dma_buffer){
   1567             soc_cm_sfree(oc->unit, oc->dma_buffer);
   1568             oc->dma_buffer = NULL;
   1569         }
   1570         if (NULL != oc->dmabuf_reply){
   1571             soc_cm_sfree(oc->unit, oc->dmabuf_reply);
   1572             oc->dmabuf_reply = NULL;
   1573         }
   1574 #endif
   1575     }
   1576 
   1577     /* Free group memory. */
   1578     if (NULL != oc->group_info) {
   1579         sal_free(oc->group_info);
   1580     }
   1581 
   1582     /* Free RMEP H/w to logical index mapping memory. */
   1583     if (NULL != oc->remote_endpoints) {
   1584         sal_free(oc->remote_endpoints);
   1585     }
   1586 
   1587     /* Destroy ingress serivce priority mapping profile. */
   1588     if (NULL != oc->ing_service_pri_map.tables) {
   1589         soc_profile_mem_destroy(unit, &oc->ing_service_pri_map);
   1590     }
   1591 
   1592     /* Destroy OAM opcode control profile. */
   1593     if (NULL != oc->oam_opcode_control_profile.tables) {
   1594         soc_profile_mem_destroy(unit, &oc->oam_opcode_control_profile);
   1595     }
   1596 
   1597     /* Free OAM control structure memory. */
   1598     sal_free(oc);
   1599     oc = NULL;
   1600 
   1601     return (BCM_E_NONE);
   1602 }
   1603 
   1604 /*
   1605  * Function:
   1606  *     _bcm_tr3_oam_handle_interrupt
   1607  * Purpose:
   1608  *     Process OAM interrupts generated by endpoints.
   1609  * Parameters:
   1610  *     unit  -  (IN) BCM unit number.
   1611  *     field -  (IN) fault field.
   1612  * Retruns:
   1613  *     BCM_E_XXX
   1614  */
   1615 STATIC int
   1616 _bcm_tr3_oam_handle_interrupt(int unit, soc_field_t field)
   1617 {
   1618     _bcm_oam_interrupt_t *intr;             /* OAM interrupt.                */
   1619     _bcm_oam_control_t   *oc;               /* OAM control structure.        */
   1620     uint32               intr_rval;         /* Interrupt register value.     */
   1621     uint32               intr_cur_status;   /* Interrupt status.             */
   1622     uint32               flags;             /* Interrupt flags.              */
   1623     bcm_oam_group_t      grp_index;         /* MA group index.               */
   1624     bcm_oam_endpoint_t   remote_ep_index;   /* Remote Endpoint index.        */
   1625     int                  intr_multi;        /* Event occured multiple times. */
   1626     int                  intr_count;        /* No. of times event detected.  */
   1627     int                  rv;                /* Operation return status       */
   1628     _bcm_oam_event_handler_t *e_handler;    /* Pointer to Event handler.     */
   1629     int                  ep_index_mask;     /* Mask the EP Index read from intr 
   1630                                                status reg, based on table sz */ 
   1631 
   1632 
   1633     /* Get OAM control structure. */
   1634     BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc));
   1635 
   1636     _BCM_OAM_LOCK(oc);
   1637 
   1638     /* Loop through the supported interrupts for this device. */
   1639     for (intr = _tr3_oam_interrupts; intr->status_register != INVALIDr;
   1640          intr++) {
   1641 
   1642         rv = soc_reg32_get(unit, intr->status_register,
   1643                            REG_PORT_ANY, 0, &intr_rval);
   1644         if (BCM_FAILURE(rv)) {
   1645             
   1646             continue;
   1647         }
   1648 
   1649         rv = soc_reg32_set(unit, intr->status_register,
   1650                            REG_PORT_ANY, 0, 0);
   1651         if (BCM_FAILURE(rv)) {
   1652             continue;
   1653         }
   1654 
   1655         /* Get  status of interrupt from hardware. */
   1656         intr_cur_status = soc_reg_field_get(unit, intr->status_register,
   1657                                             intr_rval, VALIDf);
   1658         if (0 == intr_cur_status) {
   1659             /* This interrupt event is not valid, so continue. */
   1660             continue;
   1661         }
   1662 
   1663         /* Get this interrupt event counter value. */
   1664         intr_count = oc->event_handler_cnt[intr->event_type];
   1665 
   1666         /* Check if the interrupt is set. */
   1667         if ((1 == intr_cur_status) && (intr_count > 0)) {
   1668             flags = 0;
   1669 
   1670             /* Get MA group index for this interrupt. */
   1671             if (INVALIDf != intr->group_index_field ) {
   1672                 grp_index = soc_reg_field_get(unit, intr->status_register,
   1673                                               intr_rval,
   1674                                               intr->group_index_field);
   1675             } else {
   1676                 /* Group not valid for this interrupt. */
   1677                 grp_index = BCM_OAM_GROUP_INVALID;
   1678             }
   1679 
   1680             /* Get H/w index of RMEP for this interrupt. */
   1681             if (INVALIDf != intr->endpoint_index_field ) {
   1682                 remote_ep_index = soc_reg_field_get(unit, intr->status_register,
   1683                                               intr_rval,
   1684                                               intr->endpoint_index_field);
   1685 
   1686                 /* For Apollo2, MSB(13) of the endpoint index is not applicable 
   1687                    hence recommended to mask out the same */
   1688                 ep_index_mask = soc_mem_index_max(unit, RMEPm);
   1689                 remote_ep_index &= ep_index_mask;
   1690 
   1691                 /* Get Logical index from H/w index for this RMEP. */
   1692                 remote_ep_index = oc->remote_endpoints[remote_ep_index];
   1693             } else {
   1694                 /* Endpoint not valid for this interrupt. */
   1695                 remote_ep_index = BCM_OAM_ENDPOINT_INVALID;
   1696             }
   1697 
   1698             /* Get interrupt MULTIf status. */
   1699             intr_multi = soc_reg_field_get(unit, intr->status_register,
   1700                                            intr_rval, MULTIf);
   1701             if (1 == intr_multi) {
   1702                 /*
   1703                  * Interrupt event asserted more than once.
   1704                  * Set flags status bit to indicate event multiple occurance.
   1705                  */
   1706                 flags |= BCM_OAM_EVENT_FLAGS_MULTIPLE;
   1707             }
   1708 
   1709             /* Check and call all the handlers registerd for this event. */
   1710             for (e_handler = oc->event_handler_list_p; e_handler != NULL;
   1711                  e_handler = e_handler->next_p) {
   1712 
   1713                 /* Check if an event handler is register for this event type. */
   1714                 if (SHR_BITGET(e_handler->event_types.w, intr->event_type)) {
   1715 
   1716                     /* Call the event handler with the call back parameters. */
   1717                     e_handler->cb(unit, flags, intr->event_type, grp_index,
   1718                                       remote_ep_index, e_handler->user_data);
   1719                 }
   1720             }
   1721         }
   1722     }
   1723 
   1724     _BCM_OAM_UNLOCK(oc);
   1725 
   1726     return (BCM_E_NONE);
   1727 }
   1728 
   1729 /*
   1730  * Function:
   1731  *     _bcm_tr3_oam_events_unregister
   1732  * Purpose:
   1733  *     Unregister all OAM events for this unit.
   1734  * Parameters:
   1735  *     unit -  (IN) BCM unit number.
   1736  *     oc   -  (IN) Pointer to OAM control structure.
   1737  * Retruns:
   1738  *     BCM_E_NONE
   1739  */
   1740 STATIC int
   1741 _bcm_tr3_oam_events_unregister(int unit, _bcm_oam_control_t *oc)
   1742 {
   1743     _bcm_oam_event_handler_t *e_handler; /* Pointer to event handler list. */
   1744     _bcm_oam_event_handler_t *e_delete;  /* Event handler to be freed.     */
   1745 
   1746     /* Control lock taken by the calling routine. */
   1747 
   1748     e_handler = oc->event_handler_list_p;
   1749 
   1750     while (e_handler != NULL) {
   1751         e_delete = e_handler;
   1752         e_handler = e_handler->next_p;
   1753         sal_free(e_delete);
   1754     }
   1755 
   1756     oc->event_handler_list_p = NULL;
   1757 
   1758     return (BCM_E_NONE);
   1759 }
   1760 
   1761 
   1762 /*
   1763  * Function:
   1764  *     _bcm_tr3_oam_clear_rmep
   1765  * Purpose:
   1766  *     Delete RMEP entry or Install fresh RMEP entry in the Hardware, clearing 
   1767  *     the faults.
   1768  *      
   1769  * Parameters:
   1770  *     unit       - (IN) BCM device number
   1771  *     h_data_p   - (IN) Pointer to Endpoint info associated with RMEP entry 
   1772  *                       being cleared. 
   1773  *     valid      - (IN) 0 => Delete the H/w entry
   1774  *                       1 => Install fresh entry with faults cleared.
   1775  * Returns:
   1776  *     BCM_E_XXX
   1777  */
   1778 STATIC int
   1779 _bcm_tr3_oam_clear_rmep (int unit, _bcm_oam_hash_data_t *h_data_p, int valid)
   1780 {
   1781 
   1782     rmep_entry_t       rmep_entry;          /* RMEP table entry.              */
   1783     int                rv = BCM_E_INTERNAL; /* Operation return status entry  */
   1784     uint32             oam_cur_time;    /* Current time in H/w state machine  */
   1785 
   1786     LOG_VERBOSE(BSL_LS_BCM_OAM,
   1787                 (BSL_META_U(unit,
   1788                             "OAM, EP id %d, valid %d\n"), 
   1789                  h_data_p->remote_index, valid));
   1790     
   1791     if (h_data_p == NULL) {
   1792         LOG_ERROR(BSL_LS_BCM_OAM,
   1793                   (BSL_META_U(unit,
   1794                               "OAM ERR: Arg h_data_p NULL check failed\n")));
   1795         return BCM_E_INTERNAL;
   1796     }
   1797 
   1798     /* RMEP table programming. */
   1799     sal_memset(&rmep_entry, 0, sizeof(rmep_entry_t));
   1800 
   1801     /* if valid==0 delete RMEP entry, else create a clean RMEP entry */
   1802     if (!(valid)) {
   1803         rv = WRITE_RMEPm(unit, MEM_BLOCK_ALL, h_data_p->remote_index,
   1804                          &rmep_entry);
   1805         if (rv != BCM_E_NONE) {
   1806             LOG_ERROR(BSL_LS_BCM_OAM,
   1807                       (BSL_META_U(unit,
   1808                                   "OAM ERR: Deleting RMEP entry failied\n")));
   1809         }
   1810         return (rv);
   1811     }
   1812 
   1813     /* Set the MA group index. */
   1814     soc_RMEPm_field32_set(unit, &rmep_entry, MAID_INDEXf, 
   1815                           h_data_p->group_index);
   1816 
   1817     /*
   1818      * The following steps are necessary to enable CCM timeout events
   1819      * without having received any CCMs.
   1820      */
   1821     soc_RMEPm_field32_set(unit, &rmep_entry, RMEP_TIMESTAMP_VALIDf, 1);
   1822 
   1823     BCM_IF_ERROR_RETURN(READ_OAM_CURRENT_TIMEr(unit, &oam_cur_time));
   1824 
   1825     soc_RMEPm_field32_set(unit, &rmep_entry, RMEP_TIMESTAMPf, oam_cur_time);
   1826 
   1827     soc_RMEPm_field32_set(unit, &rmep_entry, RMEP_RECEIVED_CCMf,
   1828                          _bcm_tr3_oam_ccm_msecs_to_hw_encode(h_data_p->period));
   1829     /* End of timeout setup */
   1830 
   1831 
   1832     soc_RMEPm_field32_set(unit, &rmep_entry, VALIDf, 1);
   1833 
   1834     rv = WRITE_RMEPm(unit, MEM_BLOCK_ALL, h_data_p->remote_index,
   1835                      &rmep_entry);
   1836     if (rv != BCM_E_NONE) {
   1837         LOG_ERROR(BSL_LS_BCM_OAM,
   1838                   (BSL_META_U(unit,
   1839                               "OAM ERR: Clearing RMEP entry failied\n")));
   1840         return (rv);
   1841     }
   1842 
   1843     return BCM_E_NONE;
   1844 }
   1845 
   1846 
   1847 /*
   1848  * Function:
   1849  *     _bcm_tr3_oam_clear_ma_state
   1850  * Purpose:
   1851  *     Delete MA_STATE entry or Install fresh MA_STATE entry in the Hardware, 
   1852  *     Clearing the faults.
   1853  * Parameters:
   1854  *     unit       - (IN) BCM device number
   1855  *     group_info - (IN) Group info associated with MA_STATE entry being 
   1856  *                       cleared.
   1857  *     index      - (IN) H/w index of MA_STATE entry to be modified. 
   1858  *     valid      - (IN) 0 => Delete the H/w entry
   1859  *                       1 => Install fresh entry with faults cleared.
   1860  * Returns:
   1861  *     BCM_E_XXX
   1862  */
   1863 STATIC int
   1864 _bcm_tr3_oam_clear_ma_state(int unit, _bcm_oam_group_data_t *group_info, 
   1865                             int index, int valid)
   1866 {
   1867 
   1868     ma_state_entry_t       ma_state_entry;       /* MA State table entry.     */
   1869     
   1870     LOG_VERBOSE(BSL_LS_BCM_OAM,
   1871                 (BSL_META_U(unit,
   1872                             "OAM *group_info %p, index %d, valid %d\n"), 
   1873                  group_info, index, valid));
   1874                
   1875     if (group_info == NULL) {
   1876         LOG_ERROR(BSL_LS_BCM_OAM,
   1877                   (BSL_META_U(unit,
   1878                               "OAM ERR: Arg group_info NULL check failed\n")));
   1879         return BCM_E_INTERNAL;
   1880     }
   1881 
   1882     sal_memset(&ma_state_entry, 0, sizeof(ma_state_entry_t));
   1883     
   1884     /* Mark the entry as valid. */
   1885     soc_MA_STATEm_field32_set(unit, &ma_state_entry, VALIDf, valid);
   1886 
   1887     /* Set the lowest alarm priority info. */
   1888     if (valid) {
   1889         soc_MA_STATEm_field32_set(unit, &ma_state_entry, LOWESTALARMPRIf,
   1890                                   group_info->lowest_alarm_priority);
   1891     }
   1892 
   1893     /* Write group information to hardware table. */
   1894     SOC_IF_ERROR_RETURN(WRITE_MA_STATEm(unit, MEM_BLOCK_ALL, index,
   1895                                         &ma_state_entry));
   1896     return BCM_E_NONE;
   1897 }
   1898 
   1899 
   1900 /*
   1901  * Function:
   1902  *     _bcm_tr3_oam_group_recreate
   1903  * Purpose:
   1904  *     Recreate MA_STATE and RMEP entries, due to current H/w limitation
   1905  *     Currently there is a race condition between H/w and Software
   1906  *     When RMEP is deleted and if it has any faults then, 
   1907  *     MA_STATE remote fault counters need to be decremented by software.
   1908  *     However it may so happen that after reading RMEP faults and just
   1909  *     before RMEP deletion, the fault gets cleared and H/w already decremented
   1910  *     the MA_STATE table, now when software decrements the MA_STATE it would
   1911  *     get MA_STATE table into an inconsistent state.
   1912  *     As a solution we always recreate the entire group on a RMEP deletion.
   1913  * Parameters:
   1914  *     unit     - (IN) BCM device number
   1915  *     group_id - (IN) Group Index, 
   1916  *                as per current implementation this is same as MA_STATE index.
   1917  * Returns:
   1918  *     BCM_E_XXX
   1919  * Expects:
   1920  *      OAM LOCK
   1921  */
   1922 STATIC int
   1923 _bcm_tr3_oam_group_recreate(int unit, int index)
   1924 {
   1925     _bcm_oam_control_t      *oc;                /* OAM control structure.     */
   1926     _bcm_oam_group_data_t   *group_info;        /* OAM group info             */
   1927     _bcm_oam_ep_list_t      *cur_ep_ptr = NULL; /* Pointer to group's EP list */
   1928                                                 /* entry.                     */
   1929     int                     rv = BCM_E_NONE;    /* Operation return status.   */
   1930 
   1931     /* Get OAM control structure handle. */
   1932     BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc));
   1933 
   1934     /* Get the handle to group info */
   1935     group_info = &(oc->group_info[index]);
   1936     
   1937     /*if unused Group, just clear the MA_STATE index, including the valid bit*/
   1938     if (!(group_info->in_use)) {
   1939         LOG_WARN(BSL_LS_BCM_OAM,
   1940                  (BSL_META_U(unit,
   1941                              "OAM, WARN: Recieved group recreate request for " 
   1942                               "unused Group Id %d\n"), index));
   1943     
   1944         rv = _bcm_tr3_oam_clear_ma_state(unit, group_info, index, 0);
   1945         if (BCM_FAILURE(rv)) {
   1946             LOG_ERROR(BSL_LS_BCM_OAM,
   1947                       (BSL_META_U(unit,
   1948                                   "OAM Error: MA_STATE clear failed group id %d - "
   1949                                    "%s.\n"), index, bcm_errmsg(rv)));
   1950             return rv;
   1951         }
   1952         return rv;
   1953     }
   1954     
   1955     /* 1. Traverse and delete the RMEPs in the group */
   1956     if (group_info->ep_list != NULL) {
   1957         cur_ep_ptr = *(group_info->ep_list);
   1958     }
   1959     while (cur_ep_ptr) {
   1960         if (cur_ep_ptr->ep_data_p->is_remote && cur_ep_ptr->ep_data_p->in_use) {
   1961             rv = _bcm_tr3_oam_clear_rmep(unit, cur_ep_ptr->ep_data_p, 0);
   1962             if (BCM_FAILURE(rv)) {
   1963                 LOG_ERROR(BSL_LS_BCM_OAM,
   1964                           (BSL_META_U(unit,
   1965                                       "OAM Error: RMEP delete failed Ep id %d - "
   1966                                        "%s.\n"), cur_ep_ptr->ep_data_p->ep_id, bcm_errmsg(rv)));
   1967                 return rv;
   1968             }
   1969         }
   1970         cur_ep_ptr = cur_ep_ptr->next;
   1971     }
   1972 
   1973     /* 2. Clear the MA_STATE table faults */
   1974     rv = _bcm_tr3_oam_clear_ma_state(unit, group_info, index, 1);
   1975     if (BCM_FAILURE(rv)) {
   1976         LOG_ERROR(BSL_LS_BCM_OAM,
   1977                   (BSL_META_U(unit,
   1978                               "OAM Error: MA_STATE clear failed group id %d - "
   1979                                "%s.\n"), index, bcm_errmsg(rv)));
   1980         return rv;
   1981     }
   1982 
   1983     /* 3. Recreate the RMEP table entries. Clearing the faults. */
   1984     if (group_info->ep_list != NULL) {
   1985         cur_ep_ptr = *(group_info->ep_list);
   1986     }
   1987     while (cur_ep_ptr) {
   1988         if (cur_ep_ptr->ep_data_p->is_remote && cur_ep_ptr->ep_data_p->in_use) {
   1989             rv = _bcm_tr3_oam_clear_rmep(unit, cur_ep_ptr->ep_data_p, 1);
   1990             if (BCM_FAILURE(rv)) {
   1991                 LOG_ERROR(BSL_LS_BCM_OAM,
   1992                           (BSL_META_U(unit,
   1993                                       "OAM Error: RMEP clear failed EP id %d - "
   1994                                        "%s.\n"), cur_ep_ptr->ep_data_p->ep_id, bcm_errmsg(rv)));
   1995                 return rv;
   1996             }
   1997         }
   1998         cur_ep_ptr = cur_ep_ptr->next;
   1999     }
   2000     
   2001     return rv;
   2002 }
   2003 
   2004 
   2005 /*
   2006  * Function:
   2007  *     _bcm_tr3_oam_ser_handler
   2008  * Purpose:
   2009  *     Soft Error Correction routine for MA_STATE and RMEP tables.
   2010  * Parameters:
   2011  *     unit       - (IN) BCM device number
   2012  *     mem        - (IN) Memory MA_STATE or RMEP.
   2013  *     index      - (IN) Memory Index.
   2014  * Returns:
   2015  *     BCM_E_XXX
   2016  */
   2017 STATIC int
   2018 _bcm_tr3_oam_ser_handler(int unit, soc_mem_t mem, int index)
   2019 {
   2020     int                     rv = BCM_E_NONE;    /* Operation return status.   */
   2021     _bcm_oam_control_t      *oc = NULL;         /* OAM control structure.     */
   2022     bcm_oam_endpoint_t      remote_ep_index;    /* Remote Endpoint index.     */
   2023     _bcm_oam_hash_data_t    *ep_data = NULL;    /* Remote Endpoint hash data  */
   2024     rmep_entry_t         rmep_entry;        /* Remote MEP entry.             */
   2025     LOG_VERBOSE(BSL_LS_BCM_OAM,
   2026                 (BSL_META_U(unit,
   2027                             "OAM SER on mem %s, index %d\n"), 
   2028                  SOC_MEM_NAME(unit, mem), index));
   2029               
   2030     /* Get OAM control structure handle. */
   2031     BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc));
   2032 
   2033     switch(mem){
   2034         case MA_STATEm:
   2035             _BCM_OAM_GROUP_INDEX_VALIDATE(index);
   2036             _BCM_OAM_LOCK(oc);
   2037             rv = _bcm_tr3_oam_group_recreate(unit, index);
   2038             _BCM_OAM_UNLOCK(oc);
   2039             break;
   2040             
   2041         case RMEPm:
   2042             _BCM_OAM_RMEP_INDEX_VALIDATE(index);
   2043             _BCM_OAM_LOCK(oc);
   2044             /* Get the logical index from H/w RMEP index */
   2045             remote_ep_index = oc->remote_endpoints[index];
   2046             if(remote_ep_index == BCM_OAM_ENDPOINT_INVALID) {
   2047                 /* clean the HW RMEP index */
   2048                 sal_memset(&rmep_entry, 0, sizeof(rmep_entry_t));   
   2049                 rv = WRITE_RMEPm(unit, MEM_BLOCK_ALL, index,
   2050                          &rmep_entry);   
   2051                 _BCM_OAM_UNLOCK(oc);
   2052                 break;
   2053             }
   2054             /* Get handle to Hash data */
   2055             ep_data = &(oc->oam_hash_data[remote_ep_index]);
   2056             
   2057             if (!(ep_data->in_use)) {
   2058                 /* If endpoint not in use, just clear the RMEP entry in memory */
   2059                 LOG_WARN(BSL_LS_BCM_OAM,
   2060                          (BSL_META_U(unit,
   2061                                      "OAM, WARN: Recieved Parity Error on"
   2062                                       "unused Remote Id %d\n"), remote_ep_index));
   2063                 /* Just clear this entry including valid bit */
   2064                 rv = _bcm_tr3_oam_clear_rmep(unit, ep_data, 0);
   2065             } else {
   2066                 /* Get the group Id from EP data, call group recreate routine */
   2067                 rv = _bcm_tr3_oam_group_recreate(unit, ep_data->group_index);
   2068             }
   2069             _BCM_OAM_UNLOCK(oc);
   2070             break;
   2071 
   2072         default:
   2073             LOG_ERROR(BSL_LS_BCM_OAM,
   2074                       (BSL_META_U(unit,
   2075                                   "OAM, ERR: Invalid mem in OAM SER correction "
   2076                                    "routine %s\n"), SOC_MEM_NAME(unit, mem)));
   2077             return BCM_E_INTERNAL;
   2078     }
   2079 
   2080     LOG_VERBOSE(BSL_LS_BCM_OAM,
   2081                 (BSL_META_U(unit,
   2082                             "OAM SER completed on mem %s, index %d, rv %d\n"), 
   2083                  SOC_MEM_NAME(unit, mem), index, rv));
   2084     
   2085     return rv;
   2086     
   2087 }
   2088 
   2089 
   2090 /*
   2091  * Function:
   2092  *     _bcm_tr3_oam_group_name_mangle
   2093  * Purpose:
   2094  *     Build tbe group name for hardware table write.
   2095  * Parameters:
   2096  *     name_p         -  (IN) OAM group name.
   2097  *     mangled_name_p -  (IN/OUT) Buffer to write the group name in hardware
   2098  *                       format.
   2099  * Retruns:
   2100  *     None
   2101  */
   2102 STATIC void
   2103 _bcm_tr3_oam_group_name_mangle(uint8 *name_p,
   2104                                uint8 *mangled_name_p)
   2105 {
   2106     uint8  *byte_p;    /* Pointer to group name buffer.       */
   2107     int    bytes_left; /* Number of bytes left in group name. */
   2108 
   2109     bytes_left = BCM_OAM_GROUP_NAME_LENGTH;
   2110     byte_p = (name_p + BCM_OAM_GROUP_NAME_LENGTH - 1);
   2111 
   2112     while (bytes_left > 0) {
   2113         *mangled_name_p = *byte_p;
   2114         ++mangled_name_p;
   2115         --byte_p;
   2116         --bytes_left;
   2117     }
   2118 }
   2119 
   2120 /*
   2121  * Function:
   2122  *      _bcm_tr3_oam_read_clear_faults
   2123  * Purpose:
   2124  *     Clear OAM group and endpoint faults on hardware table read operation.
   2125  * Parameters:
   2126  *     unit     - (IN) BCM device number
   2127  *     index    - (IN) Group/Endpoint hardware table index
   2128  *     mem      - (IN) Memory/table value
   2129  *     entry    - (IN) Pointer to group/endpoint entry
   2130  *     ma_mep   - (IN) Pointer to group/endpoint info structure
   2131  * Returns:
   2132  *     BCM_E_NONE      - No errors.
   2133  *     BCM_E_XXX       - Otherwise.
   2134  */
   2135 STATIC int
   2136 _bcm_tr3_oam_read_clear_faults(int unit, int index, soc_mem_t mem,
   2137                                uint32 *entry, void *ma_rmep)
   2138 {
   2139     bcm_oam_group_info_t    *group_info_p;  /* Pointer to group info         */
   2140                                             /* structure.                    */
   2141     bcm_oam_endpoint_info_t *ep_info_p;     /* Pointer to endpoint info      */
   2142                                             /* structure.                    */
   2143     _bcm_oam_fault_t        *faults_list;   /* Pointer to faults list.       */
   2144     uint32                  *faults;        /* Faults flag bits.             */
   2145     uint32                  *p_faults;      /* Persistent faults bits.       */
   2146     uint32                  clear_p_faults; /* Clear persistent faults bits. */
   2147     uint32                  rval = 0;       /* Hardware register value.      */
   2148     uint32                  clear_mask = 0; /* Mask to clear persistent faults*/
   2149 
   2150     LOG_DEBUG(BSL_LS_BCM_OAM,
   2151               (BSL_META_U(unit,
   2152                           "OAM Info: _bcm_tr3_oam_read_clear_faults index=%d "
   2153                            "Table=%d.\n"), index, mem));
   2154 
   2155     /* Switch on memory name. */
   2156     switch (mem) {
   2157         /* OAM group state table. */
   2158         case MA_STATEm:
   2159             /* Set the pointer to the start of the group faults array. */
   2160             faults_list = _tr3_oam_group_faults;
   2161 
   2162             /* Typecast to group information structure pointer. */
   2163             group_info_p = (bcm_oam_group_info_t *) ma_rmep;
   2164 
   2165             /* Get group faults information. */
   2166             faults = &group_info_p->faults;
   2167             p_faults = &group_info_p->persistent_faults;
   2168             clear_p_faults = group_info_p->clear_persistent_faults;
   2169             break;
   2170 
   2171         /* OAM remote endpoint table. */
   2172         case RMEPm:
   2173             faults_list = _tr3_oam_endpoint_faults;
   2174             ep_info_p = (bcm_oam_endpoint_info_t *) ma_rmep;
   2175             faults = &ep_info_p->faults;
   2176             p_faults = &ep_info_p->persistent_faults;
   2177             clear_p_faults = ep_info_p->clear_persistent_faults;
   2178             break;
   2179 
   2180         default:
   2181             return (BCM_E_NONE);
   2182     }
   2183 
   2184     /* Loop on list of valid faults. */
   2185     for (;faults_list->mask != 0; ++faults_list) {
   2186 
   2187         /* Get  faults status. */
   2188         if (0 != soc_mem_field32_get(unit, mem, entry,
   2189                                      faults_list->current_field)) {
   2190             *faults |= faults_list->mask;
   2191         }
   2192 
   2193         /* Get sticky faults status. */
   2194         if (0 != soc_mem_field32_get(unit, mem, entry,
   2195                                      faults_list->sticky_field)) {
   2196 
   2197             *p_faults |= faults_list->mask;
   2198 
   2199             /*
   2200              * If user has request to clear persistent faults,
   2201              * then set BITS_TO_CLEARf field in the register buffer.
   2202              */
   2203             if (clear_p_faults) {
   2204                 clear_mask |= faults_list->clear_sticky_mask;
   2205             }
   2206         }
   2207     }
   2208 
   2209     /* Check if faults need to be cleared. */
   2210     if (clear_mask && clear_p_faults) {
   2211 
   2212         LOG_VERBOSE(BSL_LS_BCM_OAM,
   2213                     (BSL_META_U(unit,
   2214                                 "OAM: clear_mask %d.\n"),
   2215                      clear_mask));
   2216 
   2217         soc_reg_field_set(unit, CCM_READ_CONTROLr, &rval, BITS_TO_CLEARf,
   2218                           clear_mask);
   2219 
   2220         /* Enable clearing of faults. */
   2221         soc_reg_field_set(unit, CCM_READ_CONTROLr, &rval, ENABLE_CLEARf, 1);
   2222 
   2223         
   2224         if (MA_STATEm == mem) {
   2225             soc_reg_field_set(unit, CCM_READ_CONTROLr, &rval, MEMORYf, 0);
   2226         } else {
   2227             soc_reg_field_set(unit, CCM_READ_CONTROLr, &rval, MEMORYf, 1);
   2228         }
   2229 
   2230         soc_reg_field_set(unit, CCM_READ_CONTROLr, &rval, INDEXf, index);
   2231 
   2232         /* Update read control register. */
   2233         BCM_IF_ERROR_RETURN(WRITE_CCM_READ_CONTROLr(unit, rval));
   2234     }
   2235 
   2236     return (BCM_E_NONE);
   2237 }
   2238 
   2239 #if defined(INCLUDE_BHH)
   2240 /*
   2241  * Function:
   2242  *      _bcm_tr3_oam_get_group_sw_rdi
   2243  * Purpose:
   2244  *     Get OAM group SW RDI information.
   2245  * Parameters:
   2246  *     unit         - (IN) BCM device number
   2247  *     group_index  - (IN) Group hardware table index
   2248  *     group_sw_rdi - (OUT) Pointer to group SW RDI
   2249  * Returns:
   2250  *     BCM_E_NONE      - No errors.
   2251  *     BCM_E_XXX       - Otherwise.
   2252  */
   2253 STATIC int
   2254 _bcm_tr3_oam_get_group_sw_rdi(int unit, bcm_oam_group_t group_index,
   2255                        uint8 *group_sw_rdi)
   2256 {
   2257     maid_reduction_entry_t  maid_reduction_entry; /* MAID reduction entry.    */
   2258 
   2259     BCM_IF_ERROR_RETURN(READ_MAID_REDUCTIONm(unit, MEM_BLOCK_ANY,
   2260                                              group_index,
   2261                                              &maid_reduction_entry));
   2262 
   2263     if (1 == soc_MAID_REDUCTIONm_field32_get(unit, &maid_reduction_entry,
   2264                                              SW_RDIf)) {
   2265         *group_sw_rdi = 1;
   2266     }
   2267     return (BCM_E_NONE);
   2268 }
   2269 #endif
   2270 
   2271 /*
   2272  * Function:
   2273  *      _bcm_tr3_oam_get_group
   2274  * Purpose:
   2275  *     Get OAM group information.
   2276  * Parameters:
   2277  *     unit         - (IN) BCM device number
   2278  *     group_index  - (IN) Group hardware table index
   2279  *     group        - (IN) Pointer to group array list
   2280  *     group_info   - (IN/OUT) Pointer to group info structure
   2281  * Returns:
   2282  *     BCM_E_NONE      - No errors.
   2283  *     BCM_E_XXX       - Otherwise.
   2284  */
   2285 STATIC int
   2286 _bcm_tr3_oam_get_group(int unit, bcm_oam_group_t group_index,
   2287                        _bcm_oam_group_data_t *group_p,
   2288                        bcm_oam_group_info_t *group_info)
   2289 {
   2290     maid_reduction_entry_t  maid_reduction_entry; /* MAID reduction entry.    */
   2291     ma_state_entry_t        ma_state_entry;       /* MA_STATE table entry.    */
   2292     int                     rv;                   /* Operation return status. */
   2293 
   2294     group_info->id = group_index;
   2295 
   2296     BCM_IF_ERROR_RETURN(READ_MA_STATEm(unit, MEM_BLOCK_ANY,
   2297                                        group_index,
   2298                                        &ma_state_entry));
   2299 
   2300     group_info->lowest_alarm_priority = soc_MA_STATEm_field32_get
   2301                                             (unit, &ma_state_entry,
   2302                                              LOWESTALARMPRIf);
   2303 
   2304     rv = _bcm_tr3_oam_read_clear_faults(unit, group_index,
   2305                                         MA_STATEm,
   2306                                         (uint32 *) &ma_state_entry,
   2307                                         group_info);
   2308     if (BCM_FAILURE(rv)) {
   2309         LOG_ERROR(BSL_LS_BCM_OAM,
   2310                   (BSL_META_U(unit,
   2311                               "OAM Error: Clean Faults Group ID=%d- Failed.\n"),
   2312                    group_index));
   2313         return (rv);
   2314     }
   2315     if (group_info->flags & BCM_OAM_GROUP_GET_FAULTS_ONLY) {
   2316         group_info->flags &= ~BCM_OAM_GROUP_GET_FAULTS_ONLY;
   2317         return BCM_E_NONE;
   2318     }    
   2319 
   2320     sal_memcpy(group_info->name, group_p[group_index].name,
   2321                BCM_OAM_GROUP_NAME_LENGTH);
   2322 
   2323     BCM_IF_ERROR_RETURN(READ_MAID_REDUCTIONm(unit, MEM_BLOCK_ANY,
   2324                                              group_index,
   2325                                              &maid_reduction_entry));
   2326 
   2327     if (1 == soc_MAID_REDUCTIONm_field32_get(unit, &maid_reduction_entry,
   2328                                              SW_RDIf)) {
   2329         group_info->flags |= BCM_OAM_GROUP_REMOTE_DEFECT_TX;
   2330     }
   2331 
   2332     return (BCM_E_NONE);
   2333 }
   2334 
   2335 /*
   2336  * Function:
   2337  *     _bcm_oam_group_ep_list_add
   2338  * Purpose:
   2339  *     Add an endpoint to a group endpoint linked list.
   2340  * Parameters:
   2341  *     unit     - (IN) BCM device number
   2342  *     group_id - (IN) OAM group ID.
   2343  *     ep_id    - (IN) OAM endpoint ID.
   2344  * Retruns:
   2345  *     BCM_E_XXX
   2346  */
   2347 STATIC int
   2348 _bcm_oam_group_ep_list_add(int unit,
   2349                            bcm_oam_group_t group_id,
   2350                            bcm_oam_endpoint_t ep_id)
   2351 {
   2352     _bcm_oam_control_t    *oc;       /* Pointer to OAM control structure. */
   2353     _bcm_oam_group_data_t *group_p;  /* Pointer to group data.            */
   2354     _bcm_oam_hash_data_t  *h_data_p; /* Pointer to endpoint hash data.    */
   2355     _bcm_oam_ep_list_t    *ep_list_p = NULL; /* Pointer to endpoint list. */
   2356 
   2357     BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc));
   2358 
   2359     group_p = &oc->group_info[group_id];
   2360     /* coverity : this check is present as part of secure coding method */
   2361     /* coverity[dead_error_condition] */
   2362     if (NULL == group_p) {
   2363         LOG_ERROR(BSL_LS_BCM_OAM,
   2364         /* coverity[dead_error_begin] */
   2365                   (BSL_META_U(unit,
   2366                               "OAM Error: Group data access for GID=%d failed"
   2367                                " %s.\n"), group_id, bcm_errmsg(BCM_E_INTERNAL)));
   2368         return (BCM_E_INTERNAL);
   2369     }
   2370 
   2371     h_data_p = &oc->oam_hash_data[ep_id];
   2372     /* this check is present as part of secure coding method */
   2373     /* coverity[dead_error_condition] */
   2374     if (NULL == h_data_p) {
   2375         LOG_ERROR(BSL_LS_BCM_OAM,
   2376                   (BSL_META_U(unit,
   2377                               "OAM Error: Endpoint data access for EP=%d failed"
   2378         /* coverity[dead_error_begin] */
   2379                                " %s.\n"), ep_id, bcm_errmsg(BCM_E_INTERNAL)));
   2380         return (BCM_E_INTERNAL);
   2381     }
   2382 
   2383     _BCM_OAM_ALLOC(ep_list_p, _bcm_oam_ep_list_t, sizeof(_bcm_oam_ep_list_t),
   2384                 "EP list");
   2385     if (NULL == ep_list_p) {
   2386         LOG_ERROR(BSL_LS_BCM_OAM,
   2387                   (BSL_META_U(unit,
   2388                               "OAM Error: Endpoint list alloc for EP=%d failed"
   2389                                " %s.\n"), ep_id, bcm_errmsg(BCM_E_MEMORY)));
   2390         return (BCM_E_MEMORY);
   2391     }
   2392 
   2393     ep_list_p->prev = NULL;
   2394     ep_list_p->ep_data_p = h_data_p;
   2395     if (NULL == (*group_p->ep_list)) {
   2396         /* Add endpoint as head node. */
   2397         ep_list_p->next = NULL;
   2398         *group_p->ep_list = ep_list_p;
   2399     } else {
   2400         /* Add the endpoint to the linked list. */
   2401         ep_list_p->next = *group_p->ep_list;
   2402         (*group_p->ep_list)->prev = ep_list_p;
   2403         *group_p->ep_list = ep_list_p;
   2404     }
   2405 
   2406     LOG_DEBUG(BSL_LS_BCM_OAM,
   2407               (BSL_META_U(unit,
   2408                           "OAM Info: _bcm_oam_group_ep_list_add (GID=%d) (EP=%d).\n"),
   2409                group_id, ep_id));
   2410     return (BCM_E_NONE);
   2411 }
   2412 
   2413 /*
   2414  * Function:
   2415  *     _bcm_oam_group_ep_list_remove
   2416  * Purpose:
   2417  *     Remove an endpoint to a group endpoint linked list.
   2418  * Parameters:
   2419  *     unit     - (IN) BCM device number
   2420  *     group_id - (IN) OAM group ID.
   2421  *     ep_id    - (IN) OAM endpoint ID.
   2422  * Retruns:
   2423  *     BCM_E_XXX
   2424  */
   2425 STATIC int
   2426 _bcm_oam_group_ep_list_remove(int unit,
   2427                               bcm_oam_group_t group_id,
   2428                               bcm_oam_endpoint_t ep_id)
   2429 {
   2430     _bcm_oam_control_t    *oc;       /* Pointer to OAM control structure. */
   2431     _bcm_oam_group_data_t *group_p;  /* Pointer to group data.            */
   2432     _bcm_oam_hash_data_t  *h_data_p; /* Pointer to endpoint hash data.    */
   2433     _bcm_oam_ep_list_t    *cur;      /* Current endpoint node pointer.    */
   2434     _bcm_oam_ep_list_t    *del_node; /* Pointer to a node to be deleted.  */
   2435 
   2436     /* Control lock already taken by calling routine. */
   2437     BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc));
   2438 
   2439     group_p = &oc->group_info[group_id];
   2440     cur =  *group_p->ep_list;
   2441     if (NULL == cur) {
   2442         /* No endpoints to remove from this group. */
   2443         LOG_DEBUG(BSL_LS_BCM_OAM,
   2444                   (BSL_META_U(unit,
   2445                               "OAM Info: No endpoints to delete in group"
   2446                                " GID:%d.\n"), group_id));
   2447         return (BCM_E_NONE);
   2448     }
   2449 
   2450     /* Check if head node needs to be deleated. */
   2451     if (ep_id == cur->ep_data_p->ep_id) {
   2452         /* Delete head node. */
   2453         del_node = *group_p->ep_list;
   2454         if ((*group_p->ep_list)->next) {
   2455             *group_p->ep_list = (*group_p->ep_list)->next;
   2456             (*group_p->ep_list)->prev = NULL;
   2457         } else {
   2458             *group_p->ep_list = NULL;
   2459         }
   2460         sal_free(del_node);
   2461         LOG_DEBUG(BSL_LS_BCM_OAM,
   2462                   (BSL_META_U(unit,
   2463                               "OAM Info: Head node delete GID=%d - Success\n"),
   2464                    group_id));
   2465         return (BCM_E_NONE);
   2466     }
   2467 
   2468     /* Traverse the list and delete the matching node. */
   2469     while (NULL != cur->next->next) {
   2470         h_data_p = cur->next->ep_data_p;
   2471         if (NULL == h_data_p) {
   2472             LOG_ERROR(BSL_LS_BCM_OAM,
   2473                       (BSL_META_U(unit,
   2474                                   "OAM Error: Group=%d endpoints access failed -"
   2475                                    " %s.\n"), group_id, bcm_errmsg(BCM_E_INTERNAL)));
   2476             return (BCM_E_INTERNAL);
   2477         }
   2478 
   2479         if (ep_id == h_data_p->ep_id) {
   2480             del_node = cur->next;
   2481             cur->next = del_node->next;
   2482             del_node->next->prev = cur;
   2483             sal_free(del_node);
   2484             LOG_DEBUG(BSL_LS_BCM_OAM,
   2485                       (BSL_META_U(unit,
   2486                                   "OAM Info: Node delete GID=%d - Success\n"),
   2487                        group_id));
   2488             return (BCM_E_NONE);
   2489         }
   2490         cur = cur->next;
   2491     }
   2492 
   2493     /* Check if tail node needs to be deleted. */
   2494     h_data_p = cur->next->ep_data_p;
   2495     if (ep_id == h_data_p->ep_id) {
   2496         /* Delete tail node. */
   2497         del_node = cur->next;
   2498         cur->next = NULL;
   2499         sal_free(del_node);
   2500         LOG_DEBUG(BSL_LS_BCM_OAM,
   2501                   (BSL_META_U(unit,
   2502                               "OAM Info: Tail node delete GID=%d - Success\n"),
   2503                    group_id));
   2504         return (BCM_E_NONE);
   2505     }
   2506 
   2507     return (BCM_E_NOT_FOUND);
   2508 }
   2509 
   2510 /*
   2511  * Function:
   2512  *     _bcm_oam_remote_mep_hw_set
   2513  * Purpose:
   2514  *     Configure hardware tables for a remote endpoint.
   2515  * Parameters:
   2516  *     unit      - (IN) BCM device number
   2517  *     ep_info_p - (IN) Pointer to remote endpoint information.
   2518  * Retruns:
   2519  *     BCM_E_XXX
   2520  */
   2521 STATIC int
   2522 _bcm_oam_remote_mep_hw_set(int unit, 
   2523                            const bcm_oam_endpoint_info_t *ep_info_p)
   2524 {
   2525     uint32 l3_entry[SOC_MAX_MEM_WORDS];     /* Remote view entry.            */
   2526     rmep_entry_t         rmep_entry;        /* Remote MEP entry.             */
   2527     uint32               oam_cur_time;      /* Current time.                 */
   2528     _bcm_oam_hash_data_t *h_data_p = NULL;  /* Hash data pointer.            */
   2529     int                  rv;                /* Operation return status.      */
   2530     _bcm_oam_control_t   *oc;               /* Pointer to control structure. */
   2531     const bcm_oam_endpoint_info_t *ep_p;    /* Pointer to endpoint info.     */
   2532     soc_mem_t            mem;               /* L3 entry memory               */
   2533 
   2534     if (NULL == ep_info_p) {
   2535         return (BCM_E_INTERNAL);
   2536     }
   2537 
   2538     /* Initialize local endpoint info pointer. */
   2539     ep_p = ep_info_p;
   2540 
   2541     /* Lock already taken by the calling routine. */
   2542     BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc));
   2543 
   2544     /* Get endpoint hash data pointer. */
   2545     h_data_p = &oc->oam_hash_data[ep_p->id];
   2546     if (!(h_data_p->in_use)) {
   2547         LOG_ERROR(BSL_LS_BCM_OAM,
   2548                   (BSL_META_U(unit,
   2549                               "OAM Error: EP valid check failed.\n")));
   2550         return (BCM_E_INTERNAL);
   2551     }
   2552 
   2553     /* RMEP table programming. */
   2554     sal_memset(&rmep_entry, 0, sizeof(rmep_entry_t));
   2555 
   2556     /* Set the MA group index. */
   2557     soc_RMEPm_field32_set(unit, &rmep_entry, MAID_INDEXf,
   2558                           ep_p->group);
   2559 
   2560     /*
   2561      * The following steps are necessary to enable CCM timeout events
   2562      * without having received any CCMs.
   2563      */
   2564     soc_RMEPm_field32_set(unit, &rmep_entry,
   2565                           RMEP_TIMESTAMP_VALIDf, 1);
   2566 
   2567     BCM_IF_ERROR_RETURN
   2568         (READ_OAM_CURRENT_TIMEr(unit, &oam_cur_time));
   2569 
   2570     soc_RMEPm_field32_set(unit, &rmep_entry, RMEP_TIMESTAMPf,
   2571                           oam_cur_time);
   2572 
   2573     soc_RMEPm_field32_set(unit, &rmep_entry,
   2574                           RMEP_RECEIVED_CCMf,
   2575                          _bcm_tr3_oam_ccm_msecs_to_hw_encode(h_data_p->period));
   2576     /* End of timeout setup */
   2577 
   2578     soc_RMEPm_field32_set(unit, &rmep_entry, VALIDf, 1);
   2579 
   2580     rv = WRITE_RMEPm(unit, MEM_BLOCK_ALL, h_data_p->remote_index,
   2581                      &rmep_entry);
   2582     if (BCM_FAILURE(rv)) {
   2583         LOG_ERROR(BSL_LS_BCM_OAM,
   2584                   (BSL_META_U(unit,
   2585                               "OAM Error: RMEP table write failed EP=%d %s.\n"),
   2586                    ep_info_p->id, bcm_errmsg(rv)));
   2587         return (rv);
   2588     }
   2589     if (SOC_IS_HURRICANE2(unit) || SOC_IS_GREYHOUND(unit) ||
   2590         SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) {
   2591         mem = L3_ENTRY_IPV4_UNICASTm;
   2592     } else {
   2593         mem = L3_ENTRY_1m;
   2594     }
   2595     /* L3 unicast table programming. */
   2596     sal_memset(&l3_entry, 0, sizeof(l3_entry));
   2597     
   2598     /* Set the CCM interval. */
   2599     soc_mem_field32_set
   2600         (unit, mem, &l3_entry, RMEP__CCMf,
   2601         _bcm_tr3_oam_ccm_msecs_to_hw_encode(h_data_p->period));
   2602 
   2603     /* Set the entry hardware index. */
   2604     soc_mem_field32_set(unit, mem, &l3_entry, RMEP__RMEP_PTRf,
   2605                                 h_data_p->remote_index);
   2606 
   2607     /*
   2608      * Construct endpoint RMEP view key for L3 Table entry
   2609      * insert operation.
   2610      */
   2611 #ifdef BCM_HURRICANE2_SUPPORT
   2612     if (SOC_IS_HURRICANE2(unit) || SOC_IS_GREYHOUND(unit) ||
   2613         SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) {
   2614         _bcm_hu2_oam_rmep_key_construct(unit, h_data_p, 
   2615                                     (l3_entry_ipv4_unicast_entry_t *)l3_entry);
   2616     } else 
   2617 #endif /* BCM_HURRICANE2_SUPPORT */
   2618     {
   2619 #ifdef BCM_TRIUMPH3_SUPPORT
   2620 
   2621         _bcm_oam_rmep_key_construct(unit, h_data_p, 
   2622                                    (l3_entry_1_entry_t *)l3_entry);
   2623 #endif /* BCM_HURRICANE2_SUPPORT */
   2624     }
   2625     /* Mark the entry as valid. */
   2626     soc_mem_field32_set(unit, mem, &l3_entry, VALIDf, 1);
   2627 
   2628     /* Install entry in hardware. */
   2629     rv = soc_mem_insert(unit, mem, 
   2630                         MEM_BLOCK_ALL, &l3_entry);
   2631     if (BCM_FAILURE(rv)) {
   2632         LOG_ERROR(BSL_LS_BCM_OAM,
   2633                   (BSL_META_U(unit,
   2634                               "OAM Error: L3 table insert failed EP=%d %s.\n"),
   2635                    ep_p->id, bcm_errmsg(rv)));
   2636         return (rv);
   2637     }
   2638     
   2639     /* Add the H/w index to logical index mapping for RMEP */
   2640     oc->remote_endpoints[h_data_p->remote_index] = ep_p->id; 
   2641 
   2642     return (BCM_E_NONE);
   2643 }
   2644 
   2645 /*
   2646  * Function:
   2647  *     _bcm_tr3_oam_find_lmep
   2648  * Purpose:
   2649  *     Search LMEP view table and return the match entry hardware index and
   2650  *     match entry data.
   2651  * Parameters:
   2652  *     unit       - (IN) BCM device number
   2653  *     h_data_p   - (IN) Pointer to endpoint hash data.
   2654  *     entry_idx  - (IN/OUT) Pointer to match entry hardware index.
   2655  *     l3_entry_p - (IN/OUT) Pointer to match entry data.
   2656  * Retruns:
   2657  *     BCM_E_XXX
   2658  */
   2659 STATIC int
   2660 _bcm_tr3_oam_find_lmep(int unit, const _bcm_oam_hash_data_t *h_data_p,
   2661                        int *entry_idx,
   2662                        uint32 *l3_entry_p)
   2663 {
   2664     uint32             l3_entry[SOC_MAX_MEM_WORDS];    /* L3 entry to search.*/
   2665     int                rv;       /* Operation return status. */
   2666 
   2667     if (NULL == h_data_p || NULL == entry_idx || NULL == l3_entry_p) {
   2668         return (BCM_E_INTERNAL);
   2669     }
   2670 
   2671     sal_memset(&l3_entry, 0, sizeof(l3_entry));
   2672 
   2673     /* Construct endpoint LMEP view key for L3 Table entry search operation. */
   2674 #ifdef BCM_HURRICANE2_SUPPORT
   2675     if (SOC_IS_HURRICANE2(unit) || SOC_IS_GREYHOUND(unit) ||
   2676         SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) {
   2677         _bcm_hu2_oam_lmep_key_construct(unit, h_data_p, 
   2678                                     (l3_entry_ipv4_unicast_entry_t *)l3_entry);
   2679     } else 
   2680 #endif /* BCM_HURRICANE2_SUPPORT */
   2681     {
   2682 #ifdef BCM_TRIUMPH3_SUPPORT
   2683         _bcm_oam_lmep_key_construct(unit, h_data_p, 
   2684                                     (l3_entry_1_entry_t *)l3_entry);
   2685 #endif /* BCM_TRIUMPH3_SUPPORT */
   2686     }
   2687     /* Take L3 module protection mutex to block any updates. */
   2688     L3_LOCK(unit);
   2689 
   2690     /* Perform the search in L3_ENTRY_1 table. */
   2691 #ifdef BCM_HURRICANE2_SUPPORT
   2692     if (SOC_IS_HURRICANE2(unit) || SOC_IS_GREYHOUND(unit) ||
   2693         SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) {
   2694         rv = soc_mem_search(unit, L3_ENTRY_IPV4_UNICASTm, MEM_BLOCK_ANY, 
   2695                             entry_idx, &l3_entry, l3_entry_p, 0);
   2696     } else 
   2697 #endif /* BCM_HURRICANE2_SUPPORT */
   2698     {
   2699         rv = soc_mem_search(unit, L3_ENTRY_1m, MEM_BLOCK_ANY, entry_idx,
   2700                         &l3_entry, l3_entry_p, 0);
   2701 
   2702     }
   2703     if (BCM_FAILURE(rv)) {
   2704         LOG_VERBOSE(BSL_LS_BCM_OAM,
   2705                   (BSL_META_U(unit,
   2706                               "OAM Error: L3 entry lookup vlan=%d port=%x %s.\n"),
   2707                    h_data_p->vlan, h_data_p->sglp, bcm_errmsg(rv)));
   2708     }
   2709 
   2710     /* Release L3 module protection mutex. */
   2711     L3_UNLOCK(unit);
   2712 
   2713     return (rv);
   2714 }
   2715 
   2716 #ifdef BCM_HURRICANE2_SUPPORT
   2717 
   2718 STATIC void _bcm_oam_cmic_tdm_slot_time_get(int unit,
   2719                                             uint32 *cmic_tdm_slot_time)
   2720 {
   2721     if(SOC_IS_GREYHOUND(unit)) {
   2722         *cmic_tdm_slot_time = 100;
   2723     }
   2724 
   2725     if(SOC_IS_GREYHOUND2(unit)) {
   2726         *cmic_tdm_slot_time = 385;
   2727     }
   2728 
   2729     if(SOC_IS_HURRICANE2(unit)) {
   2730         *cmic_tdm_slot_time = 75;
   2731     }
   2732 
   2733     if(SOC_IS_HURRICANE3(unit)) {
   2734         *cmic_tdm_slot_time = 96;
   2735         if(soc_feature(unit, soc_feature_wh2))
   2736         {
   2737             *cmic_tdm_slot_time = 40;
   2738         }
   2739     }
   2740 }
   2741 
   2742 /*
   2743  * Function:
   2744  *     _bcm_oam_modify_oam_tx_control
   2745  * Purpose:
   2746  *     Modifies the OAM TX control based on the inputs.
   2747  * Parameters:
   2748  *     unit      - (IN) BCM device number
   2749  *     reg_val   - (IN/OUT) Pointer to OAM TX control register value.
   2750  *     read_write - (IN) read and write /just write operation indication
   2751  *     tx_diable - (OUT) TX disable or not indication
   2752  * Retruns:
   2753  *     BCM_E_XXX
   2754  */
   2755 STATIC int
   2756 _bcm_oam_modify_oam_tx_control(int unit, uint32 *reg_val, int read_write,
   2757                                    uint8 *tx_diable)
   2758 {
   2759     int     rv = BCM_E_NONE;
   2760     uint32  rval = 0; 
   2761     uint32  set_val = 0;
   2762     soc_info_t *si = &SOC_INFO(unit);
   2763     uint32  cmic_tdm_slot_time = 0, clock_period = 0;
   2764     uint32 delay_us = 0;
   2765 
   2766     if(SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANE2(unit)) {
   2767         if (read_write) {
   2768             rv = READ_OAM_TX_CONTROLr(unit, &rval);
   2769             if (BCM_FAILURE(rv)) { 
   2770                 LOG_ERROR(BSL_LS_BCM_OAM,
   2771                           (BSL_META_U(unit,
   2772                           "OAM Error: reading OAM_TX_CONTROLr\n")));
   2773                 return (rv);
   2774             }
   2775             *reg_val = rval;
   2776             if( (rval&0x1) == 0x1 ) {
   2777                 set_val = (rval&0xFE);
   2778                 rv = WRITE_OAM_TX_CONTROLr(unit, set_val);
   2779                 if (BCM_FAILURE(rv)) { 
   2780                     LOG_ERROR(BSL_LS_BCM_OAM,
   2781                               (BSL_META_U(unit,
   2782                               "OAM Error: writing OAM_TX_CONTROLr\n")));
   2783                     return (rv);
   2784                 }
   2785                 /* Clock period caluclation in nano seconds. Fractional part
   2786                    will be truncated and we should be ok with it
   2787                    as only us granularity is needed */
   2788                 clock_period = (1000/si->frequency);
   2789 
   2790                 _bcm_oam_cmic_tdm_slot_time_get(unit, &cmic_tdm_slot_time);
   2791 
   2792                 /* As per WAR provovided by HW team in GH-2161,
   2793                    wait time before LMEP table access is calculated as
   2794                  (512*(3+cmic_tdm_slot_time)+cmic_tdm_slot_time)*clock periods
   2795                  where (CMIC slot is 1/68@300Mhz) with device frequency of 300Mhz,
   2796                   cmic_tdm_slot_time = 68 cycles */
   2797 
   2798                 /* Calculate the delay to be added in micro seconds */
   2799                 delay_us = (((512*(3+cmic_tdm_slot_time) + cmic_tdm_slot_time) *
   2800                             clock_period)) /1000;
   2801                 sal_usleep(delay_us);
   2802             }
   2803             *tx_diable = 1;
   2804         } else {
   2805             rv = WRITE_OAM_TX_CONTROLr(unit, *reg_val);
   2806             if (BCM_FAILURE(rv)) { 
   2807                 LOG_ERROR(BSL_LS_BCM_OAM,
   2808                           (BSL_META_U(unit,
   2809                           "OAM Error: writing OAM_TX_CONTROLr\n")));
   2810                 return (rv);
   2811             }
   2812         }
   2813     }
   2814     return rv;
   2815 }
   2816 #endif /* BCM_HURRICANE2_SUPPORT */
   2817 /*
   2818  * Function:
   2819  *     _bcm_oam_local_tx_mep_hw_set
   2820  * Purpose:
   2821  *     Configure hardware tables for a local CCM Tx enabled endpoint.
   2822  * Parameters:
   2823  *     unit      - (IN) BCM device number
   2824  *     ep_info_p - (IN) Pointer to remote endpoint information.
   2825  * Retruns:
   2826  *     BCM_E_XXX
   2827  */
   2828 STATIC int
   2829 _bcm_oam_local_tx_mep_hw_set(int unit,
   2830                              const bcm_oam_endpoint_info_t *ep_info_p)
   2831 {
   2832     _bcm_oam_hash_data_t *hash_data; /* Pointer to endpoint hash data. */
   2833     lmep_entry_t         entry;      /* LMEP table entry.              */
   2834     lmep_da_entry_t      dmac_entry; /* LMEP table entry.              */
   2835     int                  word;       /* Word index.                    */
   2836     uint32               reversed_maid[BCM_OAM_GROUP_NAME_LENGTH / 4];
   2837                                      /* Group name in Hw format.       */
   2838     _bcm_oam_control_t   *oc;        /* Pointer to control structure.  */
   2839     const bcm_oam_endpoint_info_t *ep_p;/* Pointer to endpoint info.   */
   2840 #ifdef BCM_HURRICANE2_SUPPORT
   2841     int                  rv;         /* Operation return status.       */
   2842     uint32  rval = 0;
   2843     uint8   tx_disable = 0;
   2844 #endif /* BCM_HURRICANE2_SUPPORT */
   2845 
   2846     if (NULL == ep_info_p) {
   2847         return (BCM_E_INTERNAL);
   2848     }
   2849 
   2850     /* Initialize local endpoint info pointer. */
   2851     ep_p = ep_info_p;
   2852 
   2853     /* Lock already taken by the calling routine. */
   2854     BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc));
   2855 
   2856 
   2857     /* Get the stored endpoint information from hash table. */
   2858     hash_data = &oc->oam_hash_data[ep_p->id];
   2859     if (!(hash_data->in_use)) {
   2860         LOG_ERROR(BSL_LS_BCM_OAM,
   2861                   (BSL_META_U(unit,
   2862                               "OAM Error: EP valid check failed.\n")));
   2863         return (BCM_E_INTERNAL);
   2864     }
   2865 
   2866     sal_memset(&entry, 0, sizeof(lmep_entry_t));
   2867 
   2868     /* Set the Group base index. */
   2869     soc_LMEPm_field32_set(unit, &entry, MAID_INDEXf, ep_p->group);
   2870 
   2871     /* Set source MAC address to be used on transmitted packets. */
   2872     soc_LMEPm_mac_addr_set(unit, &entry, SAf, ep_p->src_mac_address);
   2873 
   2874     /* Set the Maintenance Domain Level. */
   2875     soc_LMEPm_field32_set(unit, &entry, MDLf, ep_p->level);
   2876 
   2877     /* Set endpoint name. */
   2878     soc_LMEPm_field32_set(unit, &entry, MEPIDf, ep_p->name);
   2879 
   2880     /* Set packet priority value to be used in transmitted packet. */
   2881     soc_LMEPm_field32_set(unit, &entry, LMEP_PRIORITYf,
   2882                           ep_p->pkt_pri);
   2883 
   2884     /*
   2885      * Set VLAN ID to be used in the transmitted packet.
   2886      * For link level MEPs, this VLAN_ID == 0.
   2887      */
   2888     soc_LMEPm_field32_set(unit, &entry, VLAN_IDf, ep_p->vlan);
   2889 
   2890     /* Set interval between CCM packet transmissions. */
   2891     soc_LMEPm_field32_set
   2892         (unit, &entry, CCM_INTERVALf,
   2893         _bcm_tr3_oam_ccm_msecs_to_hw_encode(ep_p->ccm_period));
   2894 
   2895     /* Set the destination port on which packet needs to Tx. */
   2896     soc_LMEPm_field32_set(unit, &entry, DESTf, hash_data->dglp);
   2897 
   2898     /* Set HiGig opcode to Unicast packet opcode. */
   2899     soc_LMEPm_field32_set(unit, &entry, MH_OPCODEf, BCM_HG_OPCODE_UC);
   2900 
   2901     /* Set CCM packet internal priority used for scheduling. */
   2902     soc_LMEPm_field32_set(unit, &entry, INT_PRIf, ep_p->int_pri);
   2903 
   2904     /* Set Port status TLV in CCM Tx packets. */
   2905     if (ep_p->flags & BCM_OAM_ENDPOINT_PORT_STATE_UPDATE) {
   2906         if (ep_p->port_state > BCM_OAM_PORT_TLV_UP) {
   2907             return (BCM_E_PARAM);
   2908         }
   2909         soc_LMEPm_field32_set(unit, &entry, PORT_TLVf,
   2910                               (ep_p->port_state == BCM_OAM_PORT_TLV_UP)
   2911                               ? 1 : 0);
   2912     }
   2913 
   2914     /* Set Interface status TLV in CCM Tx packets - 3-bits wide. */
   2915     if (ep_p->flags & BCM_OAM_ENDPOINT_INTERFACE_STATE_UPDATE) {
   2916         if ((ep_p->interface_state < BCM_OAM_INTERFACE_TLV_UP)
   2917             || (ep_p->interface_state > BCM_OAM_INTERFACE_TLV_LLDOWN)) {
   2918             return (BCM_E_PARAM);
   2919         }
   2920         soc_LMEPm_field32_set(unit, &entry, INTERFACE_TLVf,
   2921                               ep_p->interface_state);
   2922     }
   2923 
   2924     /*
   2925      * When this bit is '1', both port and interface TLV values are set in
   2926      *  CCM Tx packets.
   2927      */
   2928     if ((ep_p->flags & BCM_OAM_ENDPOINT_PORT_STATE_TX)
   2929         || (ep_p->flags & BCM_OAM_ENDPOINT_INTERFACE_STATE_TX)) {
   2930         soc_LMEPm_field32_set(unit, &entry, INSERT_TLVf, 1);
   2931     }
   2932 
   2933     /*
   2934      * Construct group name for hardware.
   2935      * i.e Word-reverse the MAID bytes for hardware.
   2936      */
   2937     for (word = 0; word < (BCM_OAM_GROUP_NAME_LENGTH / 4);
   2938          ++word) {
   2939         reversed_maid[word]
   2940             = bcm_htonl(((uint32 *) oc->group_info[ep_p->group].name)
   2941                 [((BCM_OAM_GROUP_NAME_LENGTH / 4) - 1) - word]);
   2942     }
   2943 
   2944     /* Set the group name. */
   2945     soc_LMEPm_field_set(unit, &entry, MAIDf, reversed_maid);
   2946 #ifdef BCM_HURRICANE2_SUPPORT
   2947     rv = _bcm_oam_modify_oam_tx_control (unit, &rval, 1, &tx_disable);
   2948     if (BCM_FAILURE(rv)) {
   2949         LOG_ERROR(BSL_LS_BCM_OAM,
   2950                   (BSL_META_U(unit,
   2951                   "OAM Error: in _bcm_oam_modify_oam_tx_control \n")));
   2952         return (rv);
   2953     }
   2954 #endif /* BCM_HURRICANE2_SUPPORT */
   2955 
   2956     /* Write entry to hardware LMEP table. */
   2957     SOC_IF_ERROR_RETURN
   2958         (WRITE_LMEPm(unit, MEM_BLOCK_ALL, hash_data->local_tx_index,
   2959                      &entry));
   2960     /* LMEP_DA table programming. */
   2961     sal_memset(&dmac_entry, 0, sizeof(lmep_da_entry_t));
   2962 
   2963     /* Set CCM packet Destination MAC address value. */
   2964 #ifdef BCM_HURRICANE2_SUPPORT
   2965     if (SOC_IS_HURRICANE2(unit) || SOC_IS_GREYHOUND(unit) ||
   2966         SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) {
   2967         soc_mem_mac_addr_set(unit, LMEP_DAm, &dmac_entry, MACDAf,
   2968                          ep_p->dst_mac_address);
   2969  
   2970     } else 
   2971 #endif /* BCM_HURRICANE2_SUPPORT */
   2972     {
   2973         soc_mem_mac_addr_set(unit, LMEP_DAm, &dmac_entry, DAf,
   2974                          ep_p->dst_mac_address);
   2975     }
   2976     /*
   2977      * Write the entry to hardware LMEP_DA table.
   2978      * Use same hardware index as the LMEP table entry index.
   2979      */
   2980     SOC_IF_ERROR_RETURN
   2981         (WRITE_LMEP_DAm(unit, MEM_BLOCK_ALL, hash_data->local_tx_index,
   2982                        &dmac_entry));
   2983 
   2984 #ifdef BCM_HURRICANE2_SUPPORT
   2985     if (tx_disable) {
   2986         rv = _bcm_oam_modify_oam_tx_control (unit, &rval, 0, &tx_disable);
   2987         if (BCM_FAILURE(rv)) {
   2988             LOG_ERROR(BSL_LS_BCM_OAM,
   2989                       (BSL_META_U(unit,
   2990                       "OAM Error: in _bcm_oam_modify_oam_tx_control \n")));
   2991             return (rv);
   2992         }
   2993     }
   2994 #endif /* BCM_HURRICANE2_SUPPORT */
   2995 
   2996     return (BCM_E_NONE);
   2997 }
   2998 
   2999 /*
   3000  * Function:
   3001  *     _bcm_oam_local_tx_mep_hw_set
   3002  * Purpose:
   3003  *     Configure hardware tables for a local CCM Rx enabled endpoint.
   3004  * Parameters:
   3005  *     unit      - (IN) BCM device number
   3006  *     ep_info_p - (IN) Pointer to remote endpoint information.
   3007  * Retruns:
   3008  *     BCM_E_XXX
   3009  */
   3010 STATIC int
   3011 _bcm_oam_local_rx_mep_hw_set(int unit,
   3012                              const bcm_oam_endpoint_info_t *ep_info_p)
   3013 {
   3014     _bcm_oam_hash_data_t *h_data_p;      /* Endpoint hash data pointer.      */
   3015     ma_index_entry_t     ma_idx_entry;   /* MA_INDEX table entry buffer.     */
   3016     uint32               opcode_entry = 0; /* Opcode control profile entry.  */
   3017     void                 *entries[1];    /* Pointer to opcode control entry. */
   3018     uint32               profile_index;  /* opcode control profile index.    */
   3019     uint32               l3_entry[SOC_MAX_MEM_WORDS];  /* L3 entry buffer.   */
   3020     int                  l3_index = -1;  /* L3 entry hardware index.         */
   3021     int                  rv;             /* Operation return status.         */
   3022     uint8                mdl;            /* Maintenance domain level.        */
   3023     _bcm_oam_control_t   *oc;            /* Pointer to control structure.    */
   3024     const bcm_oam_endpoint_info_t *ep_p; /* Pointer to endpoint info.        */
   3025     soc_mem_t            mem;            /* L3 entry memory                  */
   3026     if (NULL == ep_info_p) {
   3027         return (BCM_E_INTERNAL);
   3028     }
   3029 
   3030     /* Initialize local endpoint info pointer. */
   3031     ep_p = ep_info_p;
   3032 
   3033     /* Lock already taken by the calling routine. */
   3034     BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc));
   3035 
   3036     /* Get endpoint hash data pointer. */
   3037     h_data_p = &oc->oam_hash_data[ep_p->id];
   3038 
   3039     /* Construct the opcode control profile table entry. */
   3040     if (ep_p->opcode_flags & _BCM_TR3_OAM_OPCODE_MASK) {
   3041         /* Use application specified opcode control settings. */
   3042         rv = _bcm_tr3_oam_opcode_profile_entry_set(unit,
   3043                                                    ep_p->opcode_flags,
   3044                                                    &opcode_entry);
   3045         if (BCM_FAILURE(rv)) {
   3046             LOG_ERROR(BSL_LS_BCM_OAM,
   3047                       (BSL_META_U(unit,
   3048                                   "OAM Error: Opcode profile set failed for EP=%d"
   3049                                    "  %s.\n"), ep_p->id, bcm_errmsg(rv)));
   3050             return (rv);
   3051         }
   3052     } else {
   3053         /* Use default opcode control profile settings. */
   3054         rv = _bcm_tr3_oam_opcode_profile_entry_init(unit, &opcode_entry);
   3055         if (BCM_FAILURE(rv)) {
   3056             LOG_ERROR(BSL_LS_BCM_OAM,
   3057                       (BSL_META_U(unit,
   3058                                   "OAM Error: Opcode profile init failed for EP=%d"
   3059                                    "  %s.\n"), ep_p->id, bcm_errmsg(rv)));
   3060             return (rv);
   3061         }
   3062     }
   3063 
   3064     /* Add entry to profile table.  */
   3065     entries[0] = &opcode_entry;
   3066 
   3067     soc_mem_lock(unit, OAM_OPCODE_CONTROL_PROFILEm);
   3068 
   3069     rv = soc_profile_mem_add(unit, &oc->oam_opcode_control_profile,
   3070                              (void *) &entries, 1, &profile_index);
   3071     if (BCM_FAILURE(rv)) {
   3072         LOG_ERROR(BSL_LS_BCM_OAM,
   3073                   (BSL_META_U(unit,
   3074                               "OAM Error: Opcode profile add failed for EP=%d"
   3075                                "  %s.\n"), ep_p->id, bcm_errmsg(rv)));
   3076         soc_mem_unlock(unit, OAM_OPCODE_CONTROL_PROFILEm);
   3077         return (rv);
   3078     }
   3079 
   3080     /* Release opcode control profile table lock. */
   3081     soc_mem_unlock(unit, OAM_OPCODE_CONTROL_PROFILEm);
   3082 
   3083     /* Store endpoint OAM opcode profile table index value. */
   3084     h_data_p->profile_index = profile_index;
   3085 
   3086     /*
   3087      * MA_INDEX table programming.
   3088      */
   3089 
   3090     /* Clear the entry data. */
   3091     sal_memset(&ma_idx_entry, 0, sizeof(ma_index_entry_t));
   3092 
   3093     /* Set group index value. */
   3094     soc_MA_INDEXm_field32_set(unit, &ma_idx_entry, MA_PTRf,
   3095                               ep_p->group);
   3096 
   3097     /* Set OAM opcode control profile table index. */
   3098     soc_MA_INDEXm_field32_set(unit, &ma_idx_entry,
   3099                               OAM_OPCODE_CONTROL_PROFILE_PTRf,
   3100                               h_data_p->profile_index);
   3101 
   3102     /* Set CPU CoS queue value. */
   3103     if (ep_p->opcode_flags & BCM_OAM_OPCODE_CCM_COPY_TO_CPU) {
   3104         soc_MA_INDEXm_field32_set(unit, &ma_idx_entry,
   3105                                   INT_PRIf,
   3106                                   ep_p->cpu_qid);
   3107     }
   3108 
   3109     rv = WRITE_MA_INDEXm(unit, MEM_BLOCK_ALL, h_data_p->local_rx_index,
   3110                          &ma_idx_entry);
   3111     if (BCM_FAILURE(rv)) {
   3112         LOG_ERROR(BSL_LS_BCM_OAM,
   3113                   (BSL_META_U(unit,
   3114                               "OAM Error: MA_INDEX table write failed for EP=%d"
   3115                                "  %s.\n"), ep_p->id, bcm_errmsg(rv)));
   3116         return (rv);
   3117     }
   3118 
   3119     /* L3 entry */
   3120     L3_LOCK(unit);
   3121 
   3122     if (SOC_IS_HURRICANE2(unit) || SOC_IS_GREYHOUND(unit) ||
   3123         SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) {
   3124         mem = L3_ENTRY_IPV4_UNICASTm;
   3125     } else {
   3126         mem = L3_ENTRY_1m;
   3127     }
   3128 
   3129     /* Initialize L3 entry buffer. */
   3130     sal_memset(&l3_entry, 0, sizeof(l3_entry));
   3131 
   3132     if (BCM_SUCCESS
   3133             (_bcm_tr3_oam_find_lmep(unit, h_data_p, &l3_index, l3_entry))) {
   3134 
   3135         /* There's already an entry for this vlan + glp or 0 + vp */
   3136         mdl = soc_mem_field32_get(unit, mem,  &l3_entry, LMEP__MDL_BITMAPf);
   3137 
   3138         mdl |= (1 << ep_p->level);
   3139 
   3140         rv = soc_mem_field32_modify(unit, mem, l3_index,
   3141                                     LMEP__MDL_BITMAPf, mdl);
   3142         if (BCM_FAILURE(rv)) {
   3143             LOG_ERROR(BSL_LS_BCM_OAM,
   3144                       (BSL_META_U(unit,
   3145                                   "OAM Error: L3_ENTRY table update failed for EP=%d"
   3146                                    "  %s.\n"), ep_p->id, bcm_errmsg(rv)));
   3147             L3_UNLOCK(unit);
   3148             return (rv);
   3149         }
   3150     } else {
   3151 
   3152         /* This is the first entry at this vlan+glp */
   3153         sal_memset(&l3_entry, 0, sizeof(l3_entry));
   3154 
   3155         soc_mem_field32_set(unit, mem, &l3_entry, LMEP__MDL_BITMAPf,
   3156                                     (1 << ep_p->level));
   3157 
   3158         soc_mem_field32_set
   3159             (unit, mem, &l3_entry, LMEP__MA_BASE_PTRf,
   3160                 (h_data_p->local_rx_index >> _BCM_OAM_EP_LEVEL_BIT_COUNT));
   3161 
   3162         if (ep_p->flags & BCM_OAM_ENDPOINT_MATCH_INNER_VLAN) {
   3163             soc_mem_field32_set
   3164                 (unit, mem, &l3_entry, LMEP__EXP_TAG_STATUSf, 0x1);
   3165 
   3166             soc_mem_field32_set
   3167                 (unit, mem, &l3_entry, LMEP__EXP_TAG_STATUS_MASKf, 0x1);
   3168         } else if (ep_p->flags2 &
   3169                 BCM_OAM_ENDPOINT_FLAGS2_MATCH_SINGLE_TAGGED_OUTER_VLAN) {
   3170             soc_mem_field32_set
   3171                 (unit, mem, &l3_entry, LMEP__EXP_TAG_STATUSf, 0x2);
   3172 
   3173             soc_mem_field32_set
   3174                 (unit, mem, &l3_entry, LMEP__EXP_TAG_STATUS_MASKf, 0x3);
   3175         } else {
   3176             soc_mem_field32_set
   3177                 (unit, mem, &l3_entry, LMEP__EXP_TAG_STATUSf, 0x3);
   3178 
   3179             soc_mem_field32_set
   3180                 (unit, mem, &l3_entry, LMEP__EXP_TAG_STATUS_MASKf, 0x2);
   3181         }
   3182 
   3183         /* Construct LMEP view key for L3 Table insert operation. */
   3184 #ifdef BCM_HURRICANE2_SUPPORT
   3185         if (SOC_IS_HURRICANE2(unit) || SOC_IS_GREYHOUND(unit) ||
   3186             SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) {
   3187             _bcm_hu2_oam_lmep_key_construct(unit, h_data_p, 
   3188                                    (l3_entry_ipv4_unicast_entry_t *)l3_entry);
   3189         } else 
   3190 #endif /* BCM_HURRICANE2_SUPPORT */
   3191         {
   3192 #ifdef BCM_TRIUMPH3_SUPPORT
   3193             _bcm_oam_lmep_key_construct(unit, h_data_p, 
   3194                                         (l3_entry_1_entry_t *)l3_entry);
   3195 #endif
   3196         }
   3197         soc_mem_field32_set(unit, mem, &l3_entry, VALIDf, 1);
   3198 
   3199         rv = soc_mem_insert(unit, mem, MEM_BLOCK_ALL, &l3_entry);
   3200         if (BCM_FAILURE(rv)) {
   3201             LOG_ERROR(BSL_LS_BCM_OAM,
   3202                       (BSL_META_U(unit,
   3203                                   "OAM Error: L3_ENTRY table insert failed for EP=%d"
   3204                                    "  %s.\n"), ep_p->id, bcm_errmsg(rv)));
   3205             L3_UNLOCK(unit);
   3206             return (rv);
   3207         }
   3208     }
   3209 
   3210     L3_UNLOCK(unit);
   3211     
   3212     return (BCM_E_NONE);
   3213 }
   3214 
   3215 /*
   3216  * Function:
   3217  *     _bcm_oam_rx_endpoint_reserve
   3218  * Purpose:
   3219  *     Reserve an hardware index in the group state table to maintain the state
   3220  *     for a CCM Rx enabled endpoint.
   3221  * Parameters:
   3222  *     unit      - (IN) BCM device number
   3223  *     ep_info_p - (IN) Pointer to remote endpoint information.
   3224  * Retruns:
   3225  *     BCM_E_XXX
   3226  */
   3227 STATIC int
   3228 _bcm_oam_rx_endpoint_reserve(int unit, 
   3229                              const bcm_oam_endpoint_info_t *ep_info_p)
   3230 {
   3231     _bcm_oam_hash_data_t   *h_data_p;     /* Endpoint hash data pointer.      */
   3232     int                    rv;            /* Operation return status.         */
   3233     uint32                 l3_entry[SOC_MAX_MEM_WORDS];   /* L3 entry buffer. */
   3234     int                    l3_index = -1; /* L3 entry hardware index.         */
   3235     int                    count = 0;     /* Successful Hw indices allocated. */
   3236     uint8                  mdl = 0;       /* Maintenance domain level.        */
   3237     int                    rx_index[1 << _BCM_OAM_EP_LEVEL_BIT_COUNT] = {0};
   3238                                           /* Endpoint Rx hardware index.      */
   3239     uint16                 ma_base_idx;   /* Base pointer to endpoint state   */
   3240                                           /* table [MA_INDEX = (BASE + MDL)]. */
   3241     _bcm_oam_control_t     *oc;           /* Pointer to control structure.    */
   3242     const bcm_oam_endpoint_info_t *ep_p;  /* Pointer to endpoint information. */
   3243     soc_mem_t              mem;           /* L3 entry memory                  */
   3244 
   3245     if (NULL == ep_info_p) {
   3246         return (BCM_E_INTERNAL);
   3247     }
   3248 
   3249     /* Lock already taken by the calling routine. */
   3250     BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc));
   3251 
   3252     /* Initialize local endpoint information pointer. */
   3253     ep_p = ep_info_p;
   3254 
   3255     /* Get endpoint hash data pointer. */
   3256     h_data_p = &oc->oam_hash_data[ep_p->id];
   3257     if (!(h_data_p->in_use)) {
   3258         return (BCM_E_INTERNAL);
   3259     }
   3260 
   3261     
   3262     /* Initialize L3 entry buffer. */
   3263     sal_memset(&l3_entry, 0, sizeof(l3_entry));
   3264 
   3265     /* Find out if a matching entry already installed in hardware table. */
   3266     rv = _bcm_tr3_oam_find_lmep(unit, h_data_p, &l3_index, l3_entry);
   3267     if (BCM_FAILURE(rv)) {
   3268         /*
   3269          * If NO match found, allocate a new hardware index from MA_INDEX
   3270          * pool.
   3271          */
   3272 
   3273         /*
   3274          * Endpoint MDL values can be (0-7) i.e 8 MDLs are supported per-MA
   3275          * group endpoints. While allocating the base index, next 7 hardware
   3276          * indices are also reserved.
   3277          */
   3278         rv = shr_idxres_list_alloc_set(oc->ma_idx_pool, 8,
   3279                                        (shr_idxres_element_t *) rx_index,
   3280                                        (shr_idxres_element_t *) &count);
   3281         if (BCM_FAILURE(rv)) {
   3282             LOG_ERROR(BSL_LS_BCM_OAM,
   3283                       (BSL_META_U(unit,
   3284                                   "OAM Error: MA_INDEX index alloc failed EP:%d"
   3285                                    " %s.\n"), ep_p->id, bcm_errmsg(rv)));
   3286             return (rv);
   3287         } else {
   3288             LOG_DEBUG(BSL_LS_BCM_OAM,
   3289                       (BSL_META_U(unit,
   3290                                   "OAM Info: MA_INDEX alloc for EP:%d success."
   3291                                    " rx_idx_base:%p alloc-count:%d.\n"), ep_p->id,
   3292                        rx_index, count));
   3293         }
   3294 
   3295         /* Store hardware Rx index value for this endpoint. */
   3296         h_data_p->local_rx_index = (rx_index[0] + ep_p->level);
   3297     } else if (BCM_SUCCESS(rv)) {
   3298 
   3299         if (SOC_IS_HURRICANE2(unit) || SOC_IS_GREYHOUND(unit) ||
   3300             SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) {
   3301             mem = L3_ENTRY_IPV4_UNICASTm;
   3302         } else {
   3303             mem = L3_ENTRY_1m;
   3304         }
   3305         /* Matching entry found, get installed entry MDL value. */
   3306         mdl = soc_mem_field32_get(unit, mem, &l3_entry, LMEP__MDL_BITMAPf);
   3307 
   3308         /* Findout if MDLs are same. */
   3309         if (0 == (mdl & (1 << ep_p->level))) {
   3310             ma_base_idx = soc_mem_field32_get(unit, mem, &l3_entry,
   3311                                                       LMEP__MA_BASE_PTRf);
   3312             /*
   3313              * MDLs are not same, so calculate Rx index for this new endpoint.
   3314              * Endpoint MDL values can be (0-7). 8 MDLs are supported per-MA
   3315              * group. Base Rx index written to hardware, so multiply by 8
   3316              * i.e (<< _BCM_OAM_EP_LEVEL_BIT_COUNT) and add new endpoint MDL.
   3317              */
   3318             h_data_p->local_rx_index
   3319                 = ((ma_base_idx << _BCM_OAM_EP_LEVEL_BIT_COUNT)
   3320                     | ep_p->level);
   3321         } else {
   3322             /* Rx index already taken return error. */
   3323             LOG_ERROR(BSL_LS_BCM_OAM,
   3324                       (BSL_META_U(unit,
   3325                                   "OAM Error: No free Rx index found for EP:%d"
   3326                                    " %s.\n"), ep_p->id, bcm_errmsg(rv)));
   3327             return (BCM_E_RESOURCE);
   3328         }
   3329     }
   3330 
   3331     return (rv);
   3332 }
   3333 
   3334 /*
   3335  * Function:
   3336  *     _bcm_tr3_oam_remote_endpoint_delete
   3337  * Purpose:
   3338  *     Delete a remote endpoint.
   3339  * Parameters:
   3340  *     unit      - (IN) BCM device number
   3341  *     h_data_p  - (IN) Pointer to endpoint hash data
   3342  * Retruns:
   3343  *     BCM_E_XXX
   3344  */
   3345 STATIC int
   3346 _bcm_tr3_oam_remote_endpoint_delete(int unit,
   3347                                     _bcm_oam_hash_data_t *h_data_p)
   3348 {
   3349     _bcm_oam_control_t *oc;            /* Pointer to OAM control structure.  */
   3350     uint32             l3_entry[SOC_MAX_MEM_WORDS];/* RMEP view table entry. */
   3351     ma_state_entry_t   ma_state_entry; /* Group state machine table entry.   */
   3352     rmep_entry_t       rmep_entry;     /* Remote endpoint table entry.       */
   3353     int                rv;             /* Operation return status.           */
   3354     uint32 some_rmep_ccm_defect_counter = 0; /* No. of RMEPs in MA with CCM  */
   3355                                          /* defects.                         */
   3356     uint32 some_rdi_defect_counter = 0;  /* No. of RMEPs in MA with RDI      */
   3357                                          /* defects.                         */
   3358     uint32 cur_some_rdi_defect = 0;      /* Any RMEP in MA with RDI defect.  */
   3359     uint32 cur_some_rmep_ccm_defect = 0; /* Any RMEP in MA with CCM defect.  */
   3360     uint32 cur_rmep_ccm_defect = 0;      /* RMEP lookup failed or CCM        */
   3361                                          /* interval mismatch.               */
   3362     uint32 cur_rmep_last_rdi = 0;        /* Last CCM RDI Rx from this RMEP.  */
   3363     uint32 first, last, validLow, validHigh, freeCount, allocCount;
   3364 
   3365     /* Lock already taken by the calling routine. */
   3366     BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc));
   3367     sal_memset(&rmep_entry, 0, sizeof(rmep_entry_t));
   3368 
   3369     /* Get remote endpoint entry value from hardware. */
   3370     rv = READ_RMEPm(unit, MEM_BLOCK_ANY, h_data_p->remote_index, &rmep_entry);
   3371     if (BCM_FAILURE(rv)) {
   3372         LOG_ERROR(BSL_LS_BCM_OAM,
   3373                   (BSL_META_U(unit,
   3374                               "OAM Error: RMEP table read failed for EP=%d"
   3375                                "%s.\n"), h_data_p->ep_id, bcm_errmsg(rv)));
   3376         return (rv);
   3377     }
   3378 
   3379     cur_rmep_ccm_defect
   3380         = soc_RMEPm_field32_get(unit, &rmep_entry,
   3381                                 CURRENT_RMEP_CCM_DEFECTf);
   3382 
   3383     cur_rmep_last_rdi
   3384         = soc_RMEPm_field32_get(unit, &rmep_entry,
   3385                                 CURRENT_RMEP_LAST_RDIf);
   3386 
   3387     sal_memset(&ma_state_entry, 0, sizeof(ma_state_entry));
   3388     rv = READ_MA_STATEm(unit, MEM_BLOCK_ANY, h_data_p->group_index,
   3389                         &ma_state_entry);
   3390     if (BCM_FAILURE(rv)) {
   3391         LOG_ERROR(BSL_LS_BCM_OAM,
   3392                   (BSL_META_U(unit,
   3393                               "OAM Error: Group state (GID=%d) table read"
   3394                                " failed - %s.\n"), h_data_p->ep_id, bcm_errmsg(rv)));
   3395         return (rv);
   3396     }
   3397 
   3398     if ((0 != cur_rmep_ccm_defect) || (0 != cur_rmep_last_rdi)) {
   3399 
   3400         some_rmep_ccm_defect_counter
   3401             = soc_MA_STATEm_field32_get(unit, &ma_state_entry,
   3402                                         SOME_RMEP_CCM_DEFECT_COUNTERf);
   3403         cur_some_rmep_ccm_defect
   3404             = soc_MA_STATEm_field32_get(unit, &ma_state_entry,
   3405                                         CURRENT_SOME_RMEP_CCM_DEFECTf);
   3406 
   3407         if ((0 != cur_rmep_ccm_defect)
   3408             && (some_rmep_ccm_defect_counter > 0)) {
   3409             --some_rmep_ccm_defect_counter;
   3410             soc_MA_STATEm_field32_set
   3411                 (unit, &ma_state_entry, SOME_RMEP_CCM_DEFECT_COUNTERf,
   3412                  some_rmep_ccm_defect_counter);
   3413 
   3414             if (0 == some_rmep_ccm_defect_counter) {
   3415                 cur_some_rmep_ccm_defect = 0;
   3416                 soc_MA_STATEm_field32_set
   3417                     (unit, &ma_state_entry, CURRENT_SOME_RMEP_CCM_DEFECTf,
   3418                      cur_some_rmep_ccm_defect);
   3419             }
   3420         }
   3421 
   3422         some_rdi_defect_counter
   3423             = soc_MA_STATEm_field32_get(unit, &ma_state_entry,
   3424                                         SOME_RDI_DEFECT_COUNTERf);
   3425         cur_some_rdi_defect
   3426             = soc_MA_STATEm_field32_get(unit, &ma_state_entry,
   3427                                         CURRENT_SOME_RDI_DEFECTf);
   3428 
   3429         if ((0 != cur_rmep_last_rdi)
   3430             && (some_rdi_defect_counter > 0)) {
   3431             --some_rdi_defect_counter;
   3432             soc_MA_STATEm_field32_set
   3433                 (unit, &ma_state_entry, SOME_RDI_DEFECT_COUNTERf,
   3434                  some_rdi_defect_counter);
   3435 
   3436             if (0 == some_rdi_defect_counter) {
   3437                 cur_some_rdi_defect = 0;
   3438                 soc_MA_STATEm_field32_set
   3439                     (unit, &ma_state_entry, CURRENT_SOME_RDI_DEFECTf,
   3440                      cur_some_rdi_defect);
   3441             }
   3442         }
   3443 
   3444         rv = WRITE_MA_STATEm(unit, MEM_BLOCK_ALL, h_data_p->group_index,
   3445                              &ma_state_entry);
   3446         if (BCM_FAILURE(rv)) {
   3447             LOG_ERROR(BSL_LS_BCM_OAM,
   3448                       (BSL_META_U(unit,
   3449                                   "OAM Error: Group state (GID=%d) table write"
   3450                                    " failed - %s.\n"), h_data_p->group_index,
   3451                        bcm_errmsg(rv)));
   3452             return (rv);
   3453         }
   3454     }
   3455 
   3456     /* Clear RMEP table entry for this endpoint index. */
   3457     sal_memset(&rmep_entry, 0, sizeof(rmep_entry_t));
   3458     rv = WRITE_RMEPm(unit, MEM_BLOCK_ALL, h_data_p->remote_index,
   3459                      &rmep_entry);
   3460     if (BCM_FAILURE(rv)) {
   3461         LOG_ERROR(BSL_LS_BCM_OAM,
   3462                   (BSL_META_U(unit,
   3463                               "OAM Error: RMEP table write index=%x (EP=%d)"
   3464                                " - %s.\n"), h_data_p->remote_index,
   3465                    h_data_p->ep_id, bcm_errmsg(rv)));
   3466         return (rv);
   3467     }
   3468 
   3469     sal_memset(&l3_entry, 0, sizeof(l3_entry));
   3470 
   3471     /* Construct endpoint RMEP view key for L3 Table entry delete operation. */
   3472 #ifdef BCM_HURRICANE2_SUPPORT
   3473     if (SOC_IS_HURRICANE2(unit) || SOC_IS_GREYHOUND(unit) ||
   3474         SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) {
   3475         _bcm_hu2_oam_rmep_key_construct(unit, h_data_p, 
   3476                                     (l3_entry_ipv4_unicast_entry_t *)l3_entry);
   3477         rv = soc_mem_delete(unit, L3_ENTRY_IPV4_UNICASTm, 
   3478                             MEM_BLOCK_ALL, &l3_entry);
   3479     } else 
   3480 #endif /* BCM_HURRICANE2_SUPPORT */
   3481     {
   3482 #ifdef BCM_TRIUMPH3_SUPPORT
   3483         _bcm_oam_rmep_key_construct(unit, h_data_p, 
   3484                                     (l3_entry_1_entry_t *)l3_entry);
   3485         rv = soc_mem_delete(unit, L3_ENTRY_1m, MEM_BLOCK_ALL, &l3_entry);
   3486 #endif
   3487     }
   3488     if (BCM_FAILURE(rv) && (oc->init)) {
   3489         LOG_ERROR(BSL_LS_BCM_OAM,
   3490                   (BSL_META_U(unit,
   3491                               "OAM Error: RMEP view update (EP=%d)"
   3492                                " - %s.\n"), h_data_p->ep_id, bcm_errmsg(rv)));
   3493         return (rv);
   3494     }
   3495 
   3496     /* Return ID back to free RMEP ID pool. */
   3497     BCM_IF_ERROR_RETURN
   3498         (shr_idxres_list_free(oc->rmep_pool, h_data_p->remote_index));
   3499 
   3500     rv = shr_idxres_list_state(oc->rmep_pool,
   3501                                    &first, &last,
   3502                                    &validLow, &validHigh,
   3503                                    &freeCount, &allocCount);
   3504     if (BCM_FAILURE(rv)) {
   3505         LOG_ERROR(BSL_LS_BCM_OAM,
   3506                   (BSL_META_U(unit,
   3507                               "OAM Error: RMEP pool state get failed "
   3508                                " - %s.\n"), bcm_errmsg(rv)));
   3509         return (rv);
   3510     }
   3511 
   3512     if(allocCount == 0)
   3513     {
   3514         soc_MA_STATEm_field32_set
   3515             (unit, &ma_state_entry, CURRENT_XCON_CCM_DEFECTf,
   3516              0);
   3517         soc_MA_STATEm_field32_set
   3518             (unit, &ma_state_entry, CURRENT_ERROR_CCM_DEFECTf,
   3519              0);
   3520         soc_MA_STATEm_field32_set
   3521             (unit, &ma_state_entry, STICKY_ERROR_CCM_DEFECTf,
   3522              0);
   3523         soc_MA_STATEm_field32_set
   3524             (unit, &ma_state_entry, ERROR_CCM_DEFECT_TIMESTAMPf,
   3525              0);
   3526         soc_MA_STATEm_field32_set
   3527             (unit, &ma_state_entry, ERROR_CCM_DEFECT_RECEIVE_CCMf,
   3528              0);
   3529         rv = WRITE_MA_STATEm(unit, MEM_BLOCK_ALL, h_data_p->group_index,
   3530                 &ma_state_entry);
   3531         if (BCM_FAILURE(rv)) {
   3532             LOG_ERROR(BSL_LS_BCM_OAM,
   3533                     (BSL_META_U(unit,
   3534                                 "OAM Error: Group state (GID=%d) table write"
   3535                                 " failed - %s.\n"), h_data_p->group_index,
   3536                      bcm_errmsg(rv)));
   3537             return (rv);
   3538         }
   3539     } 
   3540     /* Clear the H/w index to logical index Mapping for RMEP */
   3541     oc->remote_endpoints[h_data_p->remote_index] = BCM_OAM_ENDPOINT_INVALID; 
   3542 
   3543     return (BCM_E_NONE);
   3544 }
   3545 
   3546 /*
   3547  * Function:
   3548  *     _bcm_tr3_oam_local_endpoint_delete
   3549  * Purpose:
   3550  *     Delete a local endpoint.
   3551  * Parameters:
   3552  *     unit      - (IN) BCM device number
   3553  *     h_data_p  - (IN) Pointer to endpoint hash data
   3554  * Retruns:
   3555  *     BCM_E_XXX
   3556  */
   3557 STATIC int
   3558 _bcm_tr3_oam_local_endpoint_delete(int unit, _bcm_oam_hash_data_t *h_data_p)
   3559 {
   3560     _bcm_oam_control_t *oc;            /* Pointer to OAM control structure. */
   3561     uint32             l3_entry[SOC_MAX_MEM_WORDS];/* LMEP view table entry.*/ 
   3562     lmep_entry_t       lmep_entry;     /* Local endpoint table entry.       */
   3563     int                l3_index = -1;  /* L3 table hardware index.          */
   3564     uint8              mdl;            /* Maintenance domain level.         */
   3565     int                rv;             /* Operation return status.          */
   3566     uint32             ma_base_index;  /* Endpoint tbl base index. */
   3567     uint32 rx_index[1 << _BCM_OAM_EP_LEVEL_BIT_COUNT] = {0};
   3568                                        /* Endpoint Rx hardware index.       */
   3569     uint32 count;                      /* No. of Rx indices freed           */
   3570                                        /* successfully.                     */
   3571     int                idx;            /* Iterator variable.                */
   3572     soc_mem_t          mem;            /* L3 entry memory                  */
   3573 #ifdef BCM_HURRICANE2_SUPPORT
   3574     uint32  rval = 0;
   3575     uint8   tx_disable = 0;
   3576 #endif /* BCM_HURRICANE2_SUPPORT */
   3577 
   3578     if (NULL == h_data_p){
   3579         return (BCM_E_INTERNAL);
   3580     }
   3581     
   3582     /* Lock already taken by the calling routine. */
   3583     BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc));
   3584 
   3585 
   3586     if (1 == h_data_p->local_tx_enabled) {
   3587 
   3588         /* Clear endpoint Tx config in hardware. */
   3589         sal_memset(&lmep_entry, 0, sizeof(lmep_entry_t));
   3590 
   3591     /*HW WAR to fix the issue of wrong LMEP index being written
   3592       while deleting and adding same MEP in a loop */
   3593 #ifdef BCM_HURRICANE2_SUPPORT
   3594         rv = _bcm_oam_modify_oam_tx_control (unit, &rval, 1, &tx_disable);
   3595         if (BCM_FAILURE(rv)) { 
   3596             LOG_ERROR(BSL_LS_BCM_OAM,
   3597                     (BSL_META_U(unit,
   3598                                 "OAM Error: in _bcm_oam_modify_oam_tx_control \n")));
   3599             return (rv);
   3600         }
   3601 #endif /* BCM_HURRICANE2_SUPPORT */
   3602         rv = WRITE_LMEPm(unit, MEM_BLOCK_ALL, h_data_p->local_tx_index,
   3603                          &lmep_entry);
   3604 
   3605 #ifdef BCM_HURRICANE2_SUPPORT
   3606         if (tx_disable) {
   3607             rv = _bcm_oam_modify_oam_tx_control (unit, &rval, 0, &tx_disable);
   3608             if (BCM_FAILURE(rv)) {
   3609                 LOG_ERROR(BSL_LS_BCM_OAM,
   3610                         (BSL_META_U(unit,
   3611                                     "OAM Error: in _bcm_oam_modify_oam_tx_control \n")));
   3612                 return (rv);
   3613             }
   3614         }
   3615 #endif /* BCM_HURRICANE2_SUPPORT */
   3616         if (BCM_FAILURE(rv)) {
   3617             LOG_ERROR(BSL_LS_BCM_OAM,
   3618                       (BSL_META_U(unit,
   3619                                   "OAM Error: LMEP table write (EP=%d)"
   3620                                    " failed - %s.\n"), h_data_p->ep_id, bcm_errmsg(rv)));
   3621             return (rv);
   3622         }
   3623 
   3624         /* Return ID back to free LMEP ID pool. */
   3625         BCM_IF_ERROR_RETURN
   3626             (shr_idxres_list_free(oc->lmep_pool, h_data_p->local_tx_index));
   3627     }
   3628 
   3629     if (1 == h_data_p->local_rx_enabled) {
   3630 
   3631         /* If LM DM is enabled, delete FP entries created for the same */
   3632         if ( h_data_p->flags & 
   3633              (BCM_OAM_ENDPOINT_LOSS_MEASUREMENT | 
   3634               BCM_OAM_ENDPOINT_DELAY_MEASUREMENT) ) {
   3635             rv = _bcm_tr3_oam_loss_delay_measurement_delete(unit, oc, h_data_p);
   3636             if (BCM_FAILURE(rv)) {
   3637                 LOG_ERROR(BSL_LS_BCM_OAM,
   3638                           (BSL_META_U(unit,
   3639                                       "OAM Error: LM DM delete failed (EP=%d)"
   3640                                        "- %s.\n"), h_data_p->ep_id, bcm_errmsg(rv)));
   3641                 return (rv);
   3642             }
   3643         }
   3644 
   3645        
   3646         /* Delete OAM opcode profile entry for this endpoint. */
   3647         rv = soc_profile_mem_delete(unit, &oc->oam_opcode_control_profile,
   3648                                     h_data_p->profile_index);
   3649 
   3650         if (BCM_FAILURE(rv)) {
   3651             LOG_ERROR(BSL_LS_BCM_OAM,
   3652                       (BSL_META_U(unit,
   3653                                   "OAM Error: Profile table update error (idx=%d)"
   3654                                    "- %s.\n"), h_data_p->profile_index, bcm_errmsg(rv)));
   3655             return (rv);
   3656         }
   3657  
   3658         /* Initialize L3 entry buffer. */
   3659         sal_memset(&l3_entry, 0, sizeof(l3_entry));
   3660 
   3661         rv = _bcm_tr3_oam_find_lmep(unit, h_data_p, &l3_index, l3_entry);
   3662         if (BCM_SUCCESS(rv)) {
   3663             if (SOC_IS_HURRICANE2(unit) || SOC_IS_GREYHOUND(unit) ||
   3664                 SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) {
   3665                 mem = L3_ENTRY_IPV4_UNICASTm;
   3666             } else {
   3667                 mem = L3_ENTRY_1m;
   3668             }
   3669             /* Endpoint found, get MDL bitmap value. */
   3670             mdl = soc_mem_field32_get(unit, mem, &l3_entry,
   3671                                               LMEP__MDL_BITMAPf);
   3672 
   3673             /* Clear the MDL bit for this endpoint. */
   3674             mdl &= ~(1 << h_data_p->level);
   3675 
   3676             /* Take L3 module protection mutex to block any updates. */
   3677             L3_LOCK(unit);
   3678  
   3679             if (0 != mdl) {
   3680                 /* Valid endpoints exist for other MDLs at this index. */
   3681                 rv = soc_mem_field32_modify(unit, mem, l3_index,
   3682                                             LMEP__MDL_BITMAPf, mdl);
   3683             } else {
   3684                 rv = soc_mem_delete_index(unit, mem, MEM_BLOCK_ALL,
   3685                                           l3_index);
   3686             }
   3687 
   3688             L3_UNLOCK(unit);
   3689 
   3690             if (BCM_FAILURE(rv)) {
   3691                 LOG_ERROR(BSL_LS_BCM_OAM,
   3692                           (BSL_META_U(unit,
   3693                                       "OAM Error: LMEP view update (EP=%d) -"
   3694                                        " %s.\n"), h_data_p->ep_id, bcm_errmsg(rv)));
   3695                 return (rv);
   3696             }
   3697 
   3698             /* This is the last Rx endpoint in this OAM group. */
   3699             if (0 == mdl) {
   3700                 ma_base_index = soc_mem_field32_get(unit, mem, &l3_entry,
   3701                                                             LMEP__MA_BASE_PTRf);
   3702                 /* Return Rx indices to free pool. */
   3703                 for (idx = 0; idx < (1 << _BCM_OAM_EP_LEVEL_BIT_COUNT); idx++) {
   3704                     rx_index[idx] = (ma_base_index << _BCM_OAM_EP_LEVEL_BIT_COUNT)
   3705                                         + idx;
   3706                 }
   3707 
   3708                 rv = shr_idxres_list_free_set(oc->ma_idx_pool, 8,
   3709                                               (shr_idxres_element_t *) rx_index,
   3710                                               (shr_idxres_element_t *) &count);
   3711                 if (BCM_FAILURE(rv) || (8 != count)) {
   3712                     LOG_ERROR(BSL_LS_BCM_OAM,
   3713                               (BSL_META_U(unit,
   3714                                           "OAM Error: Rx index list free (EP=%d)"
   3715                                            " (count=%d).\n"), h_data_p->ep_id, count));
   3716                     return (rv);
   3717                 }
   3718             }
   3719         } else if (BCM_FAILURE(rv) && (oc->init)) {
   3720             LOG_ERROR(BSL_LS_BCM_OAM,
   3721                       (BSL_META_U(unit,
   3722                                   "OAM Error: LMEP table write (EP=%d) -"
   3723                                    " %s.\n"), h_data_p->ep_id, bcm_errmsg(rv)));
   3724             return (rv);
   3725         }
   3726     }
   3727 
   3728 /*SDK-147457:HW WAR to fix the issue of wrong LMEP index being written
   3729   while deleting and adding same MEP in a loop */
   3730 #ifdef BCM_HURRICANE2_SUPPORT
   3731     sal_usleep(3400);
   3732 #endif /* BCM_HURRICANE2_SUPPORT */
   3733 
   3734     return (BCM_E_NONE);
   3735 }
   3736 
   3737 
   3738 /*
   3739  * Function:
   3740  *     _bcm_tr3_oam_endpoint_destroy
   3741  * Purpose:
   3742  *     Delete an endpoint and free all its allocated resources.
   3743  * Parameters:
   3744  *     unit   - (IN) BCM device number
   3745  *     ep_id  - (IN) Endpoint ID value.
   3746  * Retruns:
   3747  *     BCM_E_XXX
   3748  */
   3749 STATIC int
   3750 _bcm_tr3_oam_endpoint_destroy(int unit,
   3751                               bcm_oam_endpoint_t ep_id)
   3752 {
   3753     _bcm_oam_control_t      *oc;        /* Pointer to OAM control structure. */
   3754     _bcm_oam_hash_data_t    *h_data_p;  /* Pointer to endpoint data.         */
   3755     _bcm_oam_hash_key_t     hash_key;   /* Hash key buffer for lookup.       */
   3756     bcm_oam_endpoint_info_t ep_info;    /* Endpoint information.             */
   3757     _bcm_oam_hash_data_t    h_data;     /* Pointer to endpoint data.         */
   3758     int                     rv;         /* Operation return status.          */
   3759 #if defined(BCM_TRIUMPH3_SUPPORT) && defined(INCLUDE_BHH)
   3760     uint16 reply_len;
   3761     bcm_oam_endpoint_t bhh_pool_ep_id;
   3762 #endif
   3763 
   3764     /* Lock already taken by the calling routine. */
   3765     BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc));
   3766 
   3767     /* Get the hash data pointer. */
   3768     h_data_p = &oc->oam_hash_data[ep_id];
   3769     if(0 == h_data_p->in_use){
   3770         return BCM_E_NOT_FOUND; 
   3771     } 
   3772 
   3773     if(bcmOAMEndpointTypeEthernet == h_data_p->type)
   3774     {
   3775     /* Remove endpoint for group's endpoint list. */
   3776     rv = _bcm_oam_group_ep_list_remove(unit, h_data_p->group_index,
   3777                                        h_data_p->ep_id);
   3778     if (BCM_FAILURE(rv)) {
   3779         LOG_ERROR(BSL_LS_BCM_OAM,
   3780                   (BSL_META_U(unit,
   3781                               "OAM Error: Remove from group list (EP=%d) -"
   3782                                " %s.\n"), ep_id, bcm_errmsg(rv)));
   3783         return (rv);
   3784     }
   3785 
   3786     if (h_data_p->flags & BCM_OAM_ENDPOINT_REMOTE) {
   3787         BCM_IF_ERROR_RETURN
   3788                 (_bcm_tr3_oam_remote_endpoint_delete(unit, h_data_p));
   3789 
   3790     } else {
   3791         BCM_IF_ERROR_RETURN
   3792             (_bcm_tr3_oam_local_endpoint_delete(unit, h_data_p));
   3793     }
   3794 
   3795     /* Return ID back to free MEP ID pool.*/
   3796     BCM_IF_ERROR_RETURN(shr_idxres_list_free(oc->mep_pool, ep_id));
   3797 
   3798     /* Initialize endpoint info structure. */
   3799     bcm_oam_endpoint_info_t_init(&ep_info);
   3800 
   3801     /* Set up endpoint information for key construction. */
   3802     ep_info.group = h_data_p->group_index;
   3803     ep_info.name = h_data_p->name;
   3804     ep_info.gport = h_data_p->gport;
   3805     ep_info.level = h_data_p->level;
   3806     ep_info.vlan = h_data_p->vlan;
   3807 
   3808     /* Construct hash key for lookup + delete operation. */
   3809     _bcm_oam_ep_hash_key_construct(unit, oc, &ep_info, &hash_key);
   3810 
   3811     /* Remove entry from hash table. */
   3812     BCM_IF_ERROR_RETURN(shr_htb_find(oc->ma_mep_htbl, hash_key,
   3813                                      (shr_htb_data_t *)&h_data,
   3814                                      1));
   3815 
   3816     /* Clear the hash data memory previously occupied by this endpoint. */
   3817     _BCM_OAM_HASH_DATA_CLEAR(h_data_p);
   3818     }
   3819     /*
   3820      * BHH specific
   3821      */
   3822     else if (soc_feature(unit, soc_feature_bhh) && 
   3823         ((bcmOAMEndpointTypeBHHMPLS == h_data_p->type) ||
   3824          (bcmOAMEndpointTypeBHHMPLSVccv == h_data_p->type))) {
   3825 #if defined(BCM_TRIUMPH3_SUPPORT) && defined(INCLUDE_BHH)
   3826 
   3827         if (h_data_p->is_remote) {
   3828             /* 
   3829             * BHH uses same index for local and remote.  So, delete always goes through
   3830             * local endpoint destory
   3831             */
   3832             return (BCM_E_NONE);
   3833         } else {
   3834 
   3835             bhh_pool_ep_id = BCM_OAM_BHH_GET_UKERNEL_EP(ep_id);
   3836 
   3837             /* Delete BHH Session in HW. BCM_E_NOT_FOUND is not an error when
   3838                switch is re-initializing as entry would have been already 
   3839                deleted by respective module init. */ 
   3840             rv = _bcm_tr3_oam_bhh_session_hw_delete(unit, h_data_p);
   3841             if (BCM_FAILURE(rv) && rv != BCM_E_NOT_FOUND) {
   3842                 LOG_ERROR(BSL_LS_BCM_OAM,
   3843                           (BSL_META_U(unit,
   3844                                       "OAM Error: bhh_session_hw_delete failled " 
   3845                                        "(EP=%d) - %s.\n"), ep_id, bcm_errmsg(rv)));
   3846                 return (rv);
   3847             }
   3848 
   3849             /* Send BHH Session Delete message to uC. Error response is not an  
   3850                during switch re-init as uKernel is reloaded and its state is 
   3851                cleared before oam init. As such endpoint wont exist during oam init*/
   3852             _bcm_tr3_oam_bhh_msg_send_receive(unit, 
   3853                           MOS_MSG_SUBCLASS_BHH_SESS_DELETE,
   3854                           (int)bhh_pool_ep_id, 0,
   3855                           MOS_MSG_SUBCLASS_BHH_SESS_DELETE_REPLY,
   3856                           &reply_len, _BHH_UC_MSG_TIMEOUT_USECS);
   3857 
   3858             h_data_p->in_use = 0;
   3859 
   3860             /* Remove endpoint for group's endpoint list. */
   3861             rv = _bcm_oam_group_ep_list_remove(unit, h_data_p->group_index,
   3862                                        h_data_p->ep_id);
   3863             if (BCM_FAILURE(rv)) {
   3864                 LOG_ERROR(BSL_LS_BCM_OAM,
   3865                           (BSL_META_U(unit,
   3866                                       "OAM Error: Remove from group list (EP=%d) -"
   3867                                        " %s.\n"), ep_id, bcm_errmsg(rv)));
   3868                 return (rv);
   3869             }
   3870 
   3871             /* Return ID back to free MEP ID pool.*/
   3872             BCM_IF_ERROR_RETURN(shr_idxres_list_free(oc->bhh_pool, bhh_pool_ep_id));
   3873         }
   3874 #else
   3875         return (BCM_E_UNAVAIL);
   3876 #endif /* INCLUDE_BHH */
   3877     }
   3878     else {
   3879         return (BCM_E_PARAM);
   3880     }
   3881 
   3882     return (BCM_E_NONE);
   3883 }
   3884 
   3885 /*
   3886  * Function:
   3887  *     _bcm_tr3_oam_group_endpoints_destroy
   3888  * Purpose:
   3889  *     Delete all endpoints associated with a group and free all
   3890  *     resources allocated by these endpoints. 
   3891  * Parameters:
   3892  *     unit      - (IN) BCM device number
   3893  *     g_info_p  - (IN) Pointer to group information
   3894  * Retruns:
   3895  *     BCM_E_XXX
   3896  */
   3897 STATIC int
   3898 _bcm_tr3_oam_group_endpoints_destroy(int unit,
   3899                                      _bcm_oam_group_data_t *g_info_p)
   3900 {
   3901     bcm_oam_endpoint_t    ep_id; /* Endpoint ID.                   */
   3902     _bcm_oam_ep_list_t    *cur;  /* Pointer to endpoint list node. */
   3903     int                   rv;    /* Operation return status.       */
   3904 
   3905     if (NULL == g_info_p) {
   3906         return (BCM_E_INTERNAL);
   3907     }
   3908 
   3909     /* Get the endpoint list head pointer. */
   3910     cur = *(g_info_p->ep_list);
   3911     if (NULL == cur) {
   3912         LOG_DEBUG(BSL_LS_BCM_OAM,
   3913                   (BSL_META_U(unit,
   3914                               "OAM Info: No endpoints in group.\n")));
   3915         return (BCM_E_NONE);
   3916     }
   3917 
   3918     while (NULL != cur) {
   3919         ep_id = cur->ep_data_p->ep_id;
   3920 
   3921         LOG_DEBUG(BSL_LS_BCM_OAM,
   3922                   (BSL_META_U(unit,
   3923                               "OAM Info: GID=%d EP:%d.\n"),
   3924                    cur->ep_data_p->group_index, ep_id));
   3925 
   3926         cur = cur->next;
   3927 
   3928         rv = _bcm_tr3_oam_endpoint_destroy(unit, ep_id);
   3929         if (BCM_FAILURE(rv)) {
   3930             LOG_ERROR(BSL_LS_BCM_OAM,
   3931                       (BSL_META_U(unit,
   3932                                   "OAM Error: Endpoint destroy (EP=%d) - "
   3933                                    "%s.\n"), ep_id, bcm_errmsg(rv)));
   3934             return (rv);
   3935         }
   3936     }
   3937 
   3938     return (BCM_E_NONE);
   3939 }
   3940 
   3941 /*
   3942  * Function:
   3943  *     _bcm_tr3_oam_endpoint_gport_resolve
   3944  * Purpose:
   3945  *     Resolve an endpoint GPORT value to SGLP and DGLP value.
   3946  * Parameters:
   3947  *     unit       - (IN) BCM device number
   3948  *     ep_info_p  - (IN) Pointer to endpoint information.
   3949  *     src_glp    - (IN/OUT) Pointer to source generic logical port value.
   3950  *     dst_glp    - (IN/OUT) Pointer to destination generic logical port value.
   3951  *     tx_gport   - (OUT) Gport on which PDUs need to be sent
   3952  * Retruns:
   3953  *     BCM_E_XXX
   3954  */
   3955 STATIC int
   3956 _bcm_tr3_oam_endpoint_gport_resolve(int unit, bcm_oam_endpoint_info_t *ep_info_p,
   3957                                     uint32 *src_glp, uint32 *dst_glp,
   3958                                     bcm_trunk_t *trunk_id, bcm_gport_t *tx_gport)
   3959 {
   3960     bcm_module_t       module_id;            /* Module ID           */
   3961     bcm_port_t         port_id;              /* Port ID.            */
   3962     int                local_id;             /* Hardware ID.        */
   3963     int                tx_enabled = 0;       /* CCM Tx enabled.     */
   3964     bcm_trunk_info_t   trunk_info;           /* Trunk information.  */
   3965     bcm_trunk_member_t *member_array = NULL; /* Trunk member array. */
   3966     bcm_trunk_t        tmp_trunk_id;         /* Temp Trunk id */
   3967     int                member_count = 0;     /* Trunk Member count. */
   3968     int                rv;                   /* Return status.      */
   3969     uint8              glp_valid = 0;        /* Logical port valid. */
   3970 
   3971     /* Get Trunk ID or (Modid + Port) value from Gport */
   3972     BCM_IF_ERROR_RETURN
   3973         (_bcm_esw_gport_resolve(unit, ep_info_p->gport, &module_id,
   3974                                 &port_id, trunk_id, &local_id));
   3975 
   3976     /* Set CCM endpoint Tx status only for local endpoints. */
   3977     if (!(ep_info_p->flags & BCM_OAM_ENDPOINT_REMOTE)) {
   3978         tx_enabled
   3979             = (ep_info_p->ccm_period
   3980                 != BCM_OAM_ENDPOINT_CCM_PERIOD_DISABLED) ? 1 : 0;
   3981     }
   3982 
   3983     /*
   3984      * If Gport is Trunk type, _bcm_esw_gport_resolve()
   3985      * sets trunk_id. Using Trunk ID, get Dst Modid and Port value.
   3986      */
   3987     if (BCM_GPORT_IS_TRUNK(ep_info_p->gport) &&
   3988         (BCM_TRUNK_INVALID == *trunk_id)) {
   3989         /* Has to be a valid Trunk. */
   3990         return (BCM_E_PARAM);
   3991     }
   3992 
   3993     if (BCM_TRUNK_INVALID != *trunk_id)  {
   3994 
   3995         /*
   3996          * CCM Tx is enabled on a trunk member port.
   3997          * trunk_index value is required to derive the Modid and Port info.
   3998          */
   3999         if (1 == tx_enabled
   4000             && _BCM_OAM_INVALID_INDEX == ep_info_p->trunk_index) {
   4001             /* Invalid Trunk member index passed. */
   4002             return (BCM_E_PORT);
   4003         }
   4004 
   4005         /* Construct Hw SGLP value. */
   4006         _BCM_TR3_OAM_MOD_PORT_TO_GLP(unit, module_id, port_id, 1, *trunk_id,
   4007             *src_glp);
   4008 
   4009         /* Get count of ports in this trunk. */
   4010         BCM_IF_ERROR_RETURN
   4011             (bcm_esw_trunk_get(unit, *trunk_id, NULL, 0, NULL, &member_count));
   4012         if (0 == member_count) {
   4013             /* No members have been added to the trunk group yet */
   4014             return (BCM_E_PARAM);
   4015         }
   4016         
   4017         _BCM_OAM_ALLOC(member_array, bcm_trunk_member_t,
   4018                        sizeof(bcm_trunk_member_t) * member_count, "Trunk info");
   4019         if (NULL == member_array) {
   4020             return (BCM_E_MEMORY);
   4021         }
   4022 
   4023         /* Get Trunk Info for the Trunk ID. */
   4024         rv = bcm_esw_trunk_get(unit, *trunk_id, &trunk_info, member_count,
   4025                                member_array, &member_count);
   4026         if (BCM_FAILURE(rv)) {
   4027             sal_free(member_array);
   4028             return (rv);
   4029         }
   4030 
   4031         /* Check if the input trunk_index is valid. */
   4032         if (ep_info_p->trunk_index >= member_count) {
   4033             sal_free(member_array);
   4034             return (BCM_E_PARAM);
   4035         }
   4036 
   4037         /* Get the Modid and Port value using Trunk Index value. */
   4038         rv = _bcm_esw_gport_resolve
   4039                 (unit, member_array[ep_info_p->trunk_index].gport,
   4040                  &module_id, &port_id, &tmp_trunk_id, &local_id);
   4041         if (BCM_FAILURE(rv)) {
   4042             sal_free(member_array);
   4043             return (rv);
   4044         }
   4045 
   4046         sal_free(member_array);
   4047 
   4048         /* Construct Hw DGLP value. */
   4049         _BCM_TR3_OAM_MOD_PORT_TO_DGLP(unit, module_id, port_id, 0, -1,
   4050             *dst_glp);
   4051         *tx_gport = member_array[ep_info_p->trunk_index].gport;
   4052         glp_valid = 1;
   4053     }
   4054 
   4055     /*
   4056      * Application can resolve the trunk and pass the desginated
   4057      * port as Gport value. Check if the Gport belongs to a trunk.
   4058      */
   4059     if ((BCM_TRUNK_INVALID == *trunk_id)
   4060         && (BCM_GPORT_IS_MODPORT(ep_info_p->gport)
   4061         || BCM_GPORT_IS_LOCAL(ep_info_p->gport))) {
   4062 
   4063         /* When Gport is ModPort or Port type, _bcm_esw_gport_resolve()
   4064          * returns Modid and Port value. Use these values to make the DGLP
   4065          * value.
   4066          */
   4067         _BCM_TR3_OAM_MOD_PORT_TO_DGLP(unit, module_id, port_id, 0, -1,
   4068             *dst_glp);
   4069 
   4070         /* Use the Modid, Port value and determine if the port
   4071          * belongs to a Trunk.
   4072          */
   4073         rv = bcm_esw_trunk_find(unit, module_id, port_id, trunk_id);
   4074         if (BCM_SUCCESS(rv)) {
   4075             /*
   4076              * Port is member of a valid trunk.
   4077              * Now create the SGLP value from Trunk ID.
   4078              */
   4079             _BCM_TR3_OAM_MOD_PORT_TO_GLP(unit, module_id, port_id, 1, *trunk_id,
   4080                 *src_glp);
   4081 
   4082         } else {
   4083             /* Port not a member of trunk. Construct SGLP */
   4084             _BCM_TR3_OAM_MOD_PORT_TO_GLP(unit, module_id, port_id, 0, -1,
   4085                                           *src_glp);
   4086         }
   4087         glp_valid = 1;
   4088         BCM_GPORT_MODPORT_SET(*tx_gport, module_id, port_id);
   4089     }
   4090 
   4091     if (BCM_GPORT_IS_MIM_PORT(ep_info_p->gport) ||
   4092         BCM_GPORT_IS_MPLS_PORT(ep_info_p->gport)) {
   4093 
   4094         _BCM_TR3_OAM_MOD_PORT_TO_GLP(unit, module_id, port_id, 0, -1, *src_glp);
   4095         _BCM_TR3_OAM_MOD_PORT_TO_DGLP(unit, module_id, port_id, 0, -1, *dst_glp);
   4096         BCM_GPORT_MODPORT_SET(*tx_gport, module_id, port_id);
   4097         glp_valid = 1;
   4098     }
   4099 
   4100     /*
   4101      * At this point, both src_glp and dst_glp should be valid.
   4102      * Gport types other than TRUNK, MODPORT or LOCAL are not valid.
   4103      */
   4104     if (0 == glp_valid) {
   4105         return (BCM_E_PORT);
   4106     }
   4107 
   4108     return (BCM_E_NONE);
   4109 }
   4110 
   4111 /*
   4112  * Function:
   4113  *     _bcm_tr3_oam_mepid_validate
   4114  * Purpose:
   4115  *     Validate an endpoint MEP id.
   4116  * Parameters:
   4117  *     unit      - (IN) BCM device number
   4118  *     ep_info_p - (IN) Pointer to endpoint information.
   4119  * Retruns:
   4120  *     BCM_E_XXX
   4121  */
   4122 STATIC int
   4123 _bcm_tr3_oam_mepid_validate(int unit,  
   4124                             bcm_oam_endpoint_info_t *ep_info_p)
   4125 {
   4126     _bcm_oam_control_t *oc;
   4127     _bcm_oam_group_data_t *group_p;   /* Pointer to group list.         */
   4128     _bcm_oam_ep_list_t    *cur;     /* Current head node pointer.       */
   4129     _bcm_oam_hash_data_t  *h_data_p = NULL; /* Endpoint hash data pointer. */
   4130 
   4131     /* Get OAM control structure. */
   4132     BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc));
   4133 
   4134     /* Get the group memory pointer. */
   4135     group_p = &oc->group_info[ep_info_p->group];
   4136 
   4137     if (1 != group_p->in_use) {
   4138         return BCM_E_NONE;
   4139     }    
   4140     cur =  *group_p->ep_list;
   4141 
   4142     /* Traverse the list and delete the matching node. */
   4143     while (NULL != cur) {
   4144         h_data_p = cur->ep_data_p;
   4145         if (NULL == h_data_p) {
   4146             LOG_ERROR(BSL_LS_BCM_OAM,
   4147                      (BSL_META_U(unit,
   4148                      "OAM Error: Hash data is empty\n")));
   4149             return (BCM_E_INTERNAL);
   4150         }
   4151         if (ep_info_p->name  == h_data_p->name) { 
   4152             if ((ep_info_p->flags & BCM_OAM_ENDPOINT_REPLACE) && 
   4153                 (cur->ep_data_p->ep_id == ep_info_p->id)) {
   4154             } else {
   4155                 return BCM_E_PARAM;
   4156             }    
   4157         }
   4158         cur = cur->next;
   4159     }
   4160     return (BCM_E_NONE);
   4161 }
   4162     
   4163 /*
   4164  * Function:
   4165  *     _bcm_tr3_oam_endpoint_params_validate
   4166  * Purpose:
   4167  *     Validate an endpoint parameters.
   4168  * Parameters:
   4169  *     unit      - (IN) BCM device number
   4170  *     oc        - (IN) Pointer to OAM control structure.
   4171  *     hash_key  - (IN) Pointer to endpoint hash key value.
   4172  *     ep_info_p - (IN) Pointer to endpoint information.
   4173  * Retruns:
   4174  *     BCM_E_XXX
   4175  */
   4176 STATIC int
   4177 _bcm_tr3_oam_endpoint_params_validate(int unit,
   4178                                   _bcm_oam_control_t *oc,
   4179                                   _bcm_oam_hash_key_t *hash_key,
   4180                                   bcm_oam_endpoint_info_t *ep_info_p)
   4181 {
   4182     int                 rv;  /* Operation return status. */
   4183     _bcm_oam_hash_data_t h_stored_data;
   4184 
   4185 
   4186     LOG_DEBUG(BSL_LS_BCM_OAM,
   4187               (BSL_META_U(unit,
   4188                           "OAM Info: _bcm_tr3_oam_endpoint_params_validate.\n")));
   4189 
   4190     /* Endpoint must be 802.1ag/Ethernet OAM type. */
   4191     if ((bcmOAMEndpointTypeEthernet != ep_info_p->type)
   4192 #if defined(BCM_TRIUMPH3_SUPPORT) && defined(INCLUDE_BHH) 
   4193         &&  /* BHH/Y.1731 OAM type */
   4194         (bcmOAMEndpointTypeBHHMPLS != ep_info_p->type) &&
   4195         (bcmOAMEndpointTypeBHHMPLSVccv != ep_info_p->type)
   4196 #endif /* INCLUDE_BHH */
   4197         )
   4198     {
   4199         /* Other OAM types are not supported, return error. */
   4200         return (BCM_E_UNAVAIL);
   4201     }
   4202 
   4203     /* Supported MDL level is 0 - 7. */
   4204     if ((ep_info_p->level < 0) || (ep_info_p->level > _BCM_OAM_EP_LEVEL_MAX)) {
   4205         LOG_ERROR(BSL_LS_BCM_OAM,
   4206                   (BSL_META_U(unit,
   4207                               "OAM Error: EP Level should be in the range(0-%d).\n"),
   4208                    _BCM_OAM_EP_LEVEL_MAX ));
   4209         return (BCM_E_PARAM);
   4210     }
   4211 
   4212     /* Supported MEPID Name range is 1 - 8191, Skipping range check for MIP */
   4213     if (((ep_info_p->name < _BCM_OAM_EP_NAME_MIN)
   4214         || (ep_info_p->name > _BCM_OAM_EP_NAME_MAX)) &&
   4215         !(ep_info_p->flags & BCM_OAM_ENDPOINT_INTERMEDIATE)) {
   4216        LOG_ERROR(BSL_LS_BCM_OAM,
   4217                  (BSL_META_U(unit,
   4218                              "OAM Error: MEP Name should be in the range(%d-%d).\n"),
   4219                   _BCM_OAM_EP_NAME_MIN, _BCM_OAM_EP_NAME_MAX));
   4220        return (BCM_E_PARAM);
   4221     }
   4222 
   4223     /* Check if any unsupported flags are passed the return BCM_E_PARAM */
   4224     if (ep_info_p->flags & BCM_OAM_ENDPOINT_CCM_COPYFIRSTTOCPU) {
   4225         LOG_ERROR(BSL_LS_BCM_OAM,
   4226                   (BSL_META_U(unit,
   4227                               "OAM  Error: Unsupported flag\n")));
   4228         return (BCM_E_PARAM);
   4229     }
   4230 
   4231    /*
   4232      * Check and return error if invalid flag bits are set for remote
   4233      * endpoint.
   4234      */
   4235     if ((ep_info_p->flags & BCM_OAM_ENDPOINT_REMOTE)
   4236         && (ep_info_p->flags & _BCM_OAM_REMOTE_EP_INVALID_FLAGS_MASK)) {
   4237 
   4238         return (BCM_E_PARAM);
   4239 
   4240     }
   4241     /*
   4242      * Check and return error if MEPID is not unique within the group
   4243      */
   4244     if(_bcm_tr3_oam_mepid_validate(unit, ep_info_p)) {
   4245         LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit,
   4246              "OAM Error: MEPID:%x passed is not unique in group %x\n"),
   4247              ep_info_p->name, ep_info_p->group));
   4248         return (BCM_E_EXISTS);
   4249     }
   4250 
   4251     /* For replace operation, endpoint ID is required. */
   4252     if ((ep_info_p->flags & BCM_OAM_ENDPOINT_REPLACE)
   4253         && !(ep_info_p->flags & BCM_OAM_ENDPOINT_WITH_ID)) {
   4254 
   4255         return (BCM_E_PARAM);
   4256 
   4257     }
   4258 
   4259     /* Validate endpoint index value. */
   4260     if (ep_info_p->flags & BCM_OAM_ENDPOINT_WITH_ID) {
   4261 
   4262         _BCM_OAM_EP_INDEX_VALIDATE(ep_info_p->id);
   4263     }
   4264 
   4265     /* MIP's are not created with non-zero ccm period */
   4266     if ((ep_info_p->flags & BCM_OAM_ENDPOINT_INTERMEDIATE) &&
   4267         (ep_info_p->ccm_period != BCM_OAM_ENDPOINT_CCM_PERIOD_DISABLED)) {
   4268          return (BCM_E_PARAM);
   4269     }
   4270 
   4271     /* Validate endpoint group id. */
   4272     _BCM_OAM_GROUP_INDEX_VALIDATE(ep_info_p->group);
   4273 
   4274     rv = shr_idxres_list_elem_state(oc->group_pool, ep_info_p->group);
   4275     if (BCM_E_EXISTS != rv) {
   4276         LOG_ERROR(BSL_LS_BCM_OAM,
   4277                   (BSL_META_U(unit,
   4278                               "OAM Error: Group (GID:%d) does not exist.\n"),
   4279                    ep_info_p->group));
   4280         return (BCM_E_PARAM);
   4281     }
   4282 
   4283     if(soc_feature(unit, soc_feature_bhh)) {
   4284 #if defined(BCM_TRIUMPH3_SUPPORT) && defined(INCLUDE_BHH)
   4285         /*
   4286          * BHH can have multiple LSPs/endpoint on same port/MDL 
   4287          * BHH does not have h/w support.  So, return here 
   4288          */
   4289         if ((bcmOAMEndpointTypeBHHMPLS == ep_info_p->type) ||
   4290             (bcmOAMEndpointTypeBHHMPLSVccv == ep_info_p->type)) {
   4291             return (BCM_E_NONE);
   4292         }
   4293 #endif
   4294     }
   4295 
   4296 #if defined(KEY_PRINT)
   4297     _bcm_oam_hash_key_print(hash_key);
   4298 #endif
   4299 
   4300     /*
   4301      * Lookup using hash key value.
   4302      * Last param value '0' specifies keep the match entry.
   4303      * Value '1' would mean remove the entry from the table.
   4304      * Matched Params:
   4305      *      Group Name + Group ID + Endpoint Name + VLAN + MDL + Gport.
   4306      */
   4307     rv = shr_htb_find(oc->ma_mep_htbl, *hash_key,
   4308                       (shr_htb_data_t *)&h_stored_data, 0);
   4309     if (BCM_SUCCESS(rv)
   4310         && !(ep_info_p->flags & BCM_OAM_ENDPOINT_REPLACE)) {
   4311 
   4312         LOG_ERROR(BSL_LS_BCM_OAM,
   4313                   (BSL_META_U(unit,
   4314                               "OAM Error: Endpoint ID=%d %s.\n"),
   4315                    ep_info_p->id, bcm_errmsg(BCM_E_EXISTS)));
   4316 
   4317         /* Endpoint must not be in use expect for Replace operation. */
   4318         return (BCM_E_EXISTS);
   4319 
   4320     } else {
   4321 
   4322         LOG_DEBUG(BSL_LS_BCM_OAM,
   4323                   (BSL_META_U(unit,
   4324                               "OAM Info: Endpoint ID=%d Available. %s.\n"),
   4325                    ep_info_p->id, bcm_errmsg(rv)));
   4326 
   4327     }
   4328 
   4329     
   4330 
   4331     return (BCM_E_NONE);
   4332 }
   4333 
   4334 /*
   4335  * Function:
   4336  *     _bcm_tr3_oam_fp_entry_id_allocate
   4337  * Purpose:
   4338  *     Allocate FP entry Id for Loss and Delay measurement
   4339  * Parameters:
   4340  *     unit         - (IN) BCM device number.
   4341  *     fp_group     - (IN) Group Id under which the FP entry is created.
   4342  *     prio         - (IN) Prioroty of FP Entry to be created.
   4343  *     fp_entry_id  - (OUT) Created FP Entry Id
   4344  * Retruns:
   4345  *     BCM_E_XXX
   4346  */
   4347 STATIC int
   4348 _bcm_tr3_oam_fp_entry_id_allocate(int unit, bcm_field_group_t fp_group, 
   4349                                   int prio, bcm_field_entry_t *fp_entry_id) {
   4350 
   4351     int rv = 0;
   4352     
   4353     if (NULL == fp_entry_id){
   4354         return (BCM_E_INTERNAL);
   4355     }
   4356     
   4357     rv = bcm_esw_field_entry_create(unit, fp_group, fp_entry_id);
   4358     if (BCM_FAILURE(rv)) {
   4359         LOG_ERROR(BSL_LS_BCM_OAM,
   4360                   (BSL_META_U(unit,
   4361                               "OAM Error: FP Entry Tx creation (tx), %s.\n"),
   4362                    bcm_errmsg(rv)));
   4363         return (rv);
   4364     }
   4365 
   4366     rv = bcm_esw_field_entry_prio_set(unit, *fp_entry_id, prio);
   4367     if (BCM_FAILURE(rv)) {
   4368         LOG_ERROR(BSL_LS_BCM_OAM,
   4369                   (BSL_META_U(unit,
   4370                               "OAM Error: FP Entry Tx Prio Set (tx), %s.\n"),
   4371                    bcm_errmsg(rv)));
   4372         return (rv);
   4373     }
   4374 
   4375     return (rv);
   4376 
   4377 }
   4378 
   4379 /*
   4380  * Function:
   4381  *     _bcm_tr3_oam_fp_entry_action_add
   4382  * Purpose:
   4383  *     Adds actions to the fp entry
   4384  * Parameters:
   4385  *     unit         - (IN) BCM device number
   4386  *     hash_data    - (IN) Pointer to endpoint hash data.
   4387  *     fp_entry_id  - (IN) FP Entry id
   4388  *     isTx         - (IN) Whether entry matches tx or rx flow
   4389  * Retruns:
   4390  *     BCM_E_XXX
   4391  */
   4392 STATIC int
   4393 _bcm_tr3_oam_fp_entry_action_add(int unit, _bcm_oam_hash_data_t *hash_data, 
   4394                                  bcm_field_entry_t fp_entry_id, uint8 isTx) {
   4395 
   4396     int rv = 0;
   4397     
   4398     if (NULL == hash_data){
   4399         return (BCM_E_INTERNAL);
   4400     }
   4401     
   4402     rv = bcm_esw_field_action_add(unit, fp_entry_id, 
   4403                                   bcmFieldActionOamLmepEnable, 1, 0);
   4404     if (BCM_FAILURE(rv)) {
   4405         LOG_ERROR(BSL_LS_BCM_OAM,
   4406                   (BSL_META_U(unit,
   4407                               "OAM Error: Adding action OamLmepEnable, EP=%d %s.\n"),
   4408                    hash_data->ep_id, bcm_errmsg(rv)));
   4409         return (rv);
   4410     }
   4411 
   4412     rv = bcm_esw_field_action_add(unit, fp_entry_id, bcmFieldActionOamLmEnable,
   4413                 hash_data->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT? 1:0, 0);
   4414     if (BCM_FAILURE(rv)) {
   4415         LOG_ERROR(BSL_LS_BCM_OAM,
   4416                   (BSL_META_U(unit,
   4417                               "OAM Error: Adding action OamLmEnable, EP=%d %s.\n"),
   4418                    hash_data->ep_id, bcm_errmsg(rv)));
   4419         return (rv);
   4420     }
   4421 
   4422     rv = bcm_esw_field_action_add(unit, fp_entry_id, bcmFieldActionOamDmEnable, 
   4423                 hash_data->flags & BCM_OAM_ENDPOINT_DELAY_MEASUREMENT? 1:0, 0);
   4424     if (BCM_FAILURE(rv)) {
   4425         LOG_ERROR(BSL_LS_BCM_OAM,
   4426                   (BSL_META_U(unit,
   4427                               "OAM Error: Adding action OamDmEnable, EP=%d %s.\n"),
   4428                    hash_data->ep_id, bcm_errmsg(rv)));
   4429         return (rv);
   4430     }
   4431     
   4432     if (hash_data->flags & BCM_OAM_ENDPOINT_DELAY_MEASUREMENT){
   4433         rv = bcm_esw_field_action_add(unit, fp_entry_id, 
   4434                 bcmFieldActionOamDmTimeFormat, 
   4435                 (hash_data->ts_format == bcmOAMTimestampFormatNTP ? 
   4436                 BCM_FIELD_OAM_DM_TIME_FORMAT_NTP : 
   4437                 BCM_FIELD_OAM_DM_TIME_FORMAT_IEEE1588), 0);
   4438         if (BCM_FAILURE(rv)) {
   4439             LOG_ERROR(BSL_LS_BCM_OAM,
   4440                       (BSL_META_U(unit,
   4441                                   "OAM Error: Adding action DmTimeFormat, "
   4442                                   "EP=%d %s.\n"), hash_data->ep_id, bcm_errmsg(rv)));
   4443             return (rv);
   4444         }
   4445     }
   4446 
   4447     rv = bcm_esw_field_action_add(unit, fp_entry_id, bcmFieldActionOamLmepMdl, 
   4448                                 hash_data->level, 0);
   4449     if (BCM_FAILURE(rv)) {
   4450         LOG_ERROR(BSL_LS_BCM_OAM,
   4451                   (BSL_META_U(unit,
   4452                               "OAM Error: Adding action LmepMdl (tx), EP=%d %s.\n"),
   4453                    hash_data->ep_id, bcm_errmsg(rv)));
   4454         return (rv);
   4455     }
   4456 
   4457     rv = bcm_esw_field_action_add(unit, fp_entry_id, bcmFieldActionOamUpMep, 
   4458                         hash_data->flags & BCM_OAM_ENDPOINT_UP_FACING? 1:0, 0);
   4459     if (BCM_FAILURE(rv)) {
   4460         LOG_ERROR(BSL_LS_BCM_OAM,
   4461                   (BSL_META_U(unit,
   4462                               "OAM Error: Adding action OamUpMep (tx), EP=%d %s.\n"),
   4463                    hash_data->ep_id, bcm_errmsg(rv)));
   4464         return (rv);
   4465     }
   4466 
   4467     /* In the case of UP MEP Tx rule is actually Rx and vice versa */
   4468     rv = bcm_esw_field_action_add(unit, fp_entry_id, 
   4469                                   bcmFieldActionOamTx, isTx, 0);
   4470     if (BCM_FAILURE(rv)) {
   4471         LOG_ERROR(BSL_LS_BCM_OAM,
   4472                   (BSL_META_U(unit,
   4473                               "OAM Error: Adding action OamTx (tx), EP=%d %s.\n"),
   4474                    hash_data->ep_id, bcm_errmsg(rv)));
   4475         return (rv);
   4476     }
   4477 
   4478     if (hash_data->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT)
   4479     {
   4480         /* Assign LM counter and priority mapping table */
   4481         rv = bcm_esw_field_action_add(unit, fp_entry_id, 
   4482                     bcmFieldActionOamLmBasePtr, hash_data->lm_counter_index, 0);
   4483         if (BCM_FAILURE(rv)) {
   4484             LOG_ERROR(BSL_LS_BCM_OAM,
   4485                       (BSL_META_U(unit,
   4486                                   "OAM Error: Adding action OamUpMep (tx), "
   4487                                   "EP=%d %s.\n"), hash_data->ep_id, bcm_errmsg(rv)));
   4488             return (rv);
   4489         }
   4490 
   4491         rv = bcm_esw_field_action_add(unit, fp_entry_id, 
   4492             bcmFieldActionOamServicePriMappingPtr, hash_data->pri_map_index, 0);
   4493         if (BCM_FAILURE(rv)) {
   4494             LOG_ERROR(BSL_LS_BCM_OAM,
   4495                       (BSL_META_U(unit,
   4496                                   "OAM Error: Adding action OamUpMep (tx), "
   4497                                   "EP=%d %s.\n"), hash_data->pri_map_index, bcm_errmsg(rv)));
   4498             return (rv);
   4499         }
   4500 
   4501     }
   4502 
   4503     return (rv);
   4504 
   4505 
   4506 }
   4507 
   4508 /*
   4509  * Function:
   4510  *     _bcm_tr3_oam_fp_trunk_create
   4511  * Purpose:
   4512  *     Create FP Entry to match trunk memeber port from which
   4513  *     LM/DM packets generated by CPU will be transmitted.
   4514  * Parameters:
   4515  *     unit      - (IN) BCM device number
   4516  *     oc        - (IN) Pointer to OAM control structure.
   4517  *     hash_data - (IN) Pointer to endpoint hash data.
   4518  * Retruns:
   4519  *     BCM_E_XXX
   4520  */
   4521 STATIC int
   4522 _bcm_tr3_oam_fp_trunk_create(int unit, _bcm_oam_control_t *oc, 
   4523                              _bcm_oam_hash_data_t *hash_data) {
   4524 
   4525     int prio = 0;
   4526     int rv= 0;
   4527     bcm_field_entry_t fp_entry = -1;
   4528     bcm_module_t modid = 0;
   4529     bcm_port_t local_port;
   4530     bcm_ip6_t mdl_data, mdl_mask;
   4531 
   4532     if (NULL == oc || NULL == hash_data ){
   4533         return (BCM_E_INTERNAL);
   4534     }
   4535     
   4536     /* Group should already be created by now*/
   4537     if( oc->fp_glp_group == -1 ){
   4538          LOG_ERROR(BSL_LS_BCM_OAM,
   4539                    (BSL_META_U(unit,
   4540                                "OAM Error: FP Croup not present, EP=%d %s.\n"),
   4541                     hash_data->pri_map_index, bcm_errmsg(rv)));
   4542          return (BCM_E_INTERNAL);
   4543     }
   4544 
   4545     /* Create fp entry */
   4546     /*******************/
   4547     /*Adding 1 to avoid hitting default Prio 0 at MAX_MDL*/
   4548     prio = (_BCM_OAM_MAX_MDL + 1) - hash_data->level; 
   4549     
   4550     rv = _bcm_tr3_oam_fp_entry_id_allocate(unit, oc->fp_glp_group, prio, 
   4551                                            &(hash_data->fp_entry_trunk[0]));
   4552     if (BCM_FAILURE(rv)) {
   4553         LOG_ERROR(BSL_LS_BCM_OAM,
   4554                   (BSL_META_U(unit,
   4555                               "OAM Error: FP Trunk Entry allocate (tx), EP=%d %s\n"),
   4556                    hash_data->ep_id, bcm_errmsg(rv)));
   4557         return (rv);
   4558     }
   4559     fp_entry = hash_data->fp_entry_trunk[0];
   4560     
   4561     /* Add Qulaifiers */
   4562     /******************/
   4563     rv = bcm_esw_field_qualify_OuterVlanId(unit, fp_entry, hash_data->vlan, 
   4564                                            BCM_FIELD_EXACT_MATCH_MASK);
   4565     if (BCM_FAILURE(rv)) {
   4566         LOG_ERROR(BSL_LS_BCM_OAM,
   4567                   (BSL_META_U(unit,
   4568                               "OAM Error: Qualifying OuterVlanId (tx), EP=%d %s.\n"),
   4569                    hash_data->ep_id, bcm_errmsg(rv)));
   4570         return (rv);
   4571     }
   4572     
   4573     /* hash_data->dglp already contains resolved trunk index port, use it to get
   4574      * port and module for qualifying LM/DM packet transmitted from CPU */
   4575     LOG_VERBOSE(BSL_LS_BCM_OAM,
   4576                 (BSL_META_U(unit,
   4577                             "OAM - dglp %d.\n"), 
   4578                  hash_data->dglp));
   4579     local_port = _BCM_OAM_GLP_PORT_GET(unit, hash_data->dglp);
   4580     modid = _BCM_OAM_DGLP_MODULE_ID_GET(hash_data->dglp);
   4581     LOG_VERBOSE(BSL_LS_BCM_OAM,
   4582                 (BSL_META_U(unit,
   4583                             "OAM - Local Port %d, modid %d.\n"), 
   4584                  local_port, modid));
   4585              
   4586     rv = bcm_esw_field_qualify_DstPort(unit, fp_entry, modid, 
   4587             BCM_FIELD_EXACT_MATCH_MASK, local_port, BCM_FIELD_EXACT_MATCH_MASK);
   4588     if (BCM_FAILURE(rv)) {
   4589         LOG_ERROR(BSL_LS_BCM_OAM,
   4590                   (BSL_META_U(unit,
   4591                               "OAM Error: Qualifying DstPort (tx), EP=%d %s.\n"),
   4592                    hash_data->ep_id, bcm_errmsg(rv)));
   4593         return (rv);
   4594     }
   4595     
   4596     rv  = bcm_esw_field_qualify_EtherType(unit, fp_entry, _BCM_OAM_ETHER_TYPE, 
   4597                                           BCM_FIELD_EXACT_MATCH_MASK);
   4598     if (BCM_FAILURE(rv)) {
   4599         LOG_ERROR(BSL_LS_BCM_OAM,
   4600                   (BSL_META_U(unit,
   4601                               "OAM Error: EtherType (tx), EP=%d %s.\n"),
   4602                    hash_data->ep_id, bcm_errmsg(rv)));
   4603         return (rv);
   4604     }
   4605 
   4606     sal_memset(&mdl_data, 0, sizeof(bcm_ip6_t));
   4607     sal_memset(&mdl_mask, 0, sizeof(bcm_ip6_t));
   4608     mdl_data[0] = (hash_data->level << 5);
   4609     mdl_mask[0] = 0xE0;
   4610     
   4611     rv  = bcm_esw_field_qualify_DstIp6(unit, fp_entry, mdl_data, mdl_mask);
   4612     if (BCM_FAILURE(rv)) {
   4613         LOG_ERROR(BSL_LS_BCM_OAM,
   4614                   (BSL_META_U(unit,
   4615                               "OAM Error: Qualifying MDL (tx), EP=%d %s.\n"),
   4616                    hash_data->ep_id, bcm_errmsg(rv)));
   4617         return (rv);
   4618     }
   4619     
   4620     /* Add Action */
   4621     /**************/
   4622     rv = _bcm_tr3_oam_fp_entry_action_add(unit, hash_data, fp_entry, 1);
   4623     if (BCM_FAILURE(rv)) {
   4624         LOG_ERROR(BSL_LS_BCM_OAM,
   4625                   (BSL_META_U(unit,
   4626                               "OAM Error: Adding action (tx), EP=%d %s.\n"),
   4627                    hash_data->ep_id, bcm_errmsg(rv)));
   4628         return (rv);
   4629     }
   4630 
   4631     return (rv);
   4632     
   4633 }
   4634 
   4635 /*
   4636  * Function:
   4637  *     _bcm_tr3_oam_fp_create
   4638  * Purpose:
   4639  *     Create IFP entry for LOSS & DELAY Measurement
   4640  * Parameters:
   4641  *     unit      - (IN) BCM device number
   4642  *     oc        - (IN-OUT) Pointer to OAM control structure.
   4643  *     hash_data - (IN-OUT) Pointer to endpoint hash data.
   4644  *     modify_entry - (OUT) Pointer to existing entries which were 
   4645  *                     modified and need re-installation.
   4646  * Retruns:
   4647  *     BCM_E_XXX
   4648  */
   4649 STATIC int
   4650 _bcm_tr3_oam_fp_create(int unit, _bcm_oam_control_t *oc, 
   4651                        _bcm_oam_hash_data_t *hash_data) {
   4652 
   4653     int rv = 0, i;
   4654     _bcm_oam_hash_data_t *existing_max_level_ep_data = NULL;
   4655     bcm_field_entry_t fp_entry_tx = -1, fp_entry_rx = -1;
   4656     /* To hold any existing entries if modified */
   4657     bcm_field_entry_t  modify_entry[2] = {-1, -1};
   4658     uint32 gport = 0;
   4659     bcm_trunk_t tgid = 0;
   4660     bcm_module_t modid = 0;
   4661     bcm_port_t local_port;
   4662     int prio = 0;
   4663     uint8 add_mdl = 0;
   4664     bcm_ip6_t mdl_data, mdl_mask;
   4665     int local_id; /* Hardware ID used in call to _bcm_esw_gport_resolve*/
   4666 
   4667     if ( (NULL == oc) || (NULL == hash_data) ){
   4668         return (BCM_E_INTERNAL);
   4669     }
   4670 
   4671     /* Create Group */
   4672     /****************/
   4673     if (oc->fp_glp_group == -1) {
   4674 
   4675         /* Prepare the Qualifier, use the same group for all 3: 
   4676          * 1. physical port, 2. trunk and 3. virtual ports. 
   4677          */
   4678         BCM_FIELD_QSET_INIT(oc->fp_glp_qs);
   4679         BCM_FIELD_QSET_ADD(oc->fp_glp_qs, bcmFieldQualifyStageIngress);
   4680         
   4681         BCM_FIELD_QSET_ADD(oc->fp_glp_qs, bcmFieldQualifyOuterVlanId);
   4682         BCM_FIELD_QSET_ADD(oc->fp_glp_qs, bcmFieldQualifyDstPort);
   4683         BCM_FIELD_QSET_ADD(oc->fp_glp_qs, bcmFieldQualifyDstTrunk);
   4684         BCM_FIELD_QSET_ADD(oc->fp_glp_qs, bcmFieldQualifySrcPort);
   4685         BCM_FIELD_QSET_ADD(oc->fp_glp_qs, bcmFieldQualifySrcTrunk);
   4686         BCM_FIELD_QSET_ADD(oc->fp_glp_qs, bcmFieldQualifyEtherType);
   4687         BCM_FIELD_QSET_ADD(oc->fp_glp_qs, bcmFieldQualifyDstIp6);
   4688         if (soc_feature(unit, soc_feature_mim)) {
   4689             BCM_FIELD_QSET_ADD(oc->fp_glp_qs, bcmFieldQualifyDstMimGport);
   4690             BCM_FIELD_QSET_ADD(oc->fp_glp_qs, bcmFieldQualifySrcMimGport);
   4691         }
   4692         /* Create fp group */
   4693         rv = bcm_esw_field_group_create(unit, oc->fp_glp_qs, 
   4694                                 BCM_FIELD_GROUP_PRIO_ANY, &(oc->fp_glp_group));
   4695          if (BCM_FAILURE(rv)) {
   4696             LOG_ERROR(BSL_LS_BCM_OAM,
   4697                       (BSL_META_U(unit,
   4698                                   "OAM Error: Group creation, EP=%d %s.\n"),
   4699                        hash_data->ep_id, bcm_errmsg(rv)));
   4700             return (rv);
   4701         }
   4702          
   4703     }
   4704 
   4705     /* Create the FP entry */
   4706     /***********************/
   4707     /* Entry priority is inversely proportional to level, In case of Multiple 
   4708      * MEPs on same vlan port following is the scheme for installation.
   4709      * -----Level 2-(Match port vlan ethertype and MDL)----
   4710      * -----Level 4-(Match port vlan ethertype and MDL)----
   4711      * -----Level 6-(Match port vlan)----------------------
   4712      */
   4713      
   4714     /* Adding 1 to avoid hitting default Prio 0 at MAX_MDL */
   4715     prio = (_BCM_OAM_MAX_MDL + 1) - hash_data->level;
   4716     
   4717     rv = _bcm_tr3_oam_fp_entry_id_allocate(unit, oc->fp_glp_group, prio, 
   4718                                            &(hash_data->fp_entry_tx));
   4719     if (BCM_FAILURE(rv)) {
   4720         LOG_ERROR(BSL_LS_BCM_OAM,
   4721                   (BSL_META_U(unit,
   4722                               "OAM Error: FP Entry allocate (tx), EP=%d %s.\n"),
   4723                    hash_data->ep_id, bcm_errmsg(rv)));
   4724         return (rv);
   4725     }
   4726     
   4727     rv = _bcm_tr3_oam_fp_entry_id_allocate(unit, oc->fp_glp_group, prio, 
   4728                                            &(hash_data->fp_entry_rx));
   4729     if (BCM_FAILURE(rv)) {
   4730         LOG_ERROR(BSL_LS_BCM_OAM,
   4731                   (BSL_META_U(unit,
   4732                               "OAM Error: FP Entry allocate (rx), EP=%d %s.\n"),
   4733                    hash_data->ep_id, bcm_errmsg(rv)));
   4734         return (rv);
   4735     }
   4736 
   4737 
   4738     /* Add Qualifiers */
   4739     /******************/    
   4740     /* 1. VP Case */
   4741     if (hash_data->vp != 0) {
   4742         LOG_VERBOSE(BSL_LS_BCM_OAM,
   4743                     (BSL_META_U(unit,
   4744                                 "OAM: MEP on VP\n")));
   4745         BCM_GPORT_MIM_PORT_ID_SET(gport, hash_data->vp);
   4746 
   4747         rv = bcm_esw_field_qualify_DstMimGport(unit, hash_data->fp_entry_tx, 
   4748                                                gport);
   4749         if (BCM_FAILURE(rv)) {
   4750             LOG_ERROR(BSL_LS_BCM_OAM,
   4751                       (BSL_META_U(unit,
   4752                                   "OAM Error: Qualifying DstMimGport (tx), "
   4753                                   "EP=%d %s.\n"), hash_data->ep_id, bcm_errmsg(rv)));
   4754             return (rv);
   4755         }
   4756 
   4757     	rv = bcm_esw_field_qualify_SrcMimGport(unit, hash_data->fp_entry_rx, 
   4758                                                gport);
   4759     	if (BCM_FAILURE(rv)) {
   4760             LOG_ERROR(BSL_LS_BCM_OAM,
   4761                       (BSL_META_U(unit,
   4762                                   "OAM Error: Qualifying SrcMimGport (rx), "
   4763                                   "EP=%d %s.\n"), hash_data->ep_id, bcm_errmsg(rv)));
   4764             return (rv);
   4765         }
   4766 	
   4767     } else {
   4768         
   4769         /* If its not VP case then we need to qualify on outer vlan for rest */
   4770          rv = bcm_esw_field_qualify_OuterVlanId(unit, hash_data->fp_entry_tx, 
   4771                                 hash_data->vlan, BCM_FIELD_EXACT_MATCH_MASK);
   4772          if (BCM_FAILURE(rv)) {
   4773              LOG_ERROR(BSL_LS_BCM_OAM,
   4774                        (BSL_META_U(unit,
   4775                                    "OAM Error: Qualifying OuterVlanId (tx), "
   4776                                    "EP=%d %s.\n"), hash_data->ep_id, bcm_errmsg(rv)));
   4777              return (rv);
   4778          }
   4779 
   4780         rv = bcm_esw_field_qualify_OuterVlanId(unit, hash_data->fp_entry_rx, 
   4781                                 hash_data->vlan, BCM_FIELD_EXACT_MATCH_MASK);
   4782         if (BCM_FAILURE(rv)) {
   4783             LOG_ERROR(BSL_LS_BCM_OAM,
   4784                       (BSL_META_U(unit,
   4785                                   "OAM Error: Qualifying OuterVlanId (rx), "
   4786                                   "EP=%d %s.\n"), hash_data->ep_id, bcm_errmsg(rv)));
   4787             return (rv);
   4788         }
   4789         
   4790         rv = _bcm_esw_gport_resolve(unit, hash_data->gport, &modid, 
   4791                                     &local_port, &tgid, &local_id);
   4792         if (BCM_FAILURE(rv)) {
   4793             LOG_ERROR(BSL_LS_BCM_OAM,
   4794                       (BSL_META_U(unit,
   4795                                   "OAM Error: call to _bcm_esw_gport_resolve "
   4796                                   "failed, EP=%d %s.\n"), hash_data->ep_id, bcm_errmsg(rv)));
   4797             return (rv);
   4798         }
   4799         LOG_VERBOSE(BSL_LS_BCM_OAM,
   4800                     (BSL_META_U(unit,
   4801                                 "OAM - Local Port %d, modid %d, trunkid %d.\n"), 
   4802                      local_port, modid, tgid));
   4803 
   4804         /* 2. Trunk Case */
   4805         if (SOC_GPORT_IS_TRUNK(hash_data->gport)) {
   4806             LOG_VERBOSE(BSL_LS_BCM_OAM,
   4807                         (BSL_META_U(unit,
   4808                                     "OAM: MEP on Trunk\n")));
   4809             
   4810             if (BCM_TRUNK_INVALID == tgid)  {
   4811                 LOG_ERROR(BSL_LS_BCM_OAM,
   4812                           (BSL_META_U(unit,
   4813                                       "OAM Error: Invalid Trunkid, EP=%d %s.\n"), 
   4814                            hash_data->ep_id, bcm_errmsg(rv)));
   4815                 return (rv);
   4816             }
   4817 
   4818             rv  = bcm_esw_field_qualify_DstTrunk(unit, hash_data->fp_entry_tx, 
   4819                                 tgid, BCM_FIELD_EXACT_MATCH_MASK);
   4820             if (BCM_FAILURE(rv)) {
   4821                 LOG_ERROR(BSL_LS_BCM_OAM,
   4822                           (BSL_META_U(unit,
   4823                                       "OAM Error: Qualifying DstTrunk (tx), "
   4824                                       "EP=%d %s.\n"), hash_data->ep_id, bcm_errmsg(rv)));
   4825                 return (rv);
   4826             }
   4827             
   4828             rv  = bcm_esw_field_qualify_SrcTrunk(unit, hash_data->fp_entry_rx, 
   4829                                     tgid, BCM_FIELD_EXACT_MATCH_MASK);
   4830             if (BCM_FAILURE(rv)) {
   4831                 LOG_ERROR(BSL_LS_BCM_OAM,
   4832                           (BSL_META_U(unit,
   4833                                       "OAM Error: Qualifying SrcTrunk (rx), "
   4834                                       "EP=%d %s.\n"), hash_data->ep_id, bcm_errmsg(rv)));
   4835                 return (rv);
   4836             }
   4837             
   4838             /*For Down MEP on LAG, Add FP Entry on primary port of the LAG also, 
   4839              * as when packet is sent from CPU, Trunk Id cannot be specified,
   4840              * and the packet will carry primary port of the LAG as destination
   4841              */
   4842             if (!(hash_data->flags & BCM_OAM_ENDPOINT_UP_FACING)){
   4843                 rv = _bcm_tr3_oam_fp_trunk_create(unit, oc, hash_data);
   4844                 if (BCM_FAILURE(rv)) {
   4845                     LOG_ERROR(BSL_LS_BCM_OAM,
   4846                               (BSL_META_U(unit,
   4847                                           "OAM Error: Creating Fp Entry on Trunk Tx "
   4848                                           "port, EP=%d %s\n"), hash_data->ep_id, bcm_errmsg(rv)));
   4849                     return (rv);
   4850                 }
   4851             }
   4852             
   4853         } else {
   4854         
   4855             /*3. Local Port*/
   4856             LOG_VERBOSE(BSL_LS_BCM_OAM,
   4857                         (BSL_META_U(unit,
   4858                                     "OAM: MEP on Local Port\n")));
   4859 
   4860             rv = bcm_esw_field_qualify_DstPort(unit, hash_data->fp_entry_tx, 
   4861                                         modid, BCM_FIELD_EXACT_MATCH_MASK, 
   4862                                         local_port, BCM_FIELD_EXACT_MATCH_MASK);
   4863             if (BCM_FAILURE(rv)) {
   4864                 LOG_ERROR(BSL_LS_BCM_OAM,
   4865                           (BSL_META_U(unit,
   4866                                       "OAM Error: Qualifying DstPort (tx), "
   4867                                       "EP=%d %s.\n"), hash_data->ep_id, bcm_errmsg(rv)));
   4868                 return (rv);
   4869             }
   4870 
   4871             rv = bcm_esw_field_qualify_SrcPort(unit, hash_data->fp_entry_rx, 
   4872                                         modid, BCM_FIELD_EXACT_MATCH_MASK, 
   4873                                         local_port, BCM_FIELD_EXACT_MATCH_MASK);
   4874             if (BCM_FAILURE(rv)) {
   4875                 LOG_ERROR(BSL_LS_BCM_OAM,
   4876                           (BSL_META_U(unit,
   4877                                       "OAM Error: Qualifying SrcPort (rx), "
   4878                                       "EP=%d %s.\n"), hash_data->ep_id, bcm_errmsg(rv)));
   4879                 return (rv);
   4880             }
   4881         }   
   4882     }
   4883 
   4884     /* Check if we need Ethertype and MDL Qualifier:
   4885      * 1. If this the first LM/DM MEP on port vlan, 
   4886      *      Qualification on Ethertype and MDL not needed.
   4887      * 2. If this is not the first LM/DM MEP on port vlan, and also not of 
   4888      *      highest level, then add Ethertype and MDL Qualifiers and insert.
   4889      * 3. If this is not the fisrt LM/DM MEP on port vlan, and also of 
   4890      *      highest level, then modify existing highest MEP entry,
   4891      *      Add Ethertype and MDL Qualifier to existing MEP entry and 
   4892      *      insert the current one without Ethertype and MDL.
   4893      */
   4894     sal_memset(&mdl_data, 0, sizeof(bcm_ip6_t));
   4895     sal_memset(&mdl_mask, 0, sizeof(bcm_ip6_t));
   4896     mdl_mask[0] = 0xE0;
   4897     LOG_VERBOSE(BSL_LS_BCM_OAM,
   4898                 (BSL_META_U(unit,
   4899                             "OAM _bcm_oam_lm_dm_search_data.match_count %d, "
   4900                             "_bcm_oam_lm_dm_search_data.highest_level %d, hash_data->level %d\n"), 
   4901                  _bcm_oam_lm_dm_search_data.match_count, 
   4902                  _bcm_oam_lm_dm_search_data.highest_level, hash_data->level));
   4903     if ( (_bcm_oam_lm_dm_search_data.match_count) && 
   4904          (_bcm_oam_lm_dm_search_data.highest_level > hash_data->level) ) {
   4905 
   4906         fp_entry_tx = hash_data->fp_entry_tx;
   4907         fp_entry_rx = hash_data->fp_entry_rx;
   4908         mdl_data[0] = hash_data->level << 5;
   4909         add_mdl = 1;
   4910         
   4911     } else {
   4912 
   4913         if ( (_bcm_oam_lm_dm_search_data.match_count) && 
   4914              (_bcm_oam_lm_dm_search_data.highest_level < hash_data->level) ) {
   4915 
   4916             existing_max_level_ep_data =  
   4917              &oc->oam_hash_data[_bcm_oam_lm_dm_search_data.highest_level_ep_id];
   4918             fp_entry_tx = existing_max_level_ep_data->fp_entry_tx;
   4919             fp_entry_rx = existing_max_level_ep_data->fp_entry_rx;
   4920             mdl_data[0] = existing_max_level_ep_data->level << 5;
   4921             add_mdl = 1;
   4922             modify_entry[0] = fp_entry_tx;
   4923             modify_entry[1] = fp_entry_rx;
   4924        
   4925         }
   4926     }
   4927     if (add_mdl) {
   4928         LOG_VERBOSE(BSL_LS_BCM_OAM,
   4929                     (BSL_META_U(unit,
   4930                                 "OAM add_mdl=true\n")));
   4931 
   4932         rv  = bcm_esw_field_qualify_EtherType(unit, fp_entry_tx, 
   4933         _BCM_OAM_ETHER_TYPE, BCM_FIELD_EXACT_MATCH_MASK);
   4934         if (BCM_FAILURE(rv)) {
   4935             LOG_ERROR(BSL_LS_BCM_OAM,
   4936                       (BSL_META_U(unit,
   4937                                   "OAM Error: EtherType (tx), EP=%d %s.\n"),
   4938                        hash_data->ep_id, bcm_errmsg(rv)));
   4939             return (rv);
   4940         }
   4941         rv  = bcm_esw_field_qualify_EtherType(unit, fp_entry_rx, 
   4942                             _BCM_OAM_ETHER_TYPE, BCM_FIELD_EXACT_MATCH_MASK);
   4943         if (BCM_FAILURE(rv)) {
   4944             LOG_ERROR(BSL_LS_BCM_OAM,
   4945                       (BSL_META_U(unit,
   4946                                   "OAM Error: EtherType (rx), EP=%d %s.\n"),
   4947                        hash_data->ep_id, bcm_errmsg(rv)));
   4948             return (rv);
   4949         }
   4950 
   4951         rv  = bcm_esw_field_qualify_DstIp6(unit, fp_entry_tx, 
   4952                                             mdl_data, mdl_mask);
   4953         if (BCM_FAILURE(rv)) {
   4954             LOG_ERROR(BSL_LS_BCM_OAM,
   4955                       (BSL_META_U(unit,
   4956                                   "OAM Error: Qualifying MDL (tx), EP=%d %s.\n"),
   4957                        hash_data->ep_id, bcm_errmsg(rv)));
   4958             return (rv);
   4959         }
   4960         rv  = bcm_esw_field_qualify_DstIp6(unit, fp_entry_rx, 
   4961                                             mdl_data, mdl_mask);
   4962         if (BCM_FAILURE(rv)) {
   4963             LOG_ERROR(BSL_LS_BCM_OAM,
   4964                       (BSL_META_U(unit,
   4965                                   "OAM Error: Qualifying MDL (rx), EP=%d %s.\n"),
   4966                        hash_data->ep_id, bcm_errmsg(rv)));
   4967             return (rv);
   4968         }
   4969     }
   4970 
   4971 
   4972     /* Add action */
   4973     /**************/
   4974     /* In the case of UP MEP Tx rule is actually Rx and vice versa */
   4975     rv = _bcm_tr3_oam_fp_entry_action_add(unit, 
   4976                         hash_data, hash_data->fp_entry_tx, 
   4977                         hash_data->flags & BCM_OAM_ENDPOINT_UP_FACING? 0:1);
   4978     if (BCM_FAILURE(rv)) {
   4979         LOG_ERROR(BSL_LS_BCM_OAM,
   4980                   (BSL_META_U(unit,
   4981                               "OAM Error: Adding action (tx), EP=%d %s.\n"),
   4982                    hash_data->ep_id, bcm_errmsg(rv)));
   4983         return (rv);
   4984     }
   4985 
   4986     rv = _bcm_tr3_oam_fp_entry_action_add(unit, hash_data, 
   4987     hash_data->fp_entry_rx, hash_data->flags & BCM_OAM_ENDPOINT_UP_FACING? 1:0);
   4988     if (BCM_FAILURE(rv)) {
   4989         LOG_ERROR(BSL_LS_BCM_OAM,
   4990                   (BSL_META_U(unit,
   4991                               "OAM Error: Adding action (rx), EP=%d %s.\n"),
   4992                    hash_data->ep_id, bcm_errmsg(rv)));
   4993         return (rv);
   4994     }
   4995     
   4996     /* Install Created/Modified entries */
   4997     /************************************/
   4998     /* Tx Entry */
   4999     rv = bcm_esw_field_entry_install(unit, hash_data->fp_entry_tx);
   5000     if (BCM_FAILURE(rv)) {
   5001         LOG_ERROR(BSL_LS_BCM_OAM,
   5002                   (BSL_META_U(unit,
   5003                               "OAM Error: FP Install failed (tx), EP=%d %s.\n"),
   5004                    hash_data->ep_id, bcm_errmsg(rv)));
   5005         return (rv);
   5006     }
   5007     /* Rx Entry */
   5008     rv = bcm_esw_field_entry_install(unit, hash_data->fp_entry_rx);
   5009     if (BCM_FAILURE(rv)) {
   5010         LOG_ERROR(BSL_LS_BCM_OAM,
   5011                   (BSL_META_U(unit,
   5012                               "OAM Error: FP Install failed (tx), EP=%d %s.\n"),
   5013                    hash_data->ep_id, bcm_errmsg(rv)));
   5014         return (rv);
   5015     }
   5016     /* Trunk Entry */
   5017     if (hash_data->fp_entry_trunk[0] != -1){
   5018         rv = bcm_esw_field_entry_install(unit, hash_data->fp_entry_trunk[0]);
   5019         if (BCM_FAILURE(rv)) {
   5020             LOG_ERROR(BSL_LS_BCM_OAM,
   5021                       (BSL_META_U(unit,
   5022                                   "OAM Error: FP Install failed (Trunk), "
   5023                                   "EP=%d %s.\n"), hash_data->ep_id, bcm_errmsg(rv)));
   5024             return (rv);
   5025         }
   5026     }
   5027     /* Any existing entries that were modified */
   5028     for (i=0; i<2; i++){
   5029         if (modify_entry[i] != -1) {
   5030             rv = bcm_esw_field_entry_install(unit, modify_entry[i]);
   5031             if (BCM_FAILURE(rv)) {
   5032                 LOG_ERROR(BSL_LS_BCM_OAM,
   5033                           (BSL_META_U(unit,
   5034                                       "OAM Error: FP Modify failed, EP=%d %s.\n"),
   5035                            hash_data->ep_id, bcm_errmsg(rv)));
   5036                 return (rv);
   5037             }
   5038         }
   5039     }
   5040 
   5041     return (rv);
   5042         
   5043 }
   5044 
   5045 /*
   5046  * Function:
   5047  *     _bcm_tr3_oam_pri_map_profile_create
   5048  * Purpose:
   5049  *     Create ING_SERVICE_PRI_MAP entry for LM
   5050  * Parameters:
   5051  *     unit      - (IN) BCM device number
   5052  *     oc        - (IN) Pointer to OAM control structure.
   5053  *     hash_data - (IN) Pointer to endpoint hash data.
   5054  *     endpoint_info - (IN) Pointer to endpoint info structure.
   5055  * Retruns:
   5056  *     BCM_E_XXX
   5057  */
   5058 STATIC int
   5059 _bcm_tr3_oam_pri_map_profile_create(int unit, _bcm_oam_control_t *oc, 
   5060     _bcm_oam_hash_data_t *hash_data, bcm_oam_endpoint_info_t *endpoint_info) {
   5061 
   5062     int rv = 0;
   5063     ing_service_pri_map_entry_t pri_ent[BCM_OAM_INTPRI_MAX];    /* profile */
   5064     soc_mem_t   mem;                                /* Profiled table memory. */
   5065     void *entries[1];                               /* Profile entry. */
   5066     uint32 profile_index;                           /* Profile table index. */
   5067     uint8 pri = 0;
   5068 
   5069     if ( (NULL == oc) || (NULL == hash_data) || (NULL == endpoint_info) ){
   5070         return (BCM_E_INTERNAL);
   5071     }
   5072      
   5073     /*
   5074      * Initialize ingress priority map profile table.
   5075      * All priorities priorities map to priority:'0'.
   5076      */
   5077     mem = ING_SERVICE_PRI_MAPm;
   5078     for (pri = 0; pri < BCM_OAM_INTPRI_MAX; pri++) {
   5079     
   5080         /* Clear ingress service pri map profile entry. */
   5081         sal_memcpy(&pri_ent[pri], soc_mem_entry_null(unit, mem),
   5082                     soc_mem_entry_words(unit, mem) * sizeof(uint32));
   5083                    
   5084         if (SOC_MEM_FIELD_VALID(unit, mem, OFFSETf)) {
   5085             soc_mem_field32_set(unit, mem, &pri_ent[pri], OFFSETf, 
   5086                                 endpoint_info->pri_map[pri]);
   5087         }
   5088 
   5089         if (SOC_MEM_FIELD_VALID(unit, mem, OFFSET_VALIDf)) {
   5090             soc_mem_field32_set(unit, mem, &pri_ent[pri], OFFSET_VALIDf, 1);
   5091         }
   5092     }
   5093     entries[0] = &pri_ent;
   5094     rv = soc_profile_mem_add(unit, &oc->ing_service_pri_map,
   5095                          (void *) &entries, BCM_OAM_INTPRI_MAX, &profile_index);
   5096     if (BCM_FAILURE(rv)) {
   5097         LOG_ERROR(BSL_LS_BCM_OAM,
   5098                   (BSL_META_U(unit,
   5099                               "OAM Error: service map profile add, EP=%d %s.\n"), 
   5100                    hash_data->ep_id, bcm_errmsg(rv)));
   5101         return (rv);
   5102     }
   5103     hash_data->pri_map_index = profile_index /BCM_OAM_INTPRI_MAX;
   5104 
   5105     return (rv);
   5106                       
   5107 }
   5108 
   5109 /*
   5110  * Function:
   5111  *    _bcm_lm_dm_search_cb
   5112  * Purpose:
   5113  *    Call back function to match existing LM endpoints over same vlan port.
   5114  *    Gives Existing Highest level enpoint, excluding the current(EP in context)
   5115  * Parameters:
   5116  *    unit      - (IN) BCM device number.
   5117  *    hash_key  - (IN) Pointer to endpoint hash key value.
   5118  *    data      - (IN) Pointer to endpoint hash data.
   5119  * Retruns:
   5120  *    BCM_E_XXX
   5121  */
   5122 STATIC int
   5123 _bcm_lm_dm_search_cb(int unit, shr_htb_key_t key, shr_htb_data_t data) {
   5124     int rv = 0;
   5125     _bcm_oam_hash_data_t *h_data_ptr;
   5126     
   5127     h_data_ptr = (_bcm_oam_hash_data_t *)data;
   5128     if ( ( h_data_ptr->flags & (BCM_OAM_ENDPOINT_LOSS_MEASUREMENT | 
   5129                                BCM_OAM_ENDPOINT_DELAY_MEASUREMENT) ) && 
   5130          (h_data_ptr->in_use == 1) && 
   5131          (h_data_ptr->ep_id != _bcm_oam_lm_dm_search_data.match_ep_id) && 
   5132          (h_data_ptr->type == _bcm_oam_lm_dm_search_data.match_type) &&
   5133          (h_data_ptr->vlan == _bcm_oam_lm_dm_search_data.match_vlan) &&
   5134          (h_data_ptr->gport == _bcm_oam_lm_dm_search_data.match_gport) ) {
   5135             _bcm_oam_lm_dm_search_data.match_count++;
   5136             if (h_data_ptr->level >= _bcm_oam_lm_dm_search_data.highest_level) {
   5137              _bcm_oam_lm_dm_search_data.highest_level = h_data_ptr->level;
   5138              _bcm_oam_lm_dm_search_data.highest_level_ep_id = h_data_ptr->ep_id;
   5139             }
   5140         }
   5141     
   5142     return rv;
   5143 }
   5144 
   5145 /*
   5146  * Function:
   5147  *     _bcm_tr3_oam_loss_delay_measurement_add
   5148  * Purpose:
   5149  *     Create LM/DM IFP entry and install the same.
   5150  * Parameters:
   5151  *     unit      - (IN) BCM device number
   5152  *     oc        - (IN) Pointer to OAM control structure.
   5153  *     hash_data - (IN) Pointer to endpoint hash data.
   5154  *     endpoint_info - (IN) Pointer to endpoint info structure.
   5155  * Retruns:
   5156  *     BCM_E_XXX
   5157  */
   5158 STATIC int
   5159 _bcm_tr3_oam_loss_delay_measurement_add(int unit, _bcm_oam_control_t *oc, 
   5160     _bcm_oam_hash_data_t *hash_data, bcm_oam_endpoint_info_t *endpoint_info) {
   5161 
   5162     int rv=0;
   5163     /*Hash data of existing endpoint on same vlan port */
   5164     _bcm_oam_hash_data_t *existing_ep_hash_data = NULL;
   5165     
   5166     if ( (NULL == oc) || (NULL == hash_data) || (NULL == endpoint_info) ){
   5167         return (BCM_E_INTERNAL);
   5168     }
   5169     
   5170     sal_memset(&_bcm_oam_lm_dm_search_data, 0, 
   5171                 sizeof(_bcm_oam_lm_dm_search_data_type_t));
   5172 
   5173     /*Set the match criteria for LM search*/
   5174     _bcm_oam_lm_dm_search_data.match_type = hash_data->type;
   5175     _bcm_oam_lm_dm_search_data.match_ep_id = hash_data->ep_id;
   5176     _bcm_oam_lm_dm_search_data.match_vlan = hash_data->vlan;
   5177     _bcm_oam_lm_dm_search_data.match_gport = hash_data->gport;
   5178     _bcm_oam_lm_dm_search_data.highest_level = 0;
   5179     _bcm_oam_lm_dm_search_data.highest_level_ep_id = 0;
   5180     
   5181     /* Iterate over existing enpoint to find 
   5182     if port vlan matching entry already exists */
   5183     rv = shr_htb_iterate(unit, oc->ma_mep_htbl, _bcm_lm_dm_search_cb);
   5184     if (BCM_FAILURE(rv)) {
   5185         LOG_ERROR(BSL_LS_BCM_OAM,
   5186                   (BSL_META_U(unit,
   5187                               "OAM Error: LM Search failed, EP=%d %s.\n"),
   5188                    hash_data->ep_id, bcm_errmsg(rv)));
   5189         return (rv);
   5190     }
   5191     
   5192     LOG_VERBOSE(BSL_LS_BCM_OAM,
   5193                 (BSL_META_U(unit,
   5194                             "OAM: Existing EP on vlan port count=%d, "
   5195                             "Highest level=%d, EP=%d\n"),
   5196                  _bcm_oam_lm_dm_search_data.match_count,
   5197                  _bcm_oam_lm_dm_search_data.highest_level, 
   5198                  _bcm_oam_lm_dm_search_data.highest_level_ep_id));    
   5199     
   5200     if (hash_data->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT) {
   5201     
   5202         /* If enpoint already exists on same vlan port, 
   5203          * Use the Primap and Counter index of existing endpoint,
   5204          * Its a hardware limitation that multi level endpoints 
   5205          * on same vlan port cannot have different primap 
   5206          */
   5207         if (_bcm_oam_lm_dm_search_data.match_count > 0) {
   5208           existing_ep_hash_data = 
   5209           &oc->oam_hash_data[_bcm_oam_lm_dm_search_data.highest_level_ep_id];
   5210           hash_data->pri_map_index = existing_ep_hash_data->pri_map_index;
   5211           hash_data->lm_counter_index = existing_ep_hash_data->lm_counter_index;
   5212             
   5213         } else {
   5214             /* Create ING_SERVICE_PRI_MAP profile for the endpoint */
   5215             rv  = _bcm_tr3_oam_pri_map_profile_create(unit, oc, hash_data, 
   5216                                                       endpoint_info);
   5217             if (BCM_FAILURE(rv)) {
   5218                 LOG_ERROR(BSL_LS_BCM_OAM,
   5219                           (BSL_META_U(unit,
   5220                                       "OAM Error: ING_SERVICE_PRI_MAP profile "
   5221                                       "creation, EP=%d %s\n"), hash_data->ep_id, bcm_errmsg(rv)));
   5222                 return (rv);
   5223             }
   5224 
   5225             /* Allocate counter index. */
   5226             rv = shr_idxres_list_alloc(oc->lm_counter_pool,
   5227                         (shr_idxres_element_t *)&hash_data->lm_counter_index);
   5228             if (BCM_FAILURE(rv)) {
   5229                 LOG_ERROR(BSL_LS_BCM_OAM,
   5230                           (BSL_META_U(unit,
   5231                                       "OAM Error: lm counter idx alloc failed, "
   5232                                       "EP=%d %s.\n"), hash_data->ep_id, bcm_errmsg(rv)));
   5233                 return (rv);
   5234             }
   5235         }
   5236     }
   5237 
   5238     /* Create Field entries / modify existing if needed. Also install*/
   5239     rv  = _bcm_tr3_oam_fp_create(unit, oc, hash_data);
   5240     if (BCM_FAILURE(rv)) {
   5241         LOG_ERROR(BSL_LS_BCM_OAM,
   5242                   (BSL_META_U(unit,
   5243                               "OAM Error: FP Create failed, EP=%d %s.\n"),
   5244                    hash_data->ep_id, bcm_errmsg(rv)));
   5245                  
   5246         /* In case of failure, free the counter index and primap 
   5247          * only if the same has been newly created for this endpoint */
   5248         if (hash_data->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT) {
   5249     
   5250             /* If another enpoint exists on same vlan port, 
   5251              * Don't free primap and counter index, as they are shared */
   5252             if (_bcm_oam_lm_dm_search_data.match_count == 0){
   5253             
   5254                 /* Free ING_SERVICE_PRI_MAP profile */
   5255                 soc_profile_mem_delete(unit, &oc->ing_service_pri_map, 
   5256                          	(hash_data->pri_map_index * BCM_OAM_INTPRI_MAX));
   5257 
   5258                 /* Free counter index. */
   5259                 shr_idxres_list_free( oc->lm_counter_pool,
   5260                             (shr_idxres_element_t)hash_data->lm_counter_index);
   5261             }
   5262         }
   5263         return (rv);
   5264     }
   5265     
   5266     /* Increment the group FP count */
   5267     oc->fp_glp_entry_cnt++;
   5268     LOG_VERBOSE(BSL_LS_BCM_OAM,
   5269                 (BSL_META_U(unit,
   5270                             "OAM: oc->fp_glp_entry_cnt=%d\n"), 
   5271                  oc->fp_glp_entry_cnt));
   5272     return (rv);
   5273 }
   5274 
   5275 
   5276 /*
   5277  * Function:
   5278  *     _bcm_tr3_oam_loss_delay_measurement_delete
   5279  * Purpose:
   5280  *     Delete LM/DM IFP entry and install the same.
   5281  * Parameters:
   5282  *     unit      - (IN) BCM device number
   5283  *     oc        - (IN) Pointer to OAM control structure.
   5284  *     hash_data - (IN) Pointer to endpoint hash data.
   5285  * Retruns:
   5286  *     BCM_E_XXX
   5287  */
   5288 STATIC int
   5289 _bcm_tr3_oam_loss_delay_measurement_delete(int unit, _bcm_oam_control_t *oc, 
   5290                                             _bcm_oam_hash_data_t *hash_data) {
   5291 
   5292     int rv=0;
   5293     /*Hash data of existing endpoint on same vlan port */
   5294     _bcm_oam_hash_data_t *existing_ep_hash_data = NULL;
   5295     
   5296     if ( (NULL == oc) || (NULL == hash_data) ){
   5297         return (BCM_E_INTERNAL);
   5298     }    
   5299     
   5300     sal_memset(&_bcm_oam_lm_dm_search_data, 0, 
   5301                sizeof(_bcm_oam_lm_dm_search_data_type_t));
   5302 
   5303     /*Set the match criteria for LM search*/
   5304     _bcm_oam_lm_dm_search_data.match_type = hash_data->type;
   5305     _bcm_oam_lm_dm_search_data.match_ep_id = hash_data->ep_id;
   5306     _bcm_oam_lm_dm_search_data.match_vlan = hash_data->vlan;
   5307     _bcm_oam_lm_dm_search_data.match_gport = hash_data->gport;
   5308     _bcm_oam_lm_dm_search_data.highest_level = 0;
   5309     _bcm_oam_lm_dm_search_data.highest_level_ep_id = 0;
   5310     
   5311     /* Iterate over existing enpoint to find if 
   5312        other port vlan matching entry already exists */
   5313     rv = shr_htb_iterate(unit, oc->ma_mep_htbl, _bcm_lm_dm_search_cb);
   5314     if (BCM_FAILURE(rv)) {
   5315         LOG_ERROR(BSL_LS_BCM_OAM,
   5316                   (BSL_META_U(unit,
   5317                               "OAM Error: LM Search failed, EP=%d %s.\n"),
   5318                    hash_data->ep_id, bcm_errmsg(rv)));
   5319         return (rv);
   5320     }
   5321     
   5322     LOG_VERBOSE(BSL_LS_BCM_OAM,
   5323                 (BSL_META_U(unit,
   5324                             "OAM: Existing EP on vlan port count=%d, "
   5325                             "Highest level=%d, EP=%d\n"), 
   5326                  _bcm_oam_lm_dm_search_data.match_count,
   5327                  _bcm_oam_lm_dm_search_data.highest_level, 
   5328                  _bcm_oam_lm_dm_search_data.highest_level_ep_id));    
   5329     
   5330     if (hash_data->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT) {
   5331     
   5332         /* If another enpoint exists on same vlan port, 
   5333             Don't free primap and counter index, as they are shared */
   5334         if (_bcm_oam_lm_dm_search_data.match_count == 0){
   5335         
   5336             /* Free ING_SERVICE_PRI_MAP profile */
   5337             rv = soc_profile_mem_delete(unit, 
   5338                             &oc->ing_service_pri_map, 
   5339                             (hash_data->pri_map_index * BCM_OAM_INTPRI_MAX));
   5340             if (BCM_FAILURE(rv)) {
   5341                 LOG_ERROR(BSL_LS_BCM_OAM,
   5342                           (BSL_META_U(unit,
   5343                                       "OAM Error: ING_SERVICE_PRI_MAP profile "
   5344                                       "deletion, EP=%d %s.\n"), hash_data->ep_id, bcm_errmsg(rv)));
   5345                 return (rv);
   5346             }
   5347 
   5348             /* Free counter index. */
   5349             rv = shr_idxres_list_free( oc->lm_counter_pool, 
   5350                             (shr_idxres_element_t)hash_data->lm_counter_index);
   5351             if (BCM_FAILURE(rv)) {
   5352                 LOG_ERROR(BSL_LS_BCM_OAM,
   5353                           (BSL_META_U(unit,
   5354                                       "OAM Error: lm counter idx free failed, "
   5355                                       "EP=%d %s.\n"), hash_data->ep_id, bcm_errmsg(rv)));
   5356                 return (rv);
   5357             }
   5358         }
   5359     }
   5360 
   5361     /* If the EP we are deleting is at the lowest level and
   5362        other EP exist at higher level
   5363        Modify the other EP to remove Ethertype and Level match criteria. */
   5364     if ( _bcm_oam_lm_dm_search_data.match_count > 0 && 
   5365          _bcm_oam_lm_dm_search_data.highest_level < hash_data->level ) {
   5366     
   5367         existing_ep_hash_data = 
   5368             &oc->oam_hash_data[_bcm_oam_lm_dm_search_data.highest_level_ep_id];
   5369 
   5370         rv = bcm_esw_field_qualifier_delete(unit, 
   5371                 existing_ep_hash_data->fp_entry_tx, bcmFieldQualifyEtherType);
   5372         if (BCM_FAILURE(rv)) {
   5373             LOG_ERROR(BSL_LS_BCM_OAM,
   5374                       (BSL_META_U(unit,
   5375                                   "OAM Error: Eth Type dequlaify (tx), EP=%d %s.\n"),
   5376                        hash_data->ep_id, bcm_errmsg(rv)));
   5377                 return (rv);
   5378         }
   5379 
   5380         rv = bcm_esw_field_qualifier_delete(unit, 
   5381                 existing_ep_hash_data->fp_entry_tx, bcmFieldQualifyDstIp6);
   5382         if (BCM_FAILURE(rv)) {
   5383             LOG_ERROR(BSL_LS_BCM_OAM,
   5384                       (BSL_META_U(unit,
   5385                                   "OAM Error: Level dequlaify (tx), EP=%d %s.\n"),
   5386                        hash_data->ep_id, bcm_errmsg(rv)));
   5387                 return (rv);
   5388         }
   5389 
   5390         rv = bcm_esw_field_qualifier_delete(unit, 
   5391                 existing_ep_hash_data->fp_entry_rx, bcmFieldQualifyEtherType);
   5392         if (BCM_FAILURE(rv)) {
   5393             LOG_ERROR(BSL_LS_BCM_OAM,
   5394                       (BSL_META_U(unit,
   5395                                   "OAM Error: Eth Type dequlaify (rx), EP=%d %s.\n"),
   5396                        hash_data->ep_id, bcm_errmsg(rv)));
   5397                 return (rv);
   5398         }
   5399 
   5400         rv = bcm_esw_field_qualifier_delete(unit, 
   5401                 existing_ep_hash_data->fp_entry_rx, bcmFieldQualifyDstIp6);
   5402         if (BCM_FAILURE(rv)) {
   5403             LOG_ERROR(BSL_LS_BCM_OAM,
   5404                       (BSL_META_U(unit,
   5405                                   "OAM Error: Level dequlaify (rx), EP=%d %s.\n"),
   5406                        hash_data->ep_id, bcm_errmsg(rv)));
   5407                 return (rv);
   5408         }
   5409 
   5410         /* Install Modified entries */
   5411         rv = bcm_esw_field_entry_install(unit, 
   5412                                          existing_ep_hash_data->fp_entry_tx);
   5413         if (BCM_FAILURE(rv)) {
   5414             LOG_ERROR(BSL_LS_BCM_OAM,
   5415                       (BSL_META_U(unit,
   5416                                   "OAM Error: FP Install failed (tx), EP=%d %s.\n"),
   5417                        hash_data->ep_id, bcm_errmsg(rv)));
   5418             return (rv);
   5419         }
   5420 
   5421         rv = bcm_esw_field_entry_install(unit, 
   5422                                          existing_ep_hash_data->fp_entry_rx);
   5423         if (BCM_FAILURE(rv)) {
   5424             LOG_ERROR(BSL_LS_BCM_OAM,
   5425                       (BSL_META_U(unit,
   5426                                   "OAM Error: FP Install failed (tx), EP=%d %s.\n"),
   5427                        hash_data->ep_id, bcm_errmsg(rv)));
   5428             return (rv);
   5429         }
   5430         
   5431     }
   5432 
   5433     /* Delete FP entries for this EP*/
   5434     /* Tx Entry */
   5435     rv = bcm_esw_field_entry_destroy(unit, hash_data->fp_entry_tx);
   5436     /* Field init happens before oam init. Due to this, FP entries are already
   5437      * wiped out. Hence we need to ignore NOT_FOUND error. */
   5438     if ((BCM_FAILURE(rv)) && (rv != BCM_E_NOT_FOUND)) {
   5439         LOG_ERROR(BSL_LS_BCM_OAM,
   5440                   (BSL_META_U(unit,
   5441                               "OAM Error: FP Destroy failed (tx), EP=%d %s.\n"),
   5442                    hash_data->ep_id, bcm_errmsg(rv)));
   5443         return (rv);
   5444     }
   5445     hash_data->fp_entry_tx = -1;
   5446     
   5447     /* Rx Entry */
   5448     rv = bcm_esw_field_entry_destroy(unit, hash_data->fp_entry_rx);
   5449     /* Field init happens before oam init. Due to this, FP entries are already
   5450      * wiped out. Hence we need to ignore NOT_FOUND error. */
   5451     if ((BCM_FAILURE(rv)) && (rv != BCM_E_NOT_FOUND)) {
   5452         LOG_ERROR(BSL_LS_BCM_OAM,
   5453                   (BSL_META_U(unit,
   5454                               "OAM Error: FP Destroy failed (rx), EP=%d %s.\n"),
   5455                    hash_data->ep_id, bcm_errmsg(rv)));
   5456         return (rv);
   5457     }
   5458     hash_data->fp_entry_rx = -1;
   5459     
   5460     /* Trunk Entry */
   5461     if (hash_data->fp_entry_trunk[0] != -1) {
   5462         rv = bcm_esw_field_entry_destroy(unit, hash_data->fp_entry_trunk[0]);
   5463         /* Field init happens before oam init. Due to this, FP entries are already
   5464          * wiped out. Hence we need to ignore NOT_FOUND error. */
   5465         if ((BCM_FAILURE(rv)) && (rv != BCM_E_NOT_FOUND)) {
   5466             LOG_ERROR(BSL_LS_BCM_OAM,
   5467                       (BSL_META_U(unit,
   5468                                   "OAM Error: FP Destroy failed (Trunk), "
   5469                                   "EP=%d %s.\n"), hash_data->ep_id, bcm_errmsg(rv)));
   5470             return (rv);
   5471         }
   5472         hash_data->fp_entry_trunk[0] = -1;
   5473     }
   5474     
   5475     /* Decrement the group FP count */
   5476     oc->fp_glp_entry_cnt--;
   5477     LOG_VERBOSE(BSL_LS_BCM_OAM,
   5478                 (BSL_META_U(unit,
   5479                             "OAM: oc->fp_glp_entry_cnt=%d\n"), 
   5480                  oc->fp_glp_entry_cnt));
   5481     /* If count goes 0 delete the group */
   5482     if (!(oc->fp_glp_entry_cnt)) {
   5483         rv = bcm_esw_field_group_destroy(unit, oc->fp_glp_group);
   5484         /* Field init happens before oam init. Due to this, FP groups are already
   5485          * wiped out. Hence we need to ignore NOT_FOUND error. */
   5486         if ((BCM_FAILURE(rv)) && (rv != BCM_E_NOT_FOUND)) {
   5487             LOG_ERROR(BSL_LS_BCM_OAM,
   5488                       (BSL_META_U(unit,
   5489                                   "OAM Error: FP Group Destroy failed, EP=%d %s.\n"),
   5490                        hash_data->ep_id, bcm_errmsg(rv)));
   5491             return (rv);
   5492         }
   5493         /* clear FP group ID to indicate that group was deleted */
   5494         oc->fp_glp_group = -1;
   5495     }
   5496 
   5497     return (BCM_E_NONE);
   5498 }
   5499 
   5500 #ifdef BCM_WARM_BOOT_SUPPORT_SW_DUMP
   5501 void
   5502 _bcm_tr3_oam_group_info_dump(int unit, bcm_oam_group_t group_index,
   5503                              _bcm_oam_group_data_t *group_p)
   5504 {
   5505     int                     rv;
   5506     bcm_oam_group_info_t    group_info;
   5507 
   5508     /* Initialize the group information structure. */
   5509     bcm_oam_group_info_t_init(&group_info);
   5510 
   5511     /* Retrieve group information and set in group_info structure. */
   5512     rv = _bcm_tr3_oam_get_group(unit, group_index, group_p, &group_info);
   5513     if (BCM_FAILURE(rv)) {
   5514         LOG_ERROR(BSL_LS_BCM_OAM,
   5515                   (BSL_META_U(unit,
   5516                               "OAM(unit %d) Error: _bcm_tr3_oam_group_info_dump"
   5517                               " (GID=%d) - %s.\n"),
   5518                               unit, group_index, bcm_errmsg(rv)));
   5519         return;
   5520     }
   5521     LOG_CLI((BSL_META_U(unit,"------------------------------------------\r\n")));
   5522     LOG_CLI((BSL_META_U(unit,"Group ID = %d details\r\n"), group_index));
   5523     LOG_CLI((BSL_META_U(unit,"Group Name =  %s\r\n"), group_info.name));
   5524     LOG_CLI((BSL_META_U(unit,"Flags =  %d\r\n"), group_info.flags));
   5525     LOG_CLI((BSL_META_U(unit,"Faults =  %d\r\n"), group_info.faults));
   5526     LOG_CLI((BSL_META_U(unit,"Persistent_faults =  %d\r\n"),
   5527                               group_info.persistent_faults));
   5528     LOG_CLI((BSL_META_U(unit,"clear_persistent_faults =  %d\r\n"),
   5529                               group_info.clear_persistent_faults));
   5530     LOG_CLI((BSL_META_U(unit,"lowest_alarm_priority =  %d\r\n"),
   5531                               group_info.lowest_alarm_priority));
   5532     LOG_CLI((BSL_META_U(unit,"------------------------------------------\r\n")));
   5533 }
   5534 
   5535 /*
   5536  * Function:
   5537  *     _bcm_oam_sw_dump
   5538  * Purpose:
   5539  *     Displays oam information maintained by software.
   5540  * Parameters:
   5541  *     unit - Device unit number
   5542  * Returns:
   5543  *     None
   5544  */
   5545 void
   5546 _bcm_tr3_oam_sw_dump(int unit)
   5547 {
   5548     _bcm_oam_control_t      *oc;
   5549     int                     ep_id;
   5550     int                     rv;
   5551     bcm_oam_group_t         grp_idx;
   5552     _bcm_oam_group_data_t   *group_p;
   5553 
   5554     LOG_CLI((BSL_META_U(unit,"OAM\n")));
   5555     /* Get OAM control structure. */
   5556     rv = _bcm_oam_control_get(unit, &oc);
   5557     if(BCM_FAILURE(rv)) {
   5558         LOG_ERROR(BSL_LS_BCM_OAM,
   5559                 (BSL_META_U(unit,
   5560                 "OAM(unit %d) Error: Get oam control variable\n"),
   5561                  unit));
   5562 
   5563         return;
   5564     }
   5565 
   5566     _BCM_OAM_LOCK(oc);
   5567 
   5568     group_p = oc->group_info;
   5569     for (grp_idx = 0; grp_idx < oc->group_count; ++grp_idx) {
   5570         if (group_p[grp_idx].in_use == 1) {
   5571             _bcm_tr3_oam_group_info_dump(unit, grp_idx, group_p);
   5572         }
   5573     }
   5574 
   5575     _BCM_OAM_UNLOCK(oc);
   5576 
   5577     for(ep_id=0; ep_id < oc->ep_count; ep_id++) {
   5578         if (oc->oam_hash_data[ep_id].in_use) {
   5579             LOG_CLI((BSL_META_U(unit,"\toam_hash_data[%d].flags = %d\n"), 
   5580                          ep_id, oc->oam_hash_data[ep_id].flags));
   5581             LOG_CLI((BSL_META_U(unit,"\toam_hash_data[%d].flags2 = %d\n"), 
   5582                          ep_id, oc->oam_hash_data[ep_id].flags2));
   5583             LOG_CLI((BSL_META_U(unit,"\toam_hash_data[%d].fp_entry_rx = %d\n"),
   5584                          ep_id, oc->oam_hash_data[ep_id].fp_entry_rx));
   5585             LOG_CLI((BSL_META_U(unit,"\toam_hash_data[%d].fp_entry_tx = %d\n"),
   5586                          ep_id, oc->oam_hash_data[ep_id].fp_entry_tx));
   5587             LOG_CLI((BSL_META_U(unit,"\toam_hash_data[%d].type = %d\n"),
   5588                          ep_id,oc->oam_hash_data[ep_id].type));
   5589             LOG_CLI((BSL_META_U(unit,"\toam_hash_data[%d].ep_id = %d\n"),
   5590                          ep_id,oc->oam_hash_data[ep_id].ep_id));
   5591             LOG_CLI((BSL_META_U(unit,"\toam_hash_data[%d].is_remote = %d\n"),
   5592                          ep_id,oc->oam_hash_data[ep_id].is_remote));
   5593             LOG_CLI((BSL_META_U(unit,"\toam_hash_data[%d].local_tx_enabled = %d\n"),
   5594                          ep_id,oc->oam_hash_data[ep_id].local_tx_enabled));
   5595             LOG_CLI((BSL_META_U(unit,"\toam_hash_data[%d].local_rx_enabled = %d\n"),
   5596                          ep_id,oc->oam_hash_data[ep_id].local_rx_enabled));
   5597             LOG_CLI((BSL_META_U(unit,"\toam_hash_data[%d].group_index = %d\n"),
   5598                          ep_id,oc->oam_hash_data[ep_id].group_index));
   5599             LOG_CLI((BSL_META_U(unit,"\toam_hash_data[%d].name = %d\n"),
   5600                          ep_id,oc->oam_hash_data[ep_id].name));
   5601             LOG_CLI((BSL_META_U(unit,"\toam_hash_data[%d].level = %d\n"),
   5602                          ep_id,oc->oam_hash_data[ep_id].level));
   5603             LOG_CLI((BSL_META_U(unit,"\toam_hash_data[%d].vlan = %d\n"),
   5604                          ep_id,oc->oam_hash_data[ep_id].vlan));
   5605             LOG_CLI((BSL_META_U(unit,"\toam_hash_data[%d].gport = %d\n"),
   5606                          ep_id,oc->oam_hash_data[ep_id].gport));
   5607             LOG_CLI((BSL_META_U(unit,"\toam_hash_data[%d].sglp = %d\n"),
   5608                          ep_id,oc->oam_hash_data[ep_id].sglp));
   5609             LOG_CLI((BSL_META_U(unit,"\toam_hash_data[%d].dglp = %d\n"),
   5610                          ep_id,oc->oam_hash_data[ep_id].dglp));
   5611             LOG_CLI((BSL_META_U(unit,"\toam_hash_data[%d].opcode_flags = %d\n"),
   5612                          ep_id,oc->oam_hash_data[ep_id].opcode_flags));
   5613             LOG_CLI((BSL_META_U(unit,"\toam_hash_data[%d].period = %d\n"),
   5614                          ep_id,oc->oam_hash_data[ep_id].period));
   5615             LOG_CLI((BSL_META_U(unit,"\toam_hash_data[%d].in_use = %d\n"),
   5616                          ep_id,oc->oam_hash_data[ep_id].in_use));
   5617             LOG_CLI((BSL_META_U(unit,"\toam_hash_data[%d].fp_entry_trunk[0] = %d\n"),
   5618                          ep_id,oc->oam_hash_data[ep_id].fp_entry_trunk[0]));
   5619             LOG_CLI((BSL_META_U(unit,"\toam_hash_data[%d].ts_format = %d\n"),
   5620                          ep_id,oc->oam_hash_data[ep_id].ts_format));
   5621             LOG_CLI((BSL_META_U(unit,"\toam_hash_data[%d].local_tx_index = %d\n"),
   5622                          ep_id,oc->oam_hash_data[ep_id].local_tx_index));
   5623             LOG_CLI((BSL_META_U(unit,"\toam_hash_data[%d].local_rx_index = %d\n"),
   5624                          ep_id,oc->oam_hash_data[ep_id].local_rx_index));
   5625             LOG_CLI((BSL_META_U(unit,"\toam_hash_data[%d].remote_index = %d\n"),
   5626                          ep_id,oc->oam_hash_data[ep_id].remote_index));
   5627             LOG_CLI((BSL_META_U(unit,"\toam_hash_data[%d].inner_vlan = %d\n"),               
   5628                          ep_id,oc->oam_hash_data[ep_id].inner_vlan));            
   5629             LOG_CLI((BSL_META_U(unit,"\toam_hash_data[%d].lm_counter_index = %d\n"),                
   5630                          ep_id,oc->oam_hash_data[ep_id].lm_counter_index));             
   5631             LOG_CLI((BSL_META_U(unit,"\toam_hash_data[%d].pri_map_index = %d\n"),                
   5632                          ep_id,oc->oam_hash_data[ep_id].pri_map_index));             
   5633             LOG_CLI((BSL_META_U(unit,"\toam_hash_data[%d].vp = %d\n"),        
   5634                          ep_id,oc->oam_hash_data[ep_id].vp));     
   5635             LOG_CLI((BSL_META_U(unit,"\toam_hash_data[%d].vfp_entry = %d\n"),              
   5636                          ep_id,oc->oam_hash_data[ep_id].vfp_entry));
   5637         }
   5638     }
   5639 }
   5640 #endif
   5641 
   5642 #if defined(BCM_WARM_BOOT_SUPPORT)
   5643 /*
   5644  * Function:
   5645  *     _bcm_tr3_oam_endpoint_alloc
   5646  * Purpose:
   5647  *     Allocate an endpoint memory element.
   5648  * Parameters:
   5649  *     ep_pp - (IN/OUT) Pointer to endpoint address pointer.
   5650  * Returns:
   5651  *     BCM_E_XXX
   5652  */
   5653 STATIC int
   5654 _bcm_tr3_oam_endpoint_alloc(bcm_oam_endpoint_info_t **ep_pp)
   5655 {
   5656     bcm_oam_endpoint_info_t *ep_p = NULL;
   5657 
   5658     _BCM_OAM_ALLOC(ep_p, bcm_oam_endpoint_info_t,
   5659                    sizeof(bcm_oam_endpoint_info_t), "Endpoint info");
   5660     if (NULL == ep_p) {
   5661         return (BCM_E_MEMORY);
   5662     }
   5663     
   5664     *ep_pp = ep_p;
   5665 
   5666     return (BCM_E_NONE);
   5667 
   5668 }
   5669 
   5670 /*
   5671  * Function:
   5672  *     _bcm_tr3_oam_sync
   5673  * Purpose:
   5674  *     Store OAM configuration to level two storage cache memory.
   5675  * Parameters:
   5676  *     unit - (IN) Device unit number
   5677  * Returns:
   5678  *     BCM_E_XXX
   5679  */
   5680 int
   5681 _bcm_tr3_oam_sync(int unit)
   5682 {
   5683     _bcm_oam_control_t  *oc;
   5684     int                 alloc_size = 0;
   5685     int                 stable_size;
   5686     soc_scache_handle_t scache_handle;
   5687     uint8               *oam_scache;
   5688     int                 grp_idx;
   5689     _bcm_oam_group_data_t *group_p;   /* Pointer to group list.         */
   5690     int                 group_count = 0;
   5691     int                 rv;
   5692     _bcm_oam_ep_list_t  *ep_list_p = NULL;
   5693     _bcm_oam_hash_data_t ep_data;
   5694 
   5695     /* Get OAM module storage size. */
   5696     SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size));
   5697 
   5698     /* If level 2 store is not configured return from here. */
   5699     if (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit) || (stable_size == 0)) {
   5700         return (BCM_E_NONE);                                                      
   5701     }
   5702 
   5703     /* Get handle to control structure. */
   5704     BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc));
   5705 
   5706     _BCM_OAM_LOCK(oc);
   5707 
   5708     /* Initialize to group array pointer. */
   5709     group_p = oc->group_info;
   5710 
   5711     /* Storing the valid group count, as was done in BCM_WB_VERSION_1_0 */
   5712     for (grp_idx = 0; grp_idx < oc->group_count; grp_idx++) {
   5713         if (BCM_E_EXISTS
   5714             == shr_idxres_list_elem_state(oc->group_pool, grp_idx)) {
   5715             group_count++;
   5716         }
   5717     }
   5718     
   5719     alloc_size += BCM_OAM_GROUP_NAME_LENGTH * (oc->group_count);
   5720 
   5721     /* To store OAM group count. */
   5722     alloc_size += sizeof(int);
   5723 
   5724     /* To store FP GID. */
   5725     alloc_size += 3 * sizeof(bcm_field_group_t);
   5726 
   5727     /* To store EP Ids */
   5728     alloc_size += (sizeof (bcm_oam_endpoint_t) * 
   5729                     (oc->rmep_count + oc->lmep_count + oc->ma_idx_count)); 
   5730 
   5731     /* To store MEP TX , RX and LAG LM/DM FP entry numbers */
   5732     alloc_size += ((sizeof (bcm_field_entry_t) * 3) * 
   5733                     (oc->ma_idx_count));
   5734 
   5735     /* Store the BHH Hw config */
   5736     alloc_size += _bcm_tr3_oam_bhh_hw_config_scache_size_get(unit);
   5737 
   5738     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_OAM, 0);
   5739 
   5740     /* Check if memory has already been allocated */
   5741     rv = _bcm_esw_scache_ptr_get(unit,
   5742                                  scache_handle,
   5743                                  0,
   5744                                  alloc_size,
   5745                                  &oam_scache,
   5746                                  BCM_WB_DEFAULT_VERSION,
   5747                                  NULL
   5748                                  );
   5749     if (!SOC_WARM_BOOT(unit) && (BCM_E_NOT_FOUND == rv)) {
   5750         rv = _bcm_esw_scache_ptr_get(unit,
   5751                                      scache_handle,
   5752                                      1,
   5753                                      alloc_size,
   5754                                      &oam_scache,
   5755                                      BCM_WB_DEFAULT_VERSION,
   5756                                      NULL
   5757                                      );
   5758         if (BCM_FAILURE(rv)
   5759             || (NULL == oam_scache)) {
   5760             goto cleanup;
   5761         }
   5762     } else if (BCM_FAILURE(rv)) {
   5763         goto cleanup;
   5764     }
   5765 
   5766     /* Store the FP groups */
   5767     sal_memcpy(oam_scache, &oc->vfp_group, sizeof(bcm_field_group_t));
   5768     oam_scache += sizeof(bcm_field_group_t);
   5769 
   5770     sal_memcpy(oam_scache, &oc->fp_vp_group, sizeof(bcm_field_group_t));
   5771     oam_scache += sizeof(bcm_field_group_t);
   5772 
   5773     sal_memcpy(oam_scache, &oc->fp_glp_group, sizeof(bcm_field_group_t));
   5774     oam_scache += sizeof(bcm_field_group_t);
   5775 
   5776     sal_memcpy(oam_scache, &group_count, sizeof(int));
   5777     oam_scache += sizeof(int);
   5778 
   5779     for (grp_idx = 0; grp_idx < oc->group_count; ++grp_idx)
   5780     {
   5781         sal_memcpy(oam_scache, group_p[grp_idx].name,
   5782                    BCM_OAM_GROUP_NAME_LENGTH);
   5783         
   5784         oam_scache += BCM_OAM_GROUP_NAME_LENGTH;
   5785     }
   5786 
   5787 
   5788     /* Store logical endpoint indexes
   5789        Following is scache allocation for different types of EPs
   5790        Rx MEP indexes (16K)
   5791        RMEP index (8K)
   5792        Tx MEP indexes (2K) 
   5793      */
   5794     sal_memset(oam_scache, 0, (sizeof (bcm_oam_endpoint_t) * 
   5795                 (oc->rmep_count + oc->lmep_count + oc->ma_idx_count))); 
   5796     for (grp_idx = 0; grp_idx < oc->group_count; ++grp_idx)
   5797     {
   5798         if (group_p[grp_idx].in_use == 1) {
   5799             ep_list_p = *(group_p[grp_idx].ep_list);
   5800             while (ep_list_p != NULL) {
   5801                 ep_data = *ep_list_p->ep_data_p; 
   5802                 if (ep_data.type == bcmOAMEndpointTypeEthernet) {
   5803 
   5804                     if (ep_data.is_remote) {
   5805                         sal_memcpy(oam_scache + 
   5806                         sizeof(bcm_oam_endpoint_t) * (oc->ma_idx_count + 
   5807                         ep_data.remote_index), 
   5808                         &(ep_data.ep_id), sizeof (bcm_oam_endpoint_t)); 
   5809 
   5810                     } else {
   5811                         if (ep_data.local_tx_enabled) {
   5812                             sal_memcpy(oam_scache + 
   5813                             sizeof(bcm_oam_endpoint_t) * (oc->ma_idx_count + 
   5814                             oc->rmep_count + ep_data.local_tx_index),
   5815                             &(ep_data.ep_id), sizeof (bcm_oam_endpoint_t));
   5816 
   5817                         }
   5818                         if (ep_data.local_rx_enabled) { 
   5819                             sal_memcpy(oam_scache + 
   5820                             sizeof(bcm_oam_endpoint_t) * (ep_data.local_rx_index),
   5821                             &(ep_data.ep_id), sizeof (bcm_oam_endpoint_t));
   5822 
   5823                         }
   5824                     } 
   5825                 }
   5826                 ep_list_p = ep_list_p->next;
   5827             }
   5828         } 
   5829     }
   5830     oam_scache +=  (sizeof (bcm_oam_endpoint_t) * 
   5831                 (oc->rmep_count + oc->lmep_count + oc->ma_idx_count));
   5832 
   5833     /*Rx MEP Tx and Rx FP entry numbers for LM/DM*/
   5834     sal_memset(oam_scache, 0, ((sizeof (bcm_field_entry_t) * 3) *
   5835                 (oc->ma_idx_count)));
   5836     for (grp_idx = 0; grp_idx < oc->group_count; ++grp_idx)
   5837     {
   5838         if (group_p[grp_idx].in_use == 1) {
   5839             ep_list_p = *(group_p[grp_idx].ep_list);
   5840             while (ep_list_p != NULL) {
   5841                 ep_data = *ep_list_p->ep_data_p;
   5842                 if ((ep_data.type == bcmOAMEndpointTypeEthernet) && 
   5843                     (!(ep_data.is_remote))) {
   5844                     if ((ep_data.local_rx_enabled) &&
   5845                         ((ep_data.flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT) ||
   5846                         (ep_data.flags & BCM_OAM_ENDPOINT_DELAY_MEASUREMENT))) {
   5847                         sal_memcpy(oam_scache +
   5848                                 (sizeof(bcm_oam_endpoint_t) * (ep_data.local_rx_index)),
   5849                                 &(ep_data.fp_entry_rx), sizeof (bcm_field_entry_t));
   5850                         sal_memcpy(oam_scache + (sizeof(bcm_oam_endpoint_t) * (oc->ma_idx_count))+
   5851                                 (sizeof(bcm_oam_endpoint_t) * (ep_data.local_rx_index)),
   5852                                 &(ep_data.fp_entry_tx), sizeof (bcm_field_entry_t));
   5853                         sal_memcpy(oam_scache + (sizeof(bcm_oam_endpoint_t) * (oc->ma_idx_count) * 2)+
   5854                                 (sizeof(bcm_oam_endpoint_t) * (ep_data.local_rx_index)),
   5855                                 &(ep_data.fp_entry_trunk[0]), sizeof (bcm_field_entry_t));
   5856                     }
   5857                 }
   5858                 ep_list_p = ep_list_p->next;
   5859             }
   5860         }
   5861     }
   5862     oam_scache += (sizeof(bcm_field_entry_t) * 3) * (oc->ma_idx_count);
   5863 
   5864 #if defined (INCLUDE_BHH)
   5865     if(soc_feature(unit, soc_feature_bhh)) {
   5866         if(oc->ukernel_not_ready == 0) {
   5867             sal_memcpy(oam_scache, &(oc->bhh_lm_dm_enable),
   5868                                              sizeof(oc->bhh_lm_dm_enable));
   5869             oam_scache += sizeof(oc->bhh_lm_dm_enable);
   5870 
   5871             if (oc->bhh_lm_dm_enable) {
   5872                 sal_memcpy(oam_scache, &(oc->bhh_udf_mode),
   5873                                                 sizeof(oc->bhh_udf_mode));
   5874                 oam_scache += sizeof(oc->bhh_udf_mode);
   5875 
   5876                 if (oc->bhh_udf_mode) {
   5877 
   5878                     sal_memcpy(oam_scache, &(oc->bhh_label_udf_id),
   5879                                                    sizeof(oc->bhh_label_udf_id));
   5880                     oam_scache += sizeof(oc->bhh_label_udf_id);
   5881 
   5882                     sal_memcpy(oam_scache, &(oc->bhh_ach_udf_id),
   5883                                                      sizeof(oc->bhh_ach_udf_id));
   5884                     oam_scache += sizeof(oc->bhh_ach_udf_id);
   5885 
   5886                     sal_memcpy(oam_scache, &(oc->bhh_opcode_udf_id),
   5887                                                   sizeof(oc->bhh_opcode_udf_id));
   5888                     oam_scache += sizeof(oc->bhh_opcode_udf_id);
   5889 
   5890                     sal_memcpy(oam_scache, &(oc->bhh_udf_pkt_fmt_id),
   5891                                                  sizeof(oc->bhh_udf_pkt_fmt_id));
   5892                     oam_scache += sizeof(oc->bhh_udf_pkt_fmt_id);
   5893 
   5894                 } else {
   5895 
   5896                     sal_memcpy(oam_scache, &(oc->bhh_label_qual_id),
   5897                                                  sizeof(oc->bhh_label_qual_id));
   5898                     oam_scache += sizeof(oc->bhh_label_qual_id);
   5899 
   5900                     sal_memcpy(oam_scache, &(oc->bhh_ach_qual_id),
   5901                                                    sizeof(oc->bhh_ach_qual_id));
   5902                     oam_scache += sizeof(oc->bhh_ach_qual_id);
   5903 
   5904                     sal_memcpy(oam_scache, &(oc->bhh_opcode_qual_id),
   5905                                                  sizeof(oc->bhh_opcode_qual_id));
   5906                     oam_scache += sizeof(oc->bhh_opcode_qual_id);
   5907                 }
   5908             }
   5909         }
   5910     }
   5911 #endif /* INCLUDE_BHH */
   5912 
   5913 cleanup:
   5914     _BCM_OAM_UNLOCK(oc);
   5915     return (rv);
   5916 }
   5917 
   5918 /*
   5919  * Function:
   5920  *     _bcm_tr3_oam_wb_group_recover
   5921  * Purpose:
   5922  *     Recover OAM group configuratoin.
   5923  * Parameters:
   5924  *     unit        - (IN) BCM device number
   5925  *     stable_size - (IN) OAM module Level2 storage size.
   5926  *     oam_scache  - (IN) Pointer to scache address pointer.
   5927  * Returns:
   5928  *     BCM_E_XXX
   5929  */
   5930 STATIC int
   5931 _bcm_tr3_oam_wb_group_recover(int unit, int stable_size, uint8 **oam_scache, 
   5932                               int grpal) 
   5933 {
   5934     int                    index;                    /* Hw table index.     */
   5935     _bcm_oam_group_data_t  *group_p;                 /* Group info pointer. */
   5936     maid_reduction_entry_t maid_entry;               /* Group entry info.   */
   5937     ma_state_entry_t       ma_state_ent;             /* Group state info.   */
   5938     int                    maid_reduction_valid = 0; /* Group valid.        */
   5939     int                    ma_state_valid = 0;       /* Group state valid.  */
   5940     _bcm_oam_control_t     *oc;                      /* Pointer to Control  */
   5941                                                      /* structure.          */
   5942     int                     rv;                      /* Operation return    */
   5943                                                      /* status.             */
   5944 
   5945     /* Control lock taken by calling routine. */
   5946     /* Get OAM control structure. */
   5947     BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc));
   5948 
   5949     for (index = 0; index < oc->group_count; index++) {
   5950 
   5951         rv = READ_MAID_REDUCTIONm(unit, MEM_BLOCK_ANY, index,
   5952                                   &maid_entry);
   5953         if (BCM_FAILURE(rv)) {
   5954             LOG_ERROR(BSL_LS_BCM_OAM,
   5955                       (BSL_META_U(unit,
   5956                                   "OAM Error: (GID=%d) MAID_REDUCTION table read"
   5957                                    " failed  - %s.\n"), index, bcm_errmsg(rv)));
   5958             goto cleanup;
   5959         }
   5960 
   5961         rv = READ_MA_STATEm(unit, MEM_BLOCK_ANY, index, &ma_state_ent);
   5962         if (BCM_FAILURE(rv)) {
   5963             LOG_ERROR(BSL_LS_BCM_OAM,
   5964                       (BSL_META_U(unit,
   5965                                   "OAM Error: (GID=%d) MA_STATE table read"
   5966                                    " failed  - %s.\n"), index, bcm_errmsg(rv)));
   5967             goto cleanup;
   5968         }
   5969 
   5970         maid_reduction_valid
   5971             = soc_MAID_REDUCTIONm_field32_get(unit, &maid_entry, VALIDf);
   5972 
   5973         ma_state_valid
   5974             = soc_MA_STATEm_field32_get(unit, &ma_state_ent, VALIDf);
   5975 
   5976         if (maid_reduction_valid || ma_state_valid) {
   5977 
   5978             /* Entry must be valid in both the tables, else return error. */
   5979             if (!maid_reduction_valid || !ma_state_valid) {
   5980                 rv = BCM_E_INTERNAL;
   5981                 goto cleanup;
   5982             }
   5983 
   5984             /* Get the group memory pointer. */
   5985             group_p = &oc->group_info[index];
   5986 
   5987             if (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit) || (stable_size == 0)) {
   5988 
   5989                 /* Set group name as zeros. */
   5990                 sal_memset(group_p->name, 0, BCM_OAM_GROUP_NAME_LENGTH);
   5991 
   5992             } else {
   5993                 if (grpal) {
   5994                     sal_memcpy(group_p->name, 
   5995                                *oam_scache + index * BCM_OAM_GROUP_NAME_LENGTH, 
   5996                                BCM_OAM_GROUP_NAME_LENGTH);
   5997                 } else {
   5998                     /* Get the group name from stored info. */
   5999                     sal_memcpy(group_p->name, *oam_scache, BCM_OAM_GROUP_NAME_LENGTH);
   6000                     *oam_scache = (*oam_scache + BCM_OAM_GROUP_NAME_LENGTH);
   6001                 }
   6002             }
   6003 
   6004             /* Reserve the group index. */
   6005             rv = shr_idxres_list_reserve(oc->group_pool, index, index);
   6006             if (BCM_FAILURE(rv)) {
   6007                 rv = (rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv;
   6008                 LOG_ERROR(BSL_LS_BCM_OAM,
   6009                           (BSL_META_U(unit,
   6010                                       "OAM Error: (GID=%d) Index reserve "
   6011                                        " failed  - %s.\n"), index, bcm_errmsg(rv)));
   6012                 goto cleanup;
   6013             }
   6014 
   6015             /* Create the linked list to maintain group endpoint information. */
   6016             _BCM_OAM_ALLOC((group_p->ep_list), _bcm_oam_ep_list_t *,
   6017                            sizeof(_bcm_oam_ep_list_t *), "EP list head");
   6018             if (NULL == group_p->ep_list) {
   6019                 rv = BCM_E_MEMORY;
   6020                 goto cleanup;
   6021             }
   6022 
   6023             /* Initialize head node.*/
   6024             *group_p->ep_list =  NULL;
   6025             group_p->in_use = 1;
   6026         }
   6027     }
   6028 
   6029     return (BCM_E_NONE);
   6030 
   6031 cleanup:
   6032 
   6033     if (BCM_E_EXISTS
   6034         == shr_idxres_list_elem_state(oc->group_pool, index)) {
   6035         shr_idxres_list_free(oc->group_pool, index);
   6036     }
   6037 
   6038     return (rv);
   6039 
   6040 }
   6041 
   6042 /*
   6043  * Function:
   6044  *     _bcm_tr3_oam_rmep_recover
   6045  * Purpose:
   6046  *     Recover OAM remote endpoint configuration.
   6047  * Parameters:
   6048  *     unit        - (IN) BCM device number
   6049  *     index       - (IN) Remote MEP hardware index.
   6050  *     l3_entry    - (IN) RMEP view table entry pointer.
   6051  * Returns:
   6052  *     BCM_E_XXX
   6053  */
   6054 STATIC int
   6055 _bcm_tr3_oam_rmep_recover(int unit, int index, uint32 *l3_entry, uint8 **scache, 
   6056                            uint16 recovered_ver)
   6057 {
   6058     rmep_entry_t            rmep_entry;      /* Remote table entry.           */
   6059     _bcm_oam_hash_data_t    *h_data_p;       /* Endpoint hash data pointer.   */
   6060     _bcm_oam_control_t      *oc;             /* Pointer to control structure. */
   6061     int                     rv;              /* Operation return status.      */
   6062     _bcm_gport_dest_t       gport_dest;      /* Gport specification.          */
   6063     bcm_gport_t             gport;           /* Gport value.                  */
   6064     uint8                   source_type;     /* Virtual or Logical Port.      */
   6065     uint16                  glp;             /* Generic logical port value.   */
   6066     bcm_oam_endpoint_info_t *ep_info = NULL; /* Endpoint information.         */
   6067     _bcm_oam_hash_key_t     hash_key;        /* Hash key buffer for lookup.   */
   6068     int                     ep_id;           /* Endpoint ID.                  */
   6069     soc_mem_t               mem;             /* L3 entry memory               */
   6070     int                     rmep_index;      /* Index of RMEP table           */ 
   6071 
   6072     LOG_DEBUG(BSL_LS_BCM_OAM,
   6073               (BSL_META_U(unit,
   6074                           "OAM Info: _bcm_tr3_oam_rmep_recover.\n")));
   6075     /*
   6076      * Get OAM control structure.
   6077      *     Note: Lock taken by calling routine.
   6078      */
   6079     BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc));
   6080 
   6081     if (SOC_IS_HURRICANE2(unit) || SOC_IS_GREYHOUND(unit) ||
   6082         SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) {
   6083         mem = L3_ENTRY_IPV4_UNICASTm;
   6084     } else {
   6085         mem = L3_ENTRY_1m;
   6086     }
   6087 
   6088     if (recovered_ver >= BCM_WB_VERSION_1_2) {
   6089         /* Recover EP index from scache */ 
   6090         rmep_index = soc_mem_field32_get(unit, mem, l3_entry, RMEP__RMEP_PTRf);
   6091         sal_memcpy(&ep_id, *scache + (sizeof(bcm_oam_endpoint_t) * 
   6092                    (oc->ma_idx_count + rmep_index)), sizeof(bcm_oam_endpoint_t));
   6093         rv = shr_idxres_list_reserve(oc->mep_pool, ep_id, ep_id);
   6094         if (BCM_FAILURE(rv)) {
   6095             rv = (rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv;
   6096             LOG_ERROR(BSL_LS_BCM_OAM,
   6097                 (BSL_META_U(unit,
   6098                     "OAM Error: (EP_ID=%d) Index reserve "
   6099                     " failed  - %s.\n"), ep_id, bcm_errmsg(rv)));
   6100             return (rv);
   6101         }
   6102 
   6103     } else {
   6104 
   6105         /* Allocate the next available endpoint index. */
   6106         rv = shr_idxres_list_alloc(oc->mep_pool,
   6107                                (shr_idxres_element_t *)&ep_id);
   6108         if (BCM_FAILURE(rv)) {
   6109             LOG_ERROR(BSL_LS_BCM_OAM,
   6110                       (BSL_META_U(unit,
   6111                                   "OAM Error: Endpoint alloc (EP=%d) - %s.\n"),
   6112                        ep_id, bcm_errmsg(rv)));
   6113             return (rv);
   6114         }
   6115     }
   6116 
   6117     h_data_p = &oc->oam_hash_data[ep_id];
   6118 
   6119     /* 
   6120      * Clear the hash data element contents before
   6121      * storing values.
   6122      */
   6123     _BCM_OAM_HASH_DATA_CLEAR(h_data_p);
   6124 
   6125     /* Get RMEP table index from LMEP view entry. */
   6126     h_data_p->remote_index
   6127         = soc_mem_field32_get(unit, mem, l3_entry, RMEP__RMEP_PTRf);
   6128 
   6129     /* Get RMEP table entry contents. */
   6130     rv = READ_RMEPm(unit, MEM_BLOCK_ANY, h_data_p->remote_index, &rmep_entry);
   6131     if (BCM_FAILURE(rv)) {
   6132         LOG_ERROR(BSL_LS_BCM_OAM,
   6133                   (BSL_META_U(unit,
   6134                               "OAM Error: RMEP (index=%d) read failed  - %s.\n"),
   6135                    h_data_p->remote_index, bcm_errmsg(rv)));
   6136         goto cleanup;
   6137     }
   6138 
   6139    /* Has to be a valid RMEP, return error otherwise. */
   6140     if (!soc_RMEPm_field32_get(unit, &rmep_entry, VALIDf)) {
   6141         rv = BCM_E_INTERNAL;
   6142         goto cleanup;
   6143     }
   6144     
   6145     h_data_p->ep_id = ep_id;
   6146 
   6147     h_data_p->is_remote = 1;
   6148 
   6149     h_data_p->flags |= BCM_OAM_ENDPOINT_REMOTE;
   6150 
   6151     h_data_p->group_index
   6152         = soc_RMEPm_field32_get(unit, &rmep_entry, MAID_INDEXf);
   6153 
   6154     h_data_p->period
   6155         = _bcm_tr3_oam_ccm_hw_encode_to_msecs
   6156             ((int) soc_RMEPm_field32_get(unit, &rmep_entry,
   6157                                          RMEP_RECEIVED_CCMf));
   6158 
   6159     h_data_p->name
   6160         = soc_mem_field32_get(unit, mem, l3_entry, RMEP__MEPIDf);
   6161 
   6162     h_data_p->level
   6163         = soc_mem_field32_get(unit, mem, l3_entry, RMEP__MDLf);
   6164 
   6165     h_data_p->vlan
   6166         = soc_mem_field32_get(unit, mem, l3_entry, RMEP__VIDf);
   6167 
   6168     h_data_p->local_tx_index = _BCM_OAM_INVALID_INDEX;
   6169     h_data_p->local_rx_index = _BCM_OAM_INVALID_INDEX;
   6170 
   6171     if (SOC_MEM_FIELD_VALID(unit, mem, RMEP__SOURCE_TYPEf)) {
   6172         source_type
   6173             = soc_mem_field32_get(unit, mem, l3_entry, RMEP__SOURCE_TYPEf);
   6174     } else {
   6175         source_type = 0;
   6176     }
   6177     glp = soc_mem_field32_get(unit, mem, l3_entry, RMEP__SGLPf);
   6178 
   6179     /* Check if virtual port type. */
   6180     if (1 == source_type) {
   6181         /*
   6182          * Virtual port type, construct gport value from VP.
   6183          */
   6184         h_data_p->vp = glp;
   6185 #if defined(INCLUDE_L3)
   6186         if (_bcm_vp_used_get(unit, glp, _bcmVpTypeMim)) {
   6187             BCM_GPORT_MIM_PORT_ID_SET(h_data_p->gport, h_data_p->vp);
   6188 
   6189          } else if (_bcm_vp_used_get(unit, glp, _bcmVpTypeMpls)) {
   6190 
   6191             BCM_GPORT_MPLS_PORT_ID_SET(h_data_p->gport, h_data_p->vp);
   6192 
   6193          } else {
   6194             LOG_ERROR(BSL_LS_BCM_OAM,
   6195                       (BSL_META_U(unit,
   6196                                   "OAM Error: Invalid Virtual Port (SVP=%d) "
   6197                                    "- %s.\n"), h_data_p->vp, bcm_errmsg(BCM_E_INTERNAL)));
   6198             rv = BCM_E_INTERNAL;
   6199             goto cleanup;
   6200          }
   6201 #endif
   6202     } else {
   6203         /*
   6204          * Generic logical port type, construct gport from GLP.
   6205          */
   6206         h_data_p->sglp = glp;
   6207 
   6208         _bcm_gport_dest_t_init(&gport_dest);
   6209 
   6210         if (_BCM_OAM_GLP_TRUNK_BIT_GET(unit, glp)) {
   6211             gport_dest.tgid = _BCM_OAM_GLP_TRUNK_ID_GET(unit, glp);
   6212             gport_dest.gport_type = _SHR_GPORT_TYPE_TRUNK;
   6213         } else {
   6214             gport_dest.gport_type = _SHR_GPORT_TYPE_MODPORT;
   6215             gport_dest.modid = _BCM_OAM_GLP_MODULE_ID_GET(unit, glp);
   6216             gport_dest.port = _BCM_OAM_GLP_PORT_GET(unit, glp);
   6217         }
   6218 
   6219         rv = _bcm_esw_gport_construct(unit, &gport_dest, &gport);
   6220         if (BCM_FAILURE(rv)) {
   6221             LOG_ERROR(BSL_LS_BCM_OAM,
   6222                       (BSL_META_U(unit,
   6223                                   "OAM Error: Gport construct failed - %s.\n"),
   6224                        bcm_errmsg(rv)));
   6225             goto cleanup;
   6226         }
   6227 
   6228         h_data_p->gport = gport;
   6229     }
   6230 
   6231     rv = shr_idxres_list_reserve(oc->rmep_pool,
   6232                                  h_data_p->remote_index,
   6233                                  h_data_p->remote_index);
   6234     if (BCM_FAILURE(rv)) {
   6235         LOG_ERROR(BSL_LS_BCM_OAM,
   6236                   (BSL_META_U(unit,
   6237                               "OAM Error: (RMEP=%d) Index reserve failed  - %s.\n"),
   6238                    h_data_p->remote_index, bcm_errmsg(rv)));
   6239         rv = (rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv;
   6240         goto cleanup;
   6241     }
   6242 
   6243     h_data_p->in_use = 1;
   6244 
   6245     rv = _bcm_oam_group_ep_list_add(unit, h_data_p->group_index, ep_id);
   6246     if (BCM_FAILURE(rv)) {
   6247         goto cleanup;
   6248     }
   6249 
   6250     rv = _bcm_tr3_oam_endpoint_alloc(&ep_info);
   6251     if (BCM_FAILURE(rv)) {
   6252         _bcm_oam_group_ep_list_remove(unit, h_data_p->group_index, ep_id);
   6253         goto cleanup;
   6254     }
   6255 
   6256     bcm_oam_endpoint_info_t_init(ep_info);
   6257 
   6258     /* Set up endpoint information for key construction. */
   6259     ep_info->group = h_data_p->group_index;
   6260     ep_info->name = h_data_p->name;
   6261     ep_info->gport = h_data_p->gport;
   6262     ep_info->level = h_data_p->level;
   6263     ep_info->vlan = h_data_p->vlan;
   6264     ep_info->id= h_data_p->ep_id;
   6265 
   6266     /* Calculate hash key for hash table insert operation. */
   6267     _bcm_oam_ep_hash_key_construct(unit, oc, ep_info, &hash_key);
   6268 
   6269     rv = shr_htb_insert(oc->ma_mep_htbl, hash_key, h_data_p);
   6270     if (BCM_FAILURE(rv)) {
   6271         LOG_ERROR(BSL_LS_BCM_OAM,
   6272                   (BSL_META_U(unit,
   6273                               "OAM Error: Hash table insert failed "
   6274                                "EP=%d %s.\n"), h_data_p->ep_id, bcm_errmsg(rv)));
   6275         _bcm_oam_group_ep_list_remove(unit, h_data_p->group_index, ep_id);
   6276         goto cleanup;
   6277     } else {
   6278         LOG_DEBUG(BSL_LS_BCM_OAM,
   6279                   (BSL_META_U(unit,
   6280                               "OAM Info: Hash Tbl (EP=%d) inserted"
   6281                                " - %s.\n"), ep_id, bcm_errmsg(rv)));
   6282     }
   6283 
   6284     /* Add the H/w index to logical index mapping for RMEP */
   6285     oc->remote_endpoints[h_data_p->remote_index] = ep_info->id;
   6286 
   6287     sal_free(ep_info);
   6288     ep_info = NULL;
   6289 
   6290     LOG_DEBUG(BSL_LS_BCM_OAM,
   6291               (BSL_META_U(unit,
   6292                           "OAM Info: _bcm_tr3_oam_rmep_recover - done.\n")));
   6293 
   6294     return (rv);
   6295 
   6296 cleanup:
   6297 
   6298     if (NULL != ep_info) {
   6299         sal_free(ep_info);
   6300     }
   6301 
   6302     /* Release the endpoint ID if in use. */
   6303     if (BCM_E_EXISTS
   6304         == shr_idxres_list_elem_state(oc->mep_pool, ep_id)) {
   6305         shr_idxres_list_free(oc->mep_pool, ep_id);
   6306     }
   6307 
   6308     /* Release the remote index if in use. */
   6309     if ((h_data_p->in_use == 1)
   6310         && (BCM_E_EXISTS
   6311             == shr_idxres_list_elem_state(oc->rmep_pool,
   6312                                           h_data_p->remote_index))) {
   6313         shr_idxres_list_free(oc->rmep_pool, h_data_p->remote_index);
   6314 
   6315         _BCM_OAM_HASH_DATA_CLEAR(h_data_p);
   6316     }
   6317 
   6318     LOG_DEBUG(BSL_LS_BCM_OAM,
   6319               (BSL_META_U(unit,
   6320                           "OAM Info: _bcm_tr3_oam_rmep_recover - error_done.\n")));
   6321     return (rv);
   6322 }
   6323 
   6324 /*
   6325  * Function:
   6326  *     _bcm_tr3_oam_lmep_rx_config_recover
   6327  * Purpose:
   6328  *     Recover OAM local endpoint Rx configuration.
   6329  * Parameters:
   6330  *     unit        - (IN) BCM device number
   6331  *     index       - (IN) Remote MEP hardware index.
   6332  *     l3_entry    - (IN) LMEP view table entry pointer.
   6333  * Returns:
   6334  *     BCM_E_XXX
   6335  */
   6336 STATIC int
   6337 _bcm_tr3_oam_lmep_rx_config_recover(int unit, int index, uint32 *l3_entry, 
   6338                                     uint8 **scache, uint16 recovered_ver)
   6339 {
   6340     _bcm_oam_hash_data_t    *h_data_p = NULL; /* Endpoint hash data pointer. */
   6341     ma_index_entry_t        ma_idx_entry; /* IA_INDEX table entry.           */
   6342     _bcm_oam_control_t      *oc;          /* Pointer to control structure.   */
   6343     uint8                   mdl_bitmap;   /* Endpoint domain level bitmap.   */
   6344     uint8                   mdl;          /* Maintenance domain level.       */
   6345     int                     rv;           /* Operation return status.        */
   6346     _bcm_gport_dest_t       gport_dest;   /* Gport specification.            */
   6347     bcm_gport_t             gport;        /* Gport value.                    */
   6348     uint8                   source_type;  /* Virtual or Logical Port.        */
   6349     uint16                  glp;          /* Generic logical port value.     */
   6350     uint32                  ma_base_idx;
   6351     int                     ep_id;        /* Endpoint ID.                    */
   6352     _bcm_oam_hash_key_t     hash_key;     /* Hash key buffer for lookup.     */
   6353     bcm_oam_endpoint_info_t *ep_info = NULL; /* Endpoint information.        */
   6354     soc_mem_t               mem;          /* L3 entry memory                 */
   6355     int                     ma_idx;       /* MA_TABLE index                  */ 
   6356     
   6357     LOG_DEBUG(BSL_LS_BCM_OAM,
   6358               (BSL_META_U(unit,
   6359                           "OAM Info: _bcm_tr3_oam_lmep_rx_config_recover.\n")));
   6360     /*
   6361      * Get OAM control structure.
   6362      *     Note: Lock taken by calling routine.
   6363      */
   6364     BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc));
   6365 
   6366     if (SOC_IS_HURRICANE2(unit) || SOC_IS_GREYHOUND(unit) ||
   6367         SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) {
   6368         mem = L3_ENTRY_IPV4_UNICASTm;
   6369     } else {
   6370         mem = L3_ENTRY_1m;
   6371     }
   6372 
   6373     mdl_bitmap
   6374         = soc_mem_field32_get(unit, mem, l3_entry, LMEP__MDL_BITMAPf);
   6375     
   6376     for (mdl = 0; mdl < _BCM_OAM_EP_LEVEL_COUNT; mdl++) {
   6377 
   6378         if (mdl_bitmap & (1 << mdl)) {
   6379             if (recovered_ver >= BCM_WB_VERSION_1_2) {
   6380                 ma_base_idx = soc_mem_field32_get(unit, mem, l3_entry,
   6381                                                 LMEP__MA_BASE_PTRf);
   6382                 ma_idx = (ma_base_idx <<  _BCM_OAM_EP_LEVEL_BIT_COUNT) + mdl;
   6383                 sal_memcpy(&ep_id, *(scache) + sizeof(bcm_oam_endpoint_t) * 
   6384                            ma_idx, sizeof(bcm_oam_endpoint_t));
   6385                 rv = shr_idxres_list_reserve(oc->mep_pool, ep_id, ep_id);
   6386                 if (BCM_FAILURE(rv)) {
   6387                     rv = (rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv;
   6388                     LOG_ERROR(BSL_LS_BCM_OAM, 
   6389                               (BSL_META_U(unit,
   6390                             "OAM Error: (EP_ID=%d) Index reserve "
   6391                             " failed  - %s.\n"), ep_id, bcm_errmsg(rv)));
   6392                     return (rv);
   6393                 }
   6394 
   6395             } else {
   6396                 /* Allocate the next available endpoint index. */
   6397                 rv = shr_idxres_list_alloc(oc->mep_pool,
   6398                                        (shr_idxres_element_t *)&ep_id);
   6399                 if (BCM_FAILURE(rv)) {
   6400                     LOG_ERROR(BSL_LS_BCM_OAM,
   6401                               (BSL_META_U(unit,
   6402                                           "OAM Error: Endpoint alloc (EP=%d) - %s.\n"),
   6403                                ep_id, bcm_errmsg(rv)));
   6404                     goto cleanup;
   6405                 }
   6406             }
   6407 
   6408             h_data_p = &oc->oam_hash_data[ep_id];
   6409 
   6410             /* 
   6411              * Clear the hash data element contents before
   6412              * storing values.
   6413              */
   6414             _BCM_OAM_HASH_DATA_CLEAR(h_data_p);
   6415 
   6416             _BCM_OAM_HASH_DATA_HW_IDX_INIT(h_data_p);
   6417 
   6418             h_data_p->ep_id = ep_id;
   6419 
   6420             h_data_p->local_rx_index
   6421                 = ((soc_mem_field32_get(unit, mem, l3_entry,
   6422                         LMEP__MA_BASE_PTRf) << _BCM_OAM_EP_LEVEL_BIT_COUNT)
   6423                         | mdl);
   6424 
   6425             rv = READ_MA_INDEXm
   6426                     (unit, MEM_BLOCK_ANY, h_data_p->local_rx_index,
   6427                      &ma_idx_entry);
   6428             if (BCM_FAILURE(rv)) {
   6429                 LOG_ERROR(BSL_LS_BCM_OAM,
   6430                           (BSL_META_U(unit,
   6431                                       "OAM Error: MA_INDEX (index:%d) read failed -"
   6432                                        " %s.\n"), h_data_p->local_rx_index,
   6433                            bcm_errmsg(rv)));
   6434                 goto cleanup;
   6435             }
   6436 
   6437             h_data_p->in_use = 1;
   6438 
   6439             h_data_p->is_remote = 0;
   6440 
   6441             h_data_p->local_rx_enabled = 1;
   6442 
   6443             h_data_p->flags |= BCM_OAM_ENDPOINT_CCM_RX;
   6444 
   6445             h_data_p->group_index
   6446                 = soc_MA_INDEXm_field32_get(unit, &ma_idx_entry, MA_PTRf);
   6447 
   6448             h_data_p->profile_index
   6449                 = soc_MA_INDEXm_field32_get
   6450                     (unit, &ma_idx_entry, OAM_OPCODE_CONTROL_PROFILE_PTRf);
   6451                        
   6452             rv = soc_profile_mem_reference(unit, &oc->oam_opcode_control_profile,
   6453                                            h_data_p->profile_index, 1);
   6454             
   6455             h_data_p->name = 0xffff;
   6456             
   6457             h_data_p->level = mdl;
   6458 
   6459             h_data_p->vlan
   6460                 = soc_mem_field32_get(unit, mem, l3_entry, LMEP__VIDf);
   6461 
   6462             if (SOC_MEM_FIELD_VALID(unit, mem, LMEP__SOURCE_TYPEf)) {
   6463                 source_type
   6464                     = soc_mem_field32_get(unit, mem, l3_entry, LMEP__SOURCE_TYPEf);
   6465             } else {
   6466                 source_type = 0;
   6467             }
   6468 
   6469             glp = soc_mem_field32_get(unit, mem, l3_entry, LMEP__SGLPf);
   6470 
   6471 
   6472             /* Check if virtual port type. */
   6473             if (1 == source_type) {
   6474                 /*
   6475                  * Virtual port type, construct gport value from VP.
   6476                  */
   6477                 h_data_p->vp = glp;
   6478 #if defined(INCLUDE_L3)
   6479                 if (_bcm_vp_used_get(unit, glp, _bcmVpTypeMim)) {
   6480 
   6481                     BCM_GPORT_MIM_PORT_ID_SET(h_data_p->gport, h_data_p->vp);
   6482 
   6483                 } else if (_bcm_vp_used_get(unit, glp, _bcmVpTypeMpls)) {
   6484 
   6485                     BCM_GPORT_MPLS_PORT_ID_SET(h_data_p->gport, h_data_p->vp);
   6486 
   6487                 } else {
   6488                     LOG_ERROR(BSL_LS_BCM_OAM,
   6489                               (BSL_META_U(unit,
   6490                                           "OAM Error: Invalid Virtual Port (SVP=%d)"
   6491                                            " - %s.\n"), h_data_p->vp,
   6492                                bcm_errmsg(BCM_E_INTERNAL)));
   6493                     return (BCM_E_INTERNAL);
   6494                 }
   6495 #endif
   6496             } else {
   6497                 /*
   6498                  * Generic logical port type, construct gport from GLP.
   6499                  */
   6500                 h_data_p->sglp = glp;
   6501 
   6502                 _bcm_gport_dest_t_init(&gport_dest);
   6503 
   6504                 if (_BCM_OAM_GLP_TRUNK_BIT_GET(unit, glp)) {
   6505                     gport_dest.tgid = _BCM_OAM_GLP_TRUNK_ID_GET(unit, glp);
   6506                     gport_dest.gport_type = _SHR_GPORT_TYPE_TRUNK;
   6507                 } else {
   6508                     gport_dest.gport_type = _SHR_GPORT_TYPE_MODPORT;
   6509                     gport_dest.modid = _BCM_OAM_GLP_MODULE_ID_GET(unit, glp);
   6510                     gport_dest.port = _BCM_OAM_GLP_PORT_GET(unit, glp);
   6511                 }
   6512 
   6513                 rv = _bcm_esw_gport_construct(unit, &gport_dest, &gport);
   6514                 if (BCM_FAILURE(rv)) {
   6515                     LOG_ERROR(BSL_LS_BCM_OAM,
   6516                               (BSL_META_U(unit,
   6517                                           "OAM Error: Gport construct failed -"
   6518                                            " %s.\n"), bcm_errmsg(rv)));
   6519                     goto cleanup;
   6520                 }
   6521 
   6522                 h_data_p->gport = gport;
   6523             }
   6524             h_data_p->fp_entry_tx = -1;
   6525             h_data_p->fp_entry_rx = -1;
   6526             h_data_p->fp_entry_trunk[0] = -1;
   6527             ma_base_idx = soc_mem_field32_get(unit, mem, l3_entry,
   6528                                               LMEP__MA_BASE_PTRf);
   6529             ma_base_idx = ma_base_idx <<  _BCM_OAM_EP_LEVEL_BIT_COUNT;
   6530             
   6531             rv = shr_idxres_list_reserve(oc->ma_idx_pool,
   6532                                          ma_base_idx,
   6533                                           ma_base_idx + 7);
   6534     
   6535             /* ma_index for all 8 levels is reserved during first endpoint 
   6536                recovery as baseindex is common for all 8 levels, 
   6537                as such during second endpoint recovery with different 
   6538                level BCM_E_RESOURCE is expected and not an error 
   6539              */ 
   6540             if ( (BCM_FAILURE(rv)) && (rv != BCM_E_RESOURCE) ) {
   6541                 LOG_ERROR(BSL_LS_BCM_OAM,
   6542                           (BSL_META_U(unit,
   6543                                       "OAM Error: (RMEP=%d) Index reserve failed"
   6544                                        "  - %s.\n"), h_data_p->remote_index,
   6545                            bcm_errmsg(rv)));
   6546                 goto cleanup;
   6547             }
   6548 
   6549             rv = _bcm_oam_group_ep_list_add(unit, h_data_p->group_index, ep_id);
   6550             if (BCM_FAILURE(rv)) {
   6551                 goto cleanup;
   6552             }
   6553 
   6554             rv = _bcm_tr3_oam_endpoint_alloc(&ep_info);
   6555             if (BCM_FAILURE(rv)) {
   6556                 _bcm_oam_group_ep_list_remove(unit,
   6557                                               h_data_p->group_index,
   6558                                               ep_id);
   6559                 goto cleanup;
   6560             }
   6561 
   6562             bcm_oam_endpoint_info_t_init(ep_info);
   6563 
   6564             /* Set up endpoint information for key construction. */
   6565             ep_info->group = h_data_p->group_index;
   6566             ep_info->name = h_data_p->name;
   6567             ep_info->gport = h_data_p->gport;
   6568             ep_info->level = h_data_p->level;
   6569             ep_info->vlan = h_data_p->vlan;
   6570 
   6571             /*
   6572              * Calculate hash key for hash table insert
   6573              * operation.
   6574              */
   6575             _bcm_oam_ep_hash_key_construct(unit, oc, ep_info, &hash_key);
   6576 
   6577             sal_free(ep_info);
   6578             ep_info = NULL;
   6579 
   6580             rv = shr_htb_insert(oc->ma_mep_htbl, hash_key, h_data_p);
   6581             if (BCM_FAILURE(rv)) {
   6582                 LOG_ERROR(BSL_LS_BCM_OAM,
   6583                           (BSL_META_U(unit,
   6584                                       "OAM Error: Hash table insert"
   6585                                        " (EP=%d) failed - %s.\n"),
   6586                            h_data_p->ep_id, bcm_errmsg(rv)));
   6587 
   6588                 _bcm_oam_group_ep_list_remove(unit,
   6589                                               h_data_p->group_index,
   6590                                               ep_id);
   6591                 goto cleanup;
   6592             } else {
   6593                 LOG_DEBUG(BSL_LS_BCM_OAM,
   6594                           (BSL_META_U(unit,
   6595                                       "OAM Info: Hash Tbl (EP=%d)"
   6596                                        " inserted  - %s.\n"), ep_id,
   6597                            bcm_errmsg(rv)));
   6598             }
   6599         }
   6600     }
   6601 
   6602     LOG_DEBUG(BSL_LS_BCM_OAM,
   6603               (BSL_META_U(unit,
   6604                           "OAM Info: _bcm_tr3_oam_lmep_rx_config_recover"
   6605                            " - done.\n")));
   6606     return (BCM_E_NONE);
   6607 
   6608 cleanup:
   6609 
   6610     if (NULL != ep_info) {
   6611         sal_free(ep_info);
   6612     }
   6613 
   6614     if (BCM_E_EXISTS
   6615         == shr_idxres_list_elem_state(oc->mep_pool, ep_id)) {
   6616         shr_idxres_list_free(oc->mep_pool, ep_id);
   6617     }
   6618 
   6619     if (NULL != h_data_p
   6620         && (BCM_E_EXISTS
   6621             == shr_idxres_list_elem_state(oc->ma_idx_pool,
   6622                                           h_data_p->local_rx_index))) {
   6623 
   6624         shr_idxres_list_free(oc->ma_idx_pool, h_data_p->local_rx_index);
   6625 
   6626         _BCM_OAM_HASH_DATA_CLEAR(h_data_p);
   6627     }
   6628 
   6629     LOG_DEBUG(BSL_LS_BCM_OAM,
   6630               (BSL_META_U(unit,
   6631                           "OAM Info: _bcm_tr3_oam_lmep_rx_config_recover"
   6632                            " - error_done.\n")));
   6633     return (rv);
   6634 }
   6635 
   6636 /*
   6637  * Function:
   6638  *     _bcm_tr3_oam_lmep_tx_config_recover
   6639  * Purpose:
   6640  *     Recover OAM local endpoint Tx configuration.
   6641  * Parameters:
   6642  *     unit        - (IN) BCM device number
   6643  * Returns:
   6644  *     BCM_E_XXX
   6645  */
   6646 STATIC int
   6647 _bcm_tr3_oam_lmep_tx_config_recover(int unit, uint8 **scache, 
   6648                                     uint16 recovered_ver)
   6649 {
   6650     _bcm_gport_dest_t       gport_dest;   /* Gport specification.             */
   6651     bcm_gport_t             gport;        /* Gport value.                     */
   6652     int                     index = 0;    /* Hardware index.                  */
   6653     lmep_entry_t            lmep_entry;   /* LMEP table entry buffer.         */
   6654     maid_reduction_entry_t  maid_red_ent; /* MAID_REDUCTION table entry buf.  */ 
   6655     _bcm_oam_hash_key_t     hash_key;     /* Hash key buffer for lookup.      */
   6656     _bcm_oam_group_data_t   *g_info_p;    /* Group information pointer.       */
   6657     _bcm_oam_control_t      *oc;          /* Pointer to control structure.    */
   6658     bcm_module_t            modid;        /* Module ID.                       */
   6659     bcm_port_t              port_id;      /* Port ID.                         */
   6660     bcm_trunk_t             trunk_id;     /* Trunk ID.                        */
   6661     uint32                  grp_idx;      /* Group index.                     */
   6662     uint16                  glp,sglp;          /* Generic logical port.            */
   6663     uint16                  vlan;         /* VLAN ID.                         */
   6664     uint8                   level;        /* Maintenance domain level.        */
   6665     _bcm_oam_ep_list_t      *cur;         /* Current head node pointer.       */
   6666     int                     ep_id = -1;   /* Endpoint ID.                     */
   6667     uint8                   match_found = 0; /* Matching endpoint found.      */
   6668     int                     rv;           /* Operation return status.         */
   6669     bcm_oam_endpoint_info_t *ep_info = NULL; /* Endpoint information.         */
   6670     _bcm_oam_hash_data_t    *h_data_p = NULL; /* Endpoint hash data pointer.  */
   6671     _bcm_oam_hash_data_t    *sh_data_p = NULL; /* Endpoint hash data pointer. */
   6672     uint32                  ccm_period = 0;
   6673     int                     trunk_index = -1;
   6674 #ifdef BCM_HURRICANE2_SUPPORT
   6675     uint32  rval = 0;
   6676     uint8   tx_disable = 0;
   6677 #endif /* BCM_HURRICANE2_SUPPORT */
   6678 
   6679     LOG_DEBUG(BSL_LS_BCM_OAM,
   6680               (BSL_META_U(unit,
   6681                           "OAM Info: _bcm_tr3_oam_lmep_tx_config_recover.\n")));
   6682 
   6683     /*
   6684      * Get OAM control structure.
   6685      *     Note: Lock taken by calling routine.
   6686      */
   6687     BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc));
   6688 
   6689     rv = _bcm_tr3_oam_endpoint_alloc(&ep_info);
   6690     if (BCM_FAILURE(rv)) {
   6691         return (rv);
   6692     }
   6693 
   6694     /*
   6695      * At this point, Remote MEP and Local MEP Rx config has been
   6696      *  recovered. Now, recover the Tx config for Local MEPs.
   6697      */
   6698 #ifdef BCM_HURRICANE2_SUPPORT
   6699     rv = _bcm_oam_modify_oam_tx_control (unit, &rval, 1, &tx_disable);
   6700     if (BCM_FAILURE(rv)) { 
   6701         LOG_ERROR(BSL_LS_BCM_OAM,
   6702                   (BSL_META_U(unit,
   6703                   "OAM Error: in _bcm_oam_modify_oam_tx_control \n")));
   6704         goto cleanup;
   6705     }
   6706 #endif /* BCM_HURRICANE2_SUPPORT */
   6707 
   6708     for (index = 0; index < oc->lmep_count; index++) {
   6709 
   6710         /* Get the LMEP table entry. */
   6711         rv = READ_LMEPm(unit, MEM_BLOCK_ANY, index, &lmep_entry);
   6712         if (BCM_FAILURE(rv)) {
   6713             LOG_ERROR(BSL_LS_BCM_OAM,
   6714                       (BSL_META_U(unit,
   6715                                   "OAM Error: LMEP table read (index=%d) failed "
   6716                                    "- %s.\n"), index, bcm_errmsg(rv)));
   6717             goto cleanup;
   6718         }
   6719 
   6720         grp_idx = soc_LMEPm_field32_get(unit, &lmep_entry, MAID_INDEXf);
   6721         ccm_period = _bcm_tr3_oam_ccm_hw_encode_to_msecs
   6722                      ((int)soc_LMEPm_field32_get(unit, &lmep_entry, 
   6723                                                  CCM_INTERVALf));
   6724         if (ccm_period == BCM_OAM_ENDPOINT_CCM_PERIOD_DISABLED) {
   6725             continue;
   6726         } 
   6727    
   6728        rv = READ_MAID_REDUCTIONm(unit, MEM_BLOCK_ANY, grp_idx, &maid_red_ent);
   6729         if (BCM_FAILURE(rv)) {
   6730             LOG_ERROR(BSL_LS_BCM_OAM,
   6731                       (BSL_META_U(unit,
   6732                                   "OAM Error: MAID_REDU read (GID=%d) failed "
   6733                                    "- %s.\n"), grp_idx, bcm_errmsg(rv)));
   6734             goto cleanup;
   6735         }
   6736 
   6737         if (soc_MAID_REDUCTIONm_field32_get(unit, &maid_red_ent, VALIDf)) {
   6738 
   6739             /* Get pointer to group memory. */
   6740             g_info_p = &oc->group_info[grp_idx];
   6741 
   6742             vlan = soc_LMEPm_field32_get(unit, &lmep_entry, VLAN_IDf);
   6743 
   6744             glp = soc_LMEPm_field32_get(unit, &lmep_entry, DESTf);
   6745 
   6746             level = soc_LMEPm_field32_get(unit, &lmep_entry, MDLf);
   6747 
   6748             modid = _BCM_OAM_DGLP_MODULE_ID_GET(glp);
   6749 
   6750             port_id = _BCM_OAM_GLP_PORT_GET(unit, glp);
   6751 
   6752             trunk_id = BCM_TRUNK_INVALID;
   6753             rv = bcm_esw_trunk_find(unit, modid, port_id, &trunk_id);
   6754             if (BCM_FAILURE(rv)
   6755                 && (BCM_E_NOT_FOUND != rv)) {
   6756                 goto cleanup;
   6757             }
   6758 
   6759             _bcm_gport_dest_t_init(&gport_dest);
   6760 
   6761             if (BCM_TRUNK_INVALID != trunk_id) {
   6762                 gport_dest.tgid = trunk_id;
   6763                 gport_dest.gport_type = _SHR_GPORT_TYPE_TRUNK;
   6764                 _BCM_TR3_OAM_MOD_PORT_TO_GLP(unit, -1,
   6765                     -1, 1, gport_dest.tgid, sglp);
   6766 
   6767                 rv = _bcm_esw_oam_lmep_tx_trunk_config_recover(unit, 
   6768                         trunk_id, 
   6769                         port_id,
   6770                         &trunk_index);
   6771 
   6772                 if(BCM_FAILURE(rv)) {
   6773                     goto cleanup;
   6774                 }
   6775             } else {
   6776                 gport_dest.gport_type = _SHR_GPORT_TYPE_MODPORT;
   6777                 gport_dest.modid = _BCM_OAM_DGLP_MODULE_ID_GET(glp);
   6778                 gport_dest.port = _BCM_OAM_GLP_PORT_GET(unit, glp);
   6779                 _BCM_TR3_OAM_MOD_PORT_TO_GLP(unit, gport_dest.modid,
   6780                     gport_dest.port, 0, -1, sglp);
   6781             }
   6782 
   6783             rv = _bcm_esw_gport_construct(unit, &gport_dest, &gport);
   6784             if (BCM_FAILURE(rv)) {
   6785                 LOG_ERROR(BSL_LS_BCM_OAM,
   6786                           (BSL_META_U(unit,
   6787                                       "OAM Error: Gport construct failed"
   6788                                        " - %s.\n"), bcm_errmsg(rv)));
   6789                 goto cleanup;
   6790             }
   6791 
   6792             /* Get the endpoint list head pointer. */
   6793             cur = *(g_info_p->ep_list);
   6794             if (NULL != cur) {
   6795                 while (NULL != cur) {
   6796                     h_data_p = cur->ep_data_p;
   6797                     if (NULL == h_data_p) {
   6798                         LOG_ERROR(BSL_LS_BCM_OAM,
   6799                                   (BSL_META_U(unit,
   6800                                               "OAM Error: Group (GID=%d) NULL"
   6801                                                " endpoint list.\n"), grp_idx));
   6802                         rv = BCM_E_INTERNAL;
   6803                         goto cleanup;
   6804                     }
   6805 
   6806                     if (vlan == h_data_p->vlan
   6807                         && gport == h_data_p->gport
   6808                         && level == h_data_p->level
   6809                         && 1 == h_data_p->local_rx_enabled) {
   6810                         match_found = 1;
   6811                         break;
   6812                     }
   6813                     cur = cur->next;
   6814                 }
   6815             }
   6816 
   6817             if (1 == match_found) {
   6818 
   6819                 bcm_oam_endpoint_info_t_init(ep_info);
   6820 
   6821                 /* Set up endpoint information for key construction. */
   6822                 ep_info->group = h_data_p->group_index;
   6823                 ep_info->name = h_data_p->name;
   6824                 ep_info->gport = h_data_p->gport;
   6825                 ep_info->level = h_data_p->level;
   6826                 ep_info->vlan = h_data_p->vlan;
   6827                 ep_info->flags = h_data_p->flags;
   6828                 /*
   6829                  * Calculate hash key for hash table insert
   6830                  * operation.
   6831                  */
   6832                 _bcm_oam_ep_hash_key_construct(unit, oc, ep_info, &hash_key);
   6833 
   6834                 _BCM_OAM_ALLOC(sh_data_p, _bcm_oam_hash_data_t,
   6835                                sizeof(_bcm_oam_hash_data_t), "Hash data");
   6836 
   6837                 if (NULL == sh_data_p) {
   6838                     goto cleanup;
   6839                 }
   6840 
   6841                 /*
   6842                  * Delete insert done by Local Rx endpoint recovery code.
   6843                  * Endpoint name has been recovered and will result
   6844                  * in a different hash index.
   6845                  */
   6846                 rv = shr_htb_find(oc->ma_mep_htbl, hash_key,
   6847                                   (shr_htb_data_t *)sh_data_p, 1);
   6848                 if (BCM_E_NOT_FOUND == rv) {
   6849                     goto cleanup;
   6850                 }
   6851 
   6852                 sal_free(sh_data_p);
   6853                 sh_data_p = NULL;
   6854 
   6855             } else {
   6856 
   6857                 if (recovered_ver >= BCM_WB_VERSION_1_2) {
   6858 
   6859                     sal_memcpy(&ep_id, *(scache) + sizeof(bcm_oam_endpoint_t) *
   6860                     (oc->rmep_count + oc->ma_idx_count + index), 
   6861                     sizeof(bcm_oam_endpoint_t));                
   6862 
   6863                     rv = shr_idxres_list_reserve(oc->mep_pool, ep_id, ep_id);
   6864                     if (BCM_FAILURE(rv)) {
   6865                         rv = (rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv;
   6866                         LOG_ERROR(BSL_LS_BCM_OAM,
   6867                         (BSL_META_U(unit,
   6868                             "OAM Error: (EP_ID=%d) Index reserve "
   6869                             " failed  - %s.\n"), ep_id, bcm_errmsg(rv)));
   6870                         goto cleanup;
   6871                     }
   6872                 } else { 
   6873                     /* Allocate the next available endpoint index. */
   6874                     rv = shr_idxres_list_alloc(oc->mep_pool,
   6875                                            (shr_idxres_element_t *)&ep_id);
   6876                     if (BCM_FAILURE(rv)) {
   6877                         LOG_ERROR(BSL_LS_BCM_OAM,
   6878                                   (BSL_META_U(unit,
   6879                                               "OAM Error: Endpoint alloc (EP=%d)"
   6880                                                " - %s.\n"), ep_id, bcm_errmsg(rv)));
   6881                         goto cleanup;
   6882                     }
   6883                 }
   6884 
   6885                 h_data_p = &oc->oam_hash_data[ep_id];
   6886 
   6887                 _BCM_OAM_HASH_DATA_CLEAR(h_data_p);
   6888 
   6889                 _BCM_OAM_HASH_DATA_HW_IDX_INIT(h_data_p);
   6890 
   6891                 rv = _bcm_oam_group_ep_list_add(unit, grp_idx, ep_id);
   6892                 if (BCM_FAILURE(rv)) {
   6893                     LOG_ERROR(BSL_LS_BCM_OAM,
   6894                               (BSL_META_U(unit,
   6895                                           "OAM Error: Adding (EP=%d)"
   6896                                            " to (GID=%d) failed - %s.\n"),
   6897                                ep_id, grp_idx, bcm_errmsg(rv)));
   6898                     goto cleanup;
   6899                 }
   6900 
   6901                 h_data_p->ep_id = ep_id;
   6902                 h_data_p->group_index = grp_idx;
   6903                 h_data_p->local_rx_enabled = 0;
   6904                 h_data_p->vlan = vlan;
   6905                 h_data_p->sglp = sglp;
   6906                 h_data_p->dglp = glp;
   6907                 h_data_p->gport = gport;
   6908                 h_data_p->level = level;
   6909             }
   6910 
   6911             h_data_p->is_remote = 0;
   6912             h_data_p->local_tx_enabled = 1;
   6913             h_data_p->local_tx_index = index;
   6914             h_data_p->name
   6915                 = soc_LMEPm_field32_get(unit, &lmep_entry, MEPIDf);
   6916 
   6917             h_data_p->period = _bcm_tr3_oam_ccm_hw_encode_to_msecs
   6918                                ((int)soc_LMEPm_field32_get(unit, &lmep_entry, 
   6919                                                            CCM_INTERVALf));
   6920             if((-1) != trunk_index) {
   6921                 h_data_p->trunk_index = trunk_index;
   6922             }
   6923             rv = shr_idxres_list_reserve(oc->lmep_pool,
   6924                                          h_data_p->local_tx_index,
   6925                                          h_data_p->local_tx_index);
   6926             if (BCM_FAILURE(rv)) {
   6927                 LOG_ERROR(BSL_LS_BCM_OAM,
   6928                           (BSL_META_U(unit,
   6929                                       "OAM Error: Tx index=%d reserve failed"
   6930                                        " - %s.\n"), index, bcm_errmsg(rv)));
   6931 
   6932                 _bcm_oam_group_ep_list_remove(unit,
   6933                                               h_data_p->group_index,
   6934                                               h_data_p->ep_id);
   6935 
   6936                 rv = (rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv;
   6937                 goto cleanup;
   6938             }
   6939 
   6940             bcm_oam_endpoint_info_t_init(ep_info);
   6941 
   6942             /* Set up endpoint information for key construction. */
   6943             ep_info->group = h_data_p->group_index;
   6944             ep_info->name = h_data_p->name;
   6945             ep_info->gport = h_data_p->gport;
   6946             ep_info->level = h_data_p->level;
   6947             ep_info->vlan = h_data_p->vlan;
   6948             ep_info->flags = h_data_p->flags;
   6949             /*
   6950              * Calculate hash key for hash table insert
   6951              * operation.
   6952              */
   6953             _bcm_oam_ep_hash_key_construct(unit, oc, ep_info, &hash_key);
   6954 
   6955             rv = shr_htb_insert(oc->ma_mep_htbl, hash_key, h_data_p);
   6956             if (BCM_FAILURE(rv)) {
   6957                 LOG_ERROR(BSL_LS_BCM_OAM,
   6958                           (BSL_META_U(unit,
   6959                                       "OAM Error: Hash table insert"
   6960                                        " (EP=%d) failed - %s.\n"),
   6961                            h_data_p->ep_id, bcm_errmsg(rv)));
   6962 
   6963                 _bcm_oam_group_ep_list_remove(unit,
   6964                                               h_data_p->group_index,
   6965                                               h_data_p->ep_id);
   6966 
   6967                 goto cleanup;
   6968             } else {
   6969                 LOG_DEBUG(BSL_LS_BCM_OAM,
   6970                           (BSL_META_U(unit,
   6971                                       "OAM Info: Hash Tbl (EP=%d)"
   6972                                        " inserted  - %s.\n"), h_data_p->ep_id,
   6973                            bcm_errmsg(rv)));
   6974             }
   6975 
   6976         }
   6977 
   6978         match_found = 0;
   6979         h_data_p = NULL;
   6980     }
   6981 #ifdef BCM_HURRICANE2_SUPPORT
   6982     if (tx_disable) {
   6983         rv = _bcm_oam_modify_oam_tx_control (unit, &rval, 0, &tx_disable);
   6984         if (BCM_FAILURE(rv)) {
   6985             LOG_ERROR(BSL_LS_BCM_OAM,
   6986                       (BSL_META_U(unit,
   6987                       "OAM Error: in _bcm_oam_modify_oam_tx_control \n")));
   6988             goto cleanup;
   6989         }
   6990     }
   6991 #endif /* BCM_HURRICANE2_SUPPORT */
   6992 
   6993 /*SDK-147457:HW WAR to fix the issue of wrong LMEP index being written
   6994   while deleting and adding same MEP in a loop */
   6995 #ifdef BCM_HURRICANE2_SUPPORT
   6996     sal_usleep(3400);
   6997 #endif /* BCM_HURRICANE2_SUPPORT */
   6998 
   6999     LOG_DEBUG(BSL_LS_BCM_OAM,
   7000               (BSL_META_U(unit,
   7001                           "OAM Info: _bcm_tr3_oam_lmep_tx_config_recover"
   7002                            " - done.\n")));
   7003     sal_free(ep_info);
   7004     return (rv);
   7005 
   7006 cleanup:
   7007 
   7008     if (NULL != sh_data_p) {
   7009         sal_free(sh_data_p);
   7010     }
   7011 
   7012     if (NULL != ep_info) {
   7013         sal_free(ep_info);
   7014     }
   7015 
   7016     if (0 == match_found && NULL != h_data_p) {
   7017         /* Return endpoint index to MEP pool. */
   7018         if (BCM_E_EXISTS
   7019             == shr_idxres_list_elem_state(oc->mep_pool, ep_id)) {
   7020             shr_idxres_list_free(oc->mep_pool, ep_id);
   7021         }
   7022         _BCM_OAM_HASH_DATA_CLEAR(h_data_p);
   7023     }
   7024 
   7025     if (BCM_E_EXISTS
   7026         == shr_idxres_list_elem_state(oc->lmep_pool, index)) {
   7027         shr_idxres_list_free(oc->lmep_pool, index);
   7028     }
   7029 
   7030     LOG_DEBUG(BSL_LS_BCM_OAM,
   7031               (BSL_META_U(unit,
   7032                           "OAM Info: _bcm_tr3_oam_lmep_tx_config_recover"
   7033                            " - error_done.\n")));
   7034     return (rv);
   7035 }
   7036 
   7037 /*
   7038  * Function:
   7039  *     _bcm_tr3_oam_wb_endpoints_recover
   7040  * Purpose:
   7041  *     Recover OAM local endpoint Rx configuration.
   7042  * Parameters:
   7043  *     unit        - Device unit number.
   7044  *     stable_size - OAM module Level2 memory size.
   7045  *     oam_scache  - Pointer to secondary storage buffer pointer.
   7046  * Returns:
   7047  *     BCM_E_XXX
   7048  */
   7049 STATIC int
   7050 _bcm_tr3_oam_wb_endpoints_recover(int unit, int stable_size, 
   7051                                   uint8 **oam_scache, uint16 recovered_ver )
   7052 {
   7053     int                     index;        /* Hardware index.                  */
   7054     uint32                  l3_ent_count; /* Max entries in L3_ENTRY_1 table. */
   7055     uint32                  l3_entry[SOC_MAX_MEM_WORDS];   /* L3 table entry. */
   7056     _bcm_oam_control_t      *oc;          /* Pointer to control structure.    */
   7057     int                     rv;           /* Operation return status.         */
   7058     soc_mem_t               mem;          /* L3 entry memory                  */
   7059 
   7060     /*
   7061      * Get OAM control structure.
   7062      *     Note: Lock taken by calling routine.
   7063      */
   7064     BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc));
   7065 
   7066     if (SOC_IS_HURRICANE2(unit) || SOC_IS_GREYHOUND(unit) ||
   7067         SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) {
   7068         mem = L3_ENTRY_IPV4_UNICASTm;
   7069         /* Get number of L3 table entries. */
   7070         l3_ent_count = soc_mem_index_count(unit, L3_ENTRY_IPV4_UNICASTm);
   7071     } else {
   7072         mem = L3_ENTRY_1m;
   7073         /* Get number of L3 table entries. */
   7074         l3_ent_count = soc_mem_index_count(unit, L3_ENTRY_1m);
   7075     }
   7076 
   7077     sal_memset(&l3_entry, 0, sizeof(l3_entry));
   7078 
   7079     /* Now get valid OAM endpoint entries. */
   7080     for (index = 0; index < l3_ent_count; index++) {
   7081 
   7082         if (SOC_IS_HURRICANE2(unit) || SOC_IS_GREYHOUND(unit) ||
   7083             SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) {
   7084             rv = READ_L3_ENTRY_IPV4_UNICASTm(unit, MEM_BLOCK_ANY, 
   7085                                              index, &l3_entry);
   7086         } else {
   7087             rv = READ_L3_ENTRY_1m(unit, MEM_BLOCK_ANY, index, &l3_entry);
   7088         }
   7089         if (BCM_FAILURE(rv)) {
   7090             LOG_ERROR(BSL_LS_BCM_OAM,
   7091                       (BSL_META_U(unit,
   7092                                   "OAM Error: L3_ENTRY (index=%d) read"
   7093                                    " failed  - %s.\n"), index, bcm_errmsg(rv)));
   7094                 return (rv);
   7095         }
   7096 
   7097 #ifdef BCM_HURRICANE2_SUPPORT
   7098         if (SOC_IS_HURRICANE2(unit) || SOC_IS_GREYHOUND(unit) ||
   7099             SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) {
   7100             if (soc_mem_field32_get(unit, mem, &l3_entry, VALIDf)) {
   7101                 switch (soc_mem_field32_get(unit, mem, &l3_entry, KEY_TYPEf)) {
   7102 
   7103                     case SOC_MEM_KEY_L3_ENTRY_RMEP:
   7104                         rv = _bcm_tr3_oam_rmep_recover(unit, index, l3_entry, 
   7105                                                     oam_scache, recovered_ver);
   7106                         if (BCM_FAILURE(rv)) {
   7107                             LOG_ERROR(BSL_LS_BCM_OAM,
   7108                                       (BSL_META_U(unit,
   7109                                                   "OAM Error: Remote endpoint"
   7110                                                    " (index=%d) reconstruct failed  - %s.\n"),
   7111                                        index, bcm_errmsg(rv)));
   7112                             return (rv);
   7113                         }
   7114                         break;
   7115 
   7116                     case SOC_MEM_KEY_L3_ENTRY_LMEP:
   7117                         rv = _bcm_tr3_oam_lmep_rx_config_recover(unit, index,
   7118                                         l3_entry, oam_scache, recovered_ver);
   7119                         if (BCM_FAILURE(rv)) {
   7120                             LOG_ERROR(BSL_LS_BCM_OAM,
   7121                                       (BSL_META_U(unit,
   7122                                                   "OAM Error: Local endpoint"
   7123                                                    " (index=%d) reconstruct failed  - %s.\n"),
   7124                                        index, bcm_errmsg(rv)));
   7125                             return (rv);
   7126                         }
   7127                         break;
   7128 
   7129                     default:
   7130                         /* Not an OAM entry. */
   7131                         continue;
   7132                 }
   7133             }
   7134         }  
   7135 #endif /* BCM_HURRICANE2_SUPPORT */
   7136 #ifdef BCM_TRIUMPH3_SUPPORT
   7137         if (soc_mem_field32_get(unit, mem, &l3_entry, VALIDf)) {
   7138             switch (soc_mem_field32_get(unit, mem, &l3_entry, KEY_TYPEf)) {
   7139 
   7140                 case SOC_MEM_KEY_L3_ENTRY_1_RMEP_RMEP:
   7141                     rv = _bcm_tr3_oam_rmep_recover(unit, index, l3_entry, 
   7142                                                     oam_scache, recovered_ver);
   7143                     if (BCM_FAILURE(rv)) {
   7144                         LOG_ERROR(BSL_LS_BCM_OAM,
   7145                                   (BSL_META_U(unit,
   7146                                               "OAM Error: Remote endpoint"
   7147                                                " (index=%d) reconstruct failed  - %s.\n"),
   7148                                    index, bcm_errmsg(rv)));
   7149                         return (rv);
   7150                     }
   7151                     break;
   7152 
   7153                 case SOC_MEM_KEY_L3_ENTRY_1_LMEP_LMEP:
   7154                     rv = _bcm_tr3_oam_lmep_rx_config_recover(unit, index,
   7155                                         l3_entry, oam_scache, recovered_ver);
   7156                     if (BCM_FAILURE(rv)) {
   7157                         LOG_ERROR(BSL_LS_BCM_OAM,
   7158                                   (BSL_META_U(unit,
   7159                                               "OAM Error: Local endpoint"
   7160                                                " (index=%d) reconstruct failed  - %s.\n"),
   7161                                    index, bcm_errmsg(rv)));
   7162                         return (rv);
   7163                     }
   7164                     break;
   7165 
   7166                 default:
   7167                     /* Not an OAM entry. */
   7168                     continue;
   7169             }
   7170         }
   7171 #endif /* BCM_TRIUMPH3_SUPPORT */
   7172     }
   7173     rv = _bcm_tr3_oam_lmep_tx_config_recover(unit, oam_scache, recovered_ver);
   7174     if (BCM_FAILURE(rv)) {
   7175         LOG_ERROR(BSL_LS_BCM_OAM,
   7176                   (BSL_META_U(unit,
   7177                               "OAM Error: Endpoint Tx config recovery"
   7178                                " failed  - %s.\n"), bcm_errmsg(rv)));
   7179         return (rv);
   7180     }
   7181     return (BCM_E_NONE);
   7182 }
   7183 
   7184 /*
   7185  * Function: bcm_tr3_oam_scache_alloc
   7186  *
   7187  * Purpose:
   7188  *     Allocate memory for OAM module in scache
   7189  * Parameters:
   7190  *     unit - (IN) Unit number
   7191  * Returns:
   7192  *     BCM_E_XXX
   7193  */
   7194 STATIC int
   7195 bcm_tr3_oam_scache_alloc(int unit) {
   7196     _bcm_oam_control_t *oc;
   7197     soc_scache_handle_t scache_handle;
   7198     uint8 *oam_scache;
   7199     int alloc_sz = 0;
   7200 
   7201     BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc));
   7202 
   7203     alloc_sz = BCM_OAM_GROUP_NAME_LENGTH * (oc->group_count);
   7204 
   7205     /* Number of oam groups */
   7206     alloc_sz += sizeof(int);
   7207 
   7208     /* VFP group, IFP VP group, IFP GLP group */
   7209     alloc_sz += 3 * sizeof(bcm_field_group_t);
   7210 
   7211     /* Allocate memory to store logical endpoint Ids */
   7212     alloc_sz += (sizeof (bcm_oam_endpoint_t) * (oc->rmep_count + 
   7213                                             oc->lmep_count + oc->ma_idx_count));
   7214 
   7215     /* To store MEP TX, RX and LAG LM/DM FP entry numbers */
   7216     alloc_sz += ((sizeof (bcm_field_entry_t) * 3) * 
   7217                  (oc->ma_idx_count));
   7218 
   7219     /* Store the BHH Hw config */
   7220     alloc_sz += _bcm_tr3_oam_bhh_hw_config_scache_size_get(unit);
   7221 
   7222     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_OAM, 0);
   7223     BCM_IF_ERROR_RETURN(_bcm_esw_scache_ptr_get(unit, scache_handle, 1,
   7224                         alloc_sz, &oam_scache, BCM_WB_DEFAULT_VERSION, NULL));
   7225     return BCM_E_NONE;
   7226 }
   7227 
   7228 /*
   7229  * Function:
   7230  *     _bcm_tr3_oam_wb_endpoints_fp_entries_recover
   7231  * Purpose:
   7232  *     Recover OAM Rx MEP FP entry numbers.
   7233  * Parameters:
   7234  *     unit        - Device unit number.
   7235  *     stable_size - OAM module Level2 memory size.
   7236  *     oam_scache  - Pointer to secondary storage buffer pointer.
   7237  * Returns:
   7238  *     BCM_E_XXX
   7239  */
   7240 STATIC int
   7241 _bcm_tr3_oam_wb_endpoints_fp_entries_recover(int unit, int stable_size,
   7242                                   uint8 **oam_scache, uint16 recovered_ver )
   7243 
   7244 {
   7245     _bcm_oam_control_t  *oc;
   7246     int                 grp_idx, rv;
   7247     _bcm_oam_ep_list_t  *ep_list_p = NULL;
   7248     _bcm_oam_hash_data_t ep_data;
   7249     _bcm_oam_hash_data_t *hash_data;
   7250     _bcm_oam_group_data_t *group_p;   /* Pointer to group list.         */
   7251     uint32 param0 = 0, param1 = 0;
   7252 
   7253     /* Get handle to control structure. */
   7254     BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc));
   7255     /* Initialize to group array pointer. */
   7256     group_p = oc->group_info;
   7257 
   7258     for (grp_idx = 0; grp_idx < oc->group_count; ++grp_idx)
   7259     {
   7260         if (group_p[grp_idx].in_use == 1) {
   7261             ep_list_p = *(group_p[grp_idx].ep_list);
   7262             while (ep_list_p != NULL) {
   7263                 ep_data = *ep_list_p->ep_data_p;
   7264                 if ((ep_data.type == bcmOAMEndpointTypeEthernet) &&
   7265                         (!(ep_data.is_remote))) {
   7266                     if ((ep_data.local_rx_enabled)) {
   7267                         hash_data = &oc->oam_hash_data[ep_data.ep_id];   
   7268                         sal_memcpy(&(hash_data->fp_entry_rx), *oam_scache +
   7269                                 (sizeof(bcm_oam_endpoint_t) *
   7270                                  (ep_data.local_rx_index)),
   7271                                 sizeof (bcm_field_entry_t));
   7272 
   7273                         sal_memcpy(&(hash_data->fp_entry_tx), *oam_scache +
   7274                                 (sizeof(bcm_oam_endpoint_t) *
   7275                                  (oc->ma_idx_count)) +
   7276                                 (sizeof(bcm_oam_endpoint_t) *
   7277                                  (ep_data.local_rx_index)),
   7278                                 sizeof (bcm_field_entry_t));
   7279                         rv = bcm_esw_field_action_get(unit,
   7280                                 hash_data->fp_entry_rx,
   7281                                 bcmFieldActionOamLmEnable, &param0, &param1);
   7282                         if ((BCM_SUCCESS(rv)) && (param0 == 1)) {
   7283 
   7284                             hash_data->flags |= BCM_OAM_ENDPOINT_LOSS_MEASUREMENT;
   7285                             if(ep_data.ep_id == 1){
   7286                                 hash_data->lm_counter_index = 0;
   7287                             }
   7288                             rv = bcm_esw_field_action_get(unit,
   7289                                     hash_data->fp_entry_rx,
   7290                                     bcmFieldActionOamLmBasePtr, 
   7291                                     &param0, 
   7292                                     &param1);
   7293                             if ((BCM_SUCCESS(rv)) && 
   7294                                 (hash_data->lm_counter_index == -1)) {
   7295                                 hash_data->lm_counter_index = param0;
   7296                             }else{
   7297                                 /*FP entry warm boot has bug in recevery of action -
   7298                                 when action is set to Zero*/ 
   7299                                 hash_data->lm_counter_index = 0;
   7300                             }
   7301                             /* Reserve the LM counter index recovered */
   7302                             rv = shr_idxres_list_reserve(oc->lm_counter_pool,
   7303                                  (shr_idxres_element_t)hash_data->lm_counter_index,
   7304                                  (shr_idxres_element_t)hash_data->lm_counter_index);
   7305                             if (BCM_FAILURE(rv)) {
   7306                                 rv = (rv == BCM_E_RESOURCE) ? (BCM_E_FULL) : rv;
   7307                                 LOG_ERROR(BSL_LS_BCM_OAM,
   7308                                         (BSL_META_U(unit,
   7309                                                     "OAM Error: lm counter idx "
   7310                                          "reserve failed  - %s.\n"),
   7311                                          bcm_errmsg(rv)));
   7312                                 continue;
   7313                             } 
   7314                         }
   7315 
   7316                         rv = bcm_esw_field_action_get(unit,
   7317                                 hash_data->fp_entry_rx,
   7318                                 bcmFieldActionOamDmEnable, &param0, &param1);
   7319                         if ((BCM_SUCCESS(rv)) && (param0 == 1)) {
   7320                             hash_data->flags |=BCM_OAM_ENDPOINT_DELAY_MEASUREMENT;
   7321                         }
   7322                         rv = bcm_esw_field_action_get(unit,
   7323                                 hash_data->fp_entry_rx,
   7324                                 bcmFieldActionOamServicePriMappingPtr, 
   7325                                 &param0, 
   7326                                 &param1);
   7327                         if ((BCM_SUCCESS(rv)) && (hash_data->pri_map_index == -1)) {
   7328                             hash_data->pri_map_index = param0;
   7329                             rv = soc_profile_mem_reference(unit, &oc->ing_service_pri_map,
   7330                                     (hash_data->pri_map_index * BCM_OAM_INTPRI_MAX), 
   7331                                      BCM_OAM_INTPRI_MAX);
   7332                             if (BCM_FAILURE(rv)) {
   7333                                 LOG_ERROR(BSL_LS_BCM_OAM,
   7334                                         (BSL_META_U(unit,
   7335                                                     "OAM Error: lm counter profile ref count "
   7336                                          "increment failed(EP=%d)  - %s.\n"),
   7337                                          hash_data->ep_id, bcm_errmsg(rv)));
   7338                                 continue;
   7339                             }
   7340                         }
   7341                         if (SOC_GPORT_IS_TRUNK(hash_data->gport) && 
   7342                             ((hash_data->flags & BCM_OAM_ENDPOINT_DELAY_MEASUREMENT) ||
   7343                              (hash_data->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT))) {
   7344                             sal_memcpy(&(hash_data->fp_entry_trunk[0]), *oam_scache +
   7345                                     (sizeof(bcm_oam_endpoint_t) *
   7346                                      (oc->ma_idx_count) * 2) +
   7347                                     (sizeof(bcm_oam_endpoint_t) *
   7348                                      (ep_data.local_rx_index)),
   7349                                     sizeof (bcm_field_entry_t));
   7350 
   7351                         }
   7352                         
   7353                     }
   7354                 }
   7355                 ep_list_p = ep_list_p->next;
   7356             }
   7357         }
   7358     }
   7359 
   7360     return (BCM_E_NONE);
   7361 }
   7362 
   7363 STATIC int
   7364 _bcm_tr3_oam_bhh_hw_config_scache_size_get (int unit)
   7365 {
   7366     _bcm_oam_control_t   *oc;
   7367     int                  scache_size = 0;
   7368 
   7369     /* Lock already taken by the calling routine. */
   7370     BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc));
   7371 
   7372 #if defined (INCLUDE_BHH)
   7373     if(soc_feature(unit, soc_feature_bhh)) {
   7374         if(oc->ukernel_not_ready == 0) {
   7375             /* Store LM/DM enable */
   7376             scache_size += sizeof(oc->bhh_lm_dm_enable);
   7377 
   7378             if (oc->bhh_lm_dm_enable) {
   7379                 /* Store UDF mode */
   7380                 scache_size += sizeof(oc->bhh_udf_mode);
   7381 
   7382                 if (oc->bhh_udf_mode) {
   7383                     /* Store label, ach & opcode UDF id */
   7384                     scache_size += sizeof(oc->bhh_label_udf_id);
   7385                     scache_size += sizeof(oc->bhh_ach_udf_id);
   7386                     scache_size += sizeof(oc->bhh_opcode_udf_id);
   7387 
   7388                     /* Store pkt_fmt_id */
   7389                     scache_size += sizeof(oc->bhh_udf_pkt_fmt_id);
   7390 
   7391                 } else {
   7392                     /* Store label, ach & opcode qual id */
   7393                     scache_size += sizeof(oc->bhh_label_qual_id);
   7394                     scache_size += sizeof(oc->bhh_ach_qual_id);
   7395                     scache_size += sizeof(oc->bhh_opcode_qual_id);
   7396                 }
   7397             }
   7398         }
   7399     }
   7400 #endif
   7401     return scache_size;
   7402 }
   7403 
   7404 #if defined(INCLUDE_BHH)
   7405 /*
   7406  * Function:
   7407  *      _bcm_tr3_oam_bhh_fp_recover
   7408  * Purpose:
   7409  *      Recover the UDF for BHH LM/DM packet processing post warmboot.
   7410  * Parameters:
   7411  *      unit - (IN) Unit number.
   7412  * Returns:
   7413  *      BCM_E_XXX
   7414  * Notes:
   7415  */
   7416 STATIC int
   7417 _bcm_tr3_oam_bhh_fp_recover(int unit, uint8 *oam_scache)
   7418 {
   7419     int                   rv = BCM_E_NONE;
   7420     _bcm_oam_control_t   *oc;
   7421 
   7422     BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc));
   7423     _BCM_OAM_LOCK(oc);
   7424 
   7425     if(oc->ukernel_not_ready) {
   7426         _BCM_OAM_UNLOCK(oc);
   7427         return BCM_E_NONE;
   7428     }
   7429 
   7430     sal_memcpy(&(oc->bhh_lm_dm_enable), oam_scache,
   7431                                           sizeof(oc->bhh_lm_dm_enable));
   7432     oam_scache += sizeof(oc->bhh_lm_dm_enable);
   7433 
   7434     if(!oc->bhh_lm_dm_enable) {
   7435         _BCM_OAM_UNLOCK(oc);
   7436         return BCM_E_NONE;
   7437     }
   7438 
   7439     BCM_FIELD_QSET_INIT(oc->bhh_lmdm_qset);
   7440     BCM_FIELD_QSET_ADD(oc->bhh_lmdm_qset, bcmFieldQualifySrcPort);
   7441     BCM_FIELD_QSET_ADD(oc->bhh_lmdm_qset, bcmFieldQualifyDstPort);
   7442     BCM_FIELD_QSET_ADD(oc->bhh_lmdm_qset, bcmFieldQualifyOuterVlanId);
   7443     BCM_FIELD_QSET_ADD(oc->bhh_lmdm_qset, bcmFieldQualifyDstL3Egress);
   7444 
   7445     sal_memcpy(&(oc->bhh_udf_mode), oam_scache,
   7446                                      sizeof(oc->bhh_udf_mode));
   7447     oam_scache += sizeof(oc->bhh_udf_mode);
   7448 
   7449     if (oc->bhh_udf_mode) { /* Configure UDF using bcm_udf_xxx() APIs */
   7450 
   7451         sal_memcpy(&(oc->bhh_label_udf_id), oam_scache,
   7452                                             sizeof(oc->bhh_label_udf_id));
   7453         oam_scache += sizeof(oc->bhh_label_udf_id);
   7454 
   7455         sal_memcpy(&(oc->bhh_ach_udf_id), oam_scache,
   7456                                            sizeof(oc->bhh_ach_udf_id));
   7457         oam_scache += sizeof(oc->bhh_ach_udf_id);
   7458 
   7459         sal_memcpy(&(oc->bhh_opcode_udf_id), oam_scache,
   7460                                              sizeof(oc->bhh_opcode_udf_id));
   7461         oam_scache += sizeof(oc->bhh_opcode_udf_id);
   7462 
   7463         sal_memcpy(&(oc->bhh_udf_pkt_fmt_id), oam_scache,
   7464                                        sizeof(oc->bhh_udf_pkt_fmt_id));
   7465         oam_scache += sizeof(oc->bhh_udf_pkt_fmt_id);
   7466 
   7467         rv = bcm_esw_field_qset_id_multi_set(unit,
   7468                                              bcmFieldQualifyUdf,
   7469                                              1,
   7470                                              &(oc->bhh_label_udf_id),
   7471                                              &(oc->bhh_lmdm_qset));
   7472         if (BCM_FAILURE(rv)) {
   7473             _BCM_OAM_UNLOCK(oc);
   7474             return rv;
   7475         }
   7476 
   7477         rv = bcm_esw_field_qset_id_multi_set(unit,
   7478                                              bcmFieldQualifyUdf,
   7479                                              1,
   7480                                              &(oc->bhh_ach_udf_id),
   7481                                              &(oc->bhh_lmdm_qset));
   7482         if (BCM_FAILURE(rv)) {
   7483             _BCM_OAM_UNLOCK(oc);
   7484             return rv;
   7485         }
   7486 
   7487 
   7488         rv = bcm_esw_field_qset_id_multi_set(unit,
   7489                                              bcmFieldQualifyUdf,
   7490                                              1,
   7491                                              &(oc->bhh_opcode_udf_id),
   7492                                              &(oc->bhh_lmdm_qset));
   7493         if (BCM_FAILURE(rv)) {
   7494             _BCM_OAM_UNLOCK(oc);
   7495             return rv;
   7496         }
   7497 
   7498 
   7499 
   7500     } else { /* Configure UDF using bcm_field_xxx() APIs */
   7501 
   7502         bcm_field_data_packet_format_t_init(&oc->bhh_field_pkt_fmt);
   7503         oc->bhh_field_pkt_fmt.relative_offset = 0;
   7504         oc->bhh_field_pkt_fmt.l2            = BCM_FIELD_DATA_FORMAT_L2_ANY;
   7505         oc->bhh_field_pkt_fmt.vlan_tag      = BCM_FIELD_DATA_FORMAT_VLAN_TAG_ANY;
   7506         oc->bhh_field_pkt_fmt.tunnel        = BCM_FIELD_DATA_FORMAT_TUNNEL_MPLS;
   7507         oc->bhh_field_pkt_fmt.mpls          = BCM_FIELD_DATA_FORMAT_MPLS_ANY;
   7508 
   7509         sal_memcpy(&(oc->bhh_label_qual_id), oam_scache,
   7510                                           sizeof(oc->bhh_label_qual_id));
   7511         oam_scache += sizeof(oc->bhh_label_qual_id);
   7512 
   7513         sal_memcpy(&(oc->bhh_ach_qual_id), oam_scache,
   7514                                              sizeof(oc->bhh_ach_qual_id));
   7515         oam_scache += sizeof(oc->bhh_ach_qual_id);
   7516 
   7517         sal_memcpy(&(oc->bhh_opcode_qual_id), oam_scache,
   7518                                               sizeof(oc->bhh_opcode_qual_id));
   7519         oam_scache += sizeof(oc->bhh_opcode_qual_id);
   7520 
   7521         rv = bcm_esw_field_qset_data_qualifier_add(unit,
   7522                                                    &oc->bhh_lmdm_qset,
   7523                                                    oc->bhh_label_qual_id);
   7524         if (BCM_FAILURE(rv)) {
   7525             _BCM_OAM_UNLOCK(oc);
   7526             return rv;
   7527         }
   7528 
   7529         rv = bcm_esw_field_qset_data_qualifier_add(unit,
   7530                                                    &oc->bhh_lmdm_qset,
   7531                                                    oc->bhh_ach_qual_id);
   7532         if (BCM_FAILURE(rv)) {
   7533             _BCM_OAM_UNLOCK(oc);
   7534             return rv;
   7535         }
   7536 
   7537         rv = bcm_esw_field_qset_data_qualifier_add(unit,
   7538                                                    &oc->bhh_lmdm_qset,
   7539                                                    oc->bhh_opcode_qual_id);
   7540         if (BCM_FAILURE(rv)) {
   7541             _BCM_OAM_UNLOCK(oc);
   7542             return rv;
   7543         }
   7544     }
   7545 
   7546     _BCM_OAM_UNLOCK(oc);
   7547     return (rv);
   7548 }
   7549 
   7550 /*
   7551  * Function:
   7552  *      _bcm_tr3_oam_bhh_fp_upgrade
   7553  * Purpose:
   7554  *      Handle warm upgrade from a release which does not
   7555  *      have bhh_udf_mode set
   7556  * Parameters:
   7557  *      unit - (IN) Unit number.
   7558  * Returns:
   7559  *      BCM_E_XXX
   7560  * Notes:
   7561  */
   7562 STATIC int
   7563 _bcm_tr3_oam_bhh_fp_upgrade(int unit)
   7564 {
   7565     int                   rv = BCM_E_NONE;
   7566     _bcm_oam_control_t   *oc;
   7567 
   7568     BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc));
   7569     _BCM_OAM_LOCK(oc);
   7570 
   7571     if(oc->ukernel_not_ready) {
   7572         _BCM_OAM_UNLOCK(oc);
   7573         return BCM_E_NONE;
   7574     }
   7575 
   7576     /* Upgrading with BHH BTE loaded, from a release which does not have
   7577      * bhh_udf_mode defined, enable LM/DM & set udf_mode to field.
   7578      */
   7579     oc->bhh_lm_dm_enable = 1;
   7580     oc->bhh_udf_mode = 0;
   7581     rv = _bcm_tr3_oam_bhh_fp_init(unit);
   7582 
   7583     _BCM_OAM_UNLOCK(oc);
   7584     return rv;
   7585 }
   7586 
   7587 /*
   7588  * Function:
   7589  *      _bcm_tr3_oam_bhh_cos_map_recover
   7590  * Purpose:
   7591  *      Recover the CoS map settings for BHH after warm boot
   7592  *
   7593  * Parameters:
   7594  *      unit - (IN) Unit number.
   7595  * Returns:
   7596  *      BCM_E_XXX
   7597  * Notes:
   7598  */
   7599 STATIC int
   7600 _bcm_tr3_oam_bhh_cos_map_recover(int unit)
   7601 {
   7602     int                    rv = BCM_E_NONE;
   7603     _bcm_oam_control_t     *oc;
   7604     int                    index;
   7605     int                    cosq_map_size;
   7606     bcm_rx_reasons_t       reasons, reasons_mask, reasons_cmp;
   7607     uint8                  int_prio, int_prio_mask;
   7608     uint32                 packet_type, packet_type_mask;
   7609     bcm_cos_queue_t        cosq;
   7610 
   7611     /* Get OAM Control Structure. */
   7612     BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc));
   7613 
   7614     _BCM_OAM_LOCK(oc);
   7615 
   7616     if(oc->ukernel_not_ready) {
   7617         _BCM_OAM_UNLOCK(oc);
   7618         return BCM_E_NONE;
   7619     }
   7620 
   7621     rv = bcm_esw_rx_cosq_mapping_size_get(unit, &cosq_map_size);
   7622     if(BCM_FAILURE(rv)) {
   7623         LOG_ERROR(BSL_LS_BCM_OAM,
   7624                   (BSL_META_U(unit,
   7625                               "BHH Error:hw init. cosq maps size %s.\n"),
   7626                    bcm_errmsg(rv)));
   7627         _BCM_OAM_UNLOCK(oc);
   7628         return (rv);
   7629     }
   7630 
   7631     /* Get CPU COS Queue mapping */
   7632     BCM_RX_REASON_CLEAR_ALL(reasons_cmp);
   7633     BCM_RX_REASON_SET(reasons_cmp, bcmRxReasonMplsUnknownAch);
   7634     oc->cpu_cosq_ach_error_index = -1;
   7635 
   7636     for (index = 0; index < cosq_map_size; index++) {
   7637         rv = bcm_esw_rx_cosq_mapping_get(unit, index,
   7638                                          &reasons, &reasons_mask,
   7639                                          &int_prio, &int_prio_mask,
   7640                                          &packet_type, &packet_type_mask,
   7641                                          &cosq);
   7642         if (rv == BCM_E_NONE) {
   7643 
   7644             if (BCM_RX_REASON_EQ(reasons, reasons_cmp) &&
   7645                 BCM_RX_REASON_EQ(reasons_mask, reasons_cmp)) {
   7646                 oc->cpu_cosq_ach_error_index = index;
   7647                 oc->cpu_cosq = cosq;
   7648                 break;
   7649             }
   7650         }
   7651     }
   7652 
   7653     if (index >= cosq_map_size) {
   7654         LOG_VERBOSE(BSL_LS_BCM_OAM,
   7655                   (BSL_META_U(unit,
   7656                             "BHH Error: Could not recover cos map entry \n")));
   7657     }
   7658 
   7659     _BCM_OAM_UNLOCK(oc);
   7660     return rv;
   7661 }
   7662 #endif /* INCLUDE_BHH*/
   7663 
   7664 /*
   7665  * Function:
   7666  *     _bcm_tr3_oam_reinit
   7667  * Purpose:
   7668  *     Reconstruct OAM module software state.
   7669  * Parameters:
   7670  *     unit - (IN) BCM device number
   7671  * Retruns:
   7672  *     BCM_E_XXX
   7673  */
   7674 STATIC int
   7675 _bcm_tr3_oam_reinit(int unit)
   7676 {
   7677     uint32              group_count = 0;   /* Stored OAM group count.           */
   7678     int                 stable_size;   /* Secondary storage size.           */
   7679     uint8               *oam_scache;   /* Pointer to scache memory.         */
   7680     soc_scache_handle_t scache_handle; /* Scache memory handler.            */
   7681     _bcm_oam_control_t  *oc;           /* Pointer to OAM control structure. */
   7682     int                 rv;            /* Operation return status.          */
   7683     uint16              recovered_ver = 0;
   7684     int                 realloc_size = 0;
   7685 
   7686     LOG_DEBUG(BSL_LS_BCM_OAM,
   7687               (BSL_META_U(unit,
   7688                           "OAM Info: OAM warm boot recovery.....\n")));
   7689 
   7690     SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size));
   7691 
   7692     /* Get OAM control structure. */
   7693     BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc));
   7694 
   7695     _BCM_OAM_LOCK(oc);
   7696 
   7697     if (!SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit) && (stable_size > 0)) {
   7698 
   7699         SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_OAM, 0);
   7700 
   7701         rv = _bcm_esw_scache_ptr_get(unit, scache_handle, 0, 0,
   7702                                      &oam_scache, BCM_WB_DEFAULT_VERSION,
   7703                                      &recovered_ver);
   7704         if (BCM_E_NOT_FOUND == rv) {
   7705             /* Upgrading from SDK release that does not have warmboot state */
   7706             bcm_tr3_oam_scache_alloc(unit);
   7707             _BCM_OAM_UNLOCK(oc);
   7708             return BCM_E_NONE;
   7709         } else if (BCM_FAILURE(rv)) {
   7710             goto cleanup;
   7711         }
   7712 
   7713         /* Recover the FP groups */
   7714         sal_memcpy(&oc->vfp_group, oam_scache, sizeof(bcm_field_group_t));
   7715         oam_scache += sizeof(bcm_field_group_t);
   7716 
   7717         sal_memcpy(&oc->fp_vp_group, oam_scache, sizeof(bcm_field_group_t));
   7718         oam_scache += sizeof(bcm_field_group_t);
   7719 
   7720         sal_memcpy(&oc->fp_glp_group, oam_scache, sizeof(bcm_field_group_t));
   7721         oam_scache += sizeof(bcm_field_group_t);
   7722 
   7723         /* Recover the OAM groups */
   7724         sal_memcpy(&group_count, oam_scache, sizeof(int));
   7725         oam_scache += sizeof(int);
   7726     } else {
   7727         rv = BCM_E_NONE;
   7728         goto cleanup;
   7729     }
   7730 
   7731     if (recovered_ver >= BCM_WB_VERSION_1_1) {
   7732         rv = _bcm_tr3_oam_wb_group_recover(unit, stable_size, &oam_scache, 1);
   7733         oam_scache += BCM_OAM_GROUP_NAME_LENGTH * (oc->group_count);
   7734     } else {
   7735         rv = _bcm_tr3_oam_wb_group_recover(unit, stable_size, &oam_scache, 0);
   7736     }
   7737     
   7738     if (BCM_FAILURE(rv)) {
   7739         LOG_ERROR(BSL_LS_BCM_OAM,
   7740                   (BSL_META_U(unit,
   7741                               "OAM Error: Group recovery failed  - %s.\n"),
   7742                    bcm_errmsg(rv)));
   7743         goto cleanup;
   7744     }
   7745 
   7746     rv = _bcm_tr3_oam_wb_endpoints_recover(unit, stable_size, &oam_scache, 
   7747                                                                 recovered_ver);
   7748     if (BCM_FAILURE(rv)) {
   7749         LOG_ERROR(BSL_LS_BCM_OAM,
   7750                   (BSL_META_U(unit,
   7751                               "OAM Error: Endpoint recovery failed  - %s.\n"),
   7752                    bcm_errmsg(rv)));
   7753         goto cleanup;
   7754     }
   7755 
   7756     if (recovered_ver >= BCM_WB_VERSION_1_2) {
   7757         oam_scache += (sizeof (bcm_oam_endpoint_t) * 
   7758                        (oc->rmep_count + oc->lmep_count + oc->ma_idx_count));
   7759     }
   7760 
   7761     if (recovered_ver >= BCM_WB_VERSION_1_3) {
   7762         rv = _bcm_tr3_oam_wb_endpoints_fp_entries_recover(unit, stable_size, 
   7763                                                           &oam_scache,
   7764                                                           recovered_ver);
   7765         if (BCM_FAILURE(rv)) {
   7766             LOG_ERROR(BSL_LS_BCM_OAM,
   7767                     (BSL_META_U(unit,
   7768                                 "OAM Error: Endpoint FP entries recovery " 
   7769                                 "failed  - %s.\n"),
   7770                      bcm_errmsg(rv)));
   7771             goto cleanup;
   7772         }
   7773         oam_scache += ((sizeof (bcm_field_entry_t) * 3) * 
   7774                        (oc->ma_idx_count));
   7775     }
   7776 
   7777     if (recovered_ver >= BCM_WB_VERSION_1_4) {
   7778 #if defined(INCLUDE_BHH)
   7779         if(soc_feature(unit, soc_feature_bhh)) {
   7780             rv = _bcm_tr3_oam_bhh_fp_recover(unit, oam_scache);
   7781             if (BCM_FAILURE(rv)) {
   7782                 LOG_ERROR(BSL_LS_BCM_OAM,
   7783                           (BSL_META_U(unit,
   7784                                     "OAM Error: BHH fp recovery failed - %s \n"),
   7785                            bcm_errmsg(rv)));
   7786                 goto cleanup;
   7787             }
   7788         }
   7789 #endif
   7790     } else {
   7791 #if defined(INCLUDE_BHH)
   7792         if(soc_feature(unit, soc_feature_bhh)) {
   7793             rv = _bcm_tr3_oam_bhh_fp_upgrade(unit);
   7794             if (BCM_FAILURE(rv)) {
   7795                 LOG_ERROR(BSL_LS_BCM_OAM,
   7796                           (BSL_META_U(unit,
   7797                                     "OAM Error: BHH FP upgrade failed - %s \n"),
   7798                            bcm_errmsg(rv)));
   7799                 goto cleanup;
   7800             }
   7801 
   7802         }
   7803 #endif
   7804     }
   7805 
   7806     if (!SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit) && (stable_size > 0)) {
   7807 
   7808     /* In BCM_WB_VERSION_1_1 onwards we allocate memory for max OAM groups and
   7809        not just the groups created, as such while upgrading from 
   7810        BCM_WB_VERSION_1_0 to BCM_WB_VERSION_1_1 or greater we must add the 
   7811        differential.
   7812     */
   7813         if (recovered_ver < BCM_WB_VERSION_1_1) {
   7814             realloc_size += (BCM_OAM_GROUP_NAME_LENGTH * 
   7815                              (oc->group_count - group_count));
   7816        }
   7817 
   7818     /* In BCM_WB_VERSION_1_2 onwards we allocate memory for storing EP indexes
   7819         also, as such while upgrading from any version lower than 
   7820         BCM_WB_VERSION_1_2 we must add the differential.
   7821     */
   7822         if (recovered_ver < BCM_WB_VERSION_1_2) {
   7823             realloc_size += (sizeof (bcm_oam_endpoint_t) * 
   7824                         (oc->rmep_count + oc->lmep_count + oc->ma_idx_count)); 
   7825         }   
   7826 
   7827     /* In BCM_WB_VERSION_1_3 onwards we allocate memory for storing EP FP
   7828        indexes also, as such while upgrading from any version lower than 
   7829         BCM_WB_VERSION_1_3 we must add the differential.
   7830     */
   7831         if (recovered_ver < BCM_WB_VERSION_1_3) {
   7832             realloc_size += ((sizeof (bcm_field_entry_t) * 2) * 
   7833                              (oc->ma_idx_count)); 
   7834         }
   7835 
   7836         /* In BCM_WB_VERSION_1_4 onwards we allocate memory for storing the
   7837          * BHH H/w config, so must add differential while upgrading from
   7838          * lower version
   7839          */
   7840         if (recovered_ver < BCM_WB_VERSION_1_4) {
   7841             /* Store the BHH Hw config */
   7842             realloc_size += _bcm_tr3_oam_bhh_hw_config_scache_size_get(unit);
   7843         }
   7844 
   7845         SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_OAM, 0); 
   7846         rv = soc_scache_realloc(unit, scache_handle, realloc_size); 
   7847         if (SOC_FAILURE(rv)) {
   7848             LOG_ERROR(BSL_LS_BCM_OAM,
   7849             (BSL_META_U(unit,"OAM Error: scache alloc failed  - %s.\n"),
   7850                     bcm_errmsg(rv)));
   7851             goto cleanup;
   7852         }
   7853     }
   7854     
   7855 cleanup:
   7856     _BCM_OAM_UNLOCK(oc);
   7857     return (rv);
   7858 }
   7859 #endif /* BCM_WARM_BOOT_SUPPORT */
   7860 
   7861 /* * * * * * * * * * * * * * * * * * * *
   7862  *            OAM BCM APIs             *
   7863  */
   7864 
   7865 /*
   7866  * Function: bcm_tr3_oam_init
   7867  *
   7868  * Purpose:
   7869  *     Initialize OAM module.
   7870  * Parameters:
   7871  *     unit - (IN) BCM device number
   7872  * Returns:
   7873  *     BCM_E_UNIT    - Invalid BCM unit number.
   7874  *     BCM_E_UNAVAIL - OAM not support on this device.
   7875  *     BCM_E_MEMORY  - Allocation failure
   7876  *     CM_E_XXX     - Error code from bcm_XX_oam_init()
   7877  *     BCM_E_NONE    - Success
   7878  */
   7879 int
   7880 bcm_tr3_oam_init(int unit)
   7881 {
   7882     _bcm_oam_control_t *oc = NULL;  /* OAM control structure.     */
   7883     int             rv;             /* Operation return value.    */
   7884     uint32          size;           /* Size of memory allocation. */
   7885     bcm_port_t      port;           /* Port number.               */
   7886     bcm_oam_endpoint_t   ep_index;  /* Endpoint index.               */
   7887 #if defined(BCM_TRIUMPH3_SUPPORT) && defined(INCLUDE_BHH)
   7888     int uc;
   7889     uint8 carrier_code[] = {0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF};
   7890     char *carrier_code_str;
   7891     uint32 node_id = 0;
   7892     bhh_sdk_msg_ctrl_init_t msg_init;
   7893     uint8 *buffer, *buffer_ptr;
   7894     uint16 buffer_len, reply_len;
   7895     int priority;
   7896     int ukernel_not_ready = 0;
   7897     uint8 bhh_consolidate_final_event = 0;
   7898     int status;
   7899 #endif
   7900 
   7901 
   7902     /* Ensure that the unit has OAM support. */
   7903     if (!soc_feature(unit, soc_feature_oam)) {
   7904         LOG_ERROR(BSL_LS_BCM_OAM,
   7905                   (BSL_META_U(unit,
   7906                               "OAM Error: OAM not supported \n")));
   7907         return (BCM_E_UNAVAIL);
   7908     }
   7909 
   7910     /* Detach first if the module has been previously initialized. */
   7911     if (NULL != _oam_control[unit]) {
   7912         _oam_control[unit]->init = FALSE;
   7913 
   7914         /* COVERITY : Intentional stack use. Marking the event as intentional */
   7915         /* coverity[stack_use_callee] */
   7916         /* coverity[stack_use_overflow] */
   7917         rv = bcm_tr3_oam_detach(unit);
   7918         if (BCM_FAILURE(rv)) {
   7919             LOG_ERROR(BSL_LS_BCM_OAM,
   7920                       (BSL_META_U(unit,
   7921                                   "OAM Error: Module deinit - %s.\n"),
   7922                        bcm_errmsg(rv)));
   7923             return (rv);
   7924         }
   7925     }
   7926 
   7927     /* Allocate OAM control memeory for this unit. */
   7928     _BCM_OAM_ALLOC(oc, _bcm_oam_control_t, sizeof (_bcm_oam_control_t),
   7929                    "OAM control");
   7930     if (NULL == oc) {
   7931         return (BCM_E_MEMORY);
   7932     }
   7933 
   7934     if (soc_feature(unit, soc_feature_bhh)) {
   7935 #ifdef INCLUDE_BHH
   7936         /*
   7937          * Initialize uController side
   7938          */
   7939 
   7940         /*
   7941          * Start BHH application in BTE (Broadcom Task Engine) uController,
   7942          * if not already running (warm boot).
   7943          * Determine which uController is running BHH  by choosing the first
   7944          * uC that returns successfully.
   7945          */
   7946         for (uc = 0; uc < SOC_INFO(unit).num_ucs; uc++) {
   7947             rv = soc_uc_status(unit, uc, &status);
   7948             if ((rv == SOC_E_NONE) && (status != 0)) {
   7949                 rv = soc_cmic_uc_appl_init(unit, uc, MOS_MSG_CLASS_BHH,
   7950                                            _BHH_UC_MSG_TIMEOUT_USECS,
   7951                                            BHH_SDK_VERSION,
   7952                                            BHH_UC_MIN_VERSION,
   7953                                            _bcm_oam_bhh_appl_callback, NULL);
   7954                 if (SOC_E_NONE == rv) {
   7955                     /* BHH started successfully */
   7956                     oc->uc_num = uc;
   7957                     break;
   7958                 }
   7959             }
   7960         }
   7961 
   7962         if (uc >= SOC_INFO(unit).num_ucs) {  /* Could not find or start BHH appl */
   7963             ukernel_not_ready = 1;
   7964             LOG_ERROR(BSL_LS_BCM_OAM,
   7965                       (BSL_META_U(unit,
   7966                                   "uKernel Not Ready, bhh not started\n")));
   7967         }
   7968 #endif
   7969     }
   7970 
   7971     /* Get number of endpoints and groups supported by this unit. */
   7972     rv = _bcm_oam_group_endpoint_count_init(unit, oc);
   7973     if (BCM_FAILURE(rv)) {
   7974         _bcm_tr3_oam_control_free(unit, oc);
   7975         return (rv);
   7976     }
   7977 
   7978     if (soc_feature(unit, soc_feature_bhh)) {
   7979 #if defined(BCM_TRIUMPH3_SUPPORT) && defined(INCLUDE_BHH)
   7980         oc->unit = unit;
   7981 
   7982         oc->ukernel_not_ready = ukernel_not_ready;
   7983         /* Get SOC properties for BHH */
   7984         oc->bhh_endpoint_count = soc_property_get(unit, 
   7985                                                   spn_BHH_NUM_SESSIONS, 128);
   7986         oc->bhh_max_encap_length =
   7987                              soc_property_get(unit,
   7988                                               spn_BHH_ENCAP_MAX_LENGTH,
   7989                                               _BCM_OAM_BHH_DEFAULT_ENCAP_LENGTH);
   7990 
   7991         if(oc->bhh_max_encap_length > _BCM_OAM_BHH_MAX_ENCAP_LENGTH) {
   7992             LOG_ERROR(BSL_LS_BCM_OAM,
   7993                       (BSL_META_U(unit,
   7994                                   "Invalid max encap_length=%u\n"),
   7995                                   oc->bhh_max_encap_length));
   7996             return BCM_E_CONFIG;
   7997         }
   7998 
   7999         carrier_code_str = soc_property_get_str(unit, spn_BHH_CARRIER_CODE);
   8000         if (carrier_code_str != NULL) {
   8001             /*
   8002              * Note that the carrier code is specified in colon separated
   8003              * MAC address format.
   8004              */
   8005             if (_shr_parse_macaddr(carrier_code_str, carrier_code) < 0) {
   8006                 _bcm_tr3_oam_control_free(unit, oc);
   8007                 return (BCM_E_INTERNAL);
   8008             }
   8009         }
   8010 
   8011         node_id = soc_property_get(unit, spn_BHH_NODE_ID, 0);
   8012         oc->bhh_lm_dm_enable = soc_property_get(unit, spn_BHH_LM_DM_ENABLE, 1);
   8013         oc->bhh_udf_mode = soc_property_get(unit, spn_BHH_UDF_MODE, 1);
   8014         bhh_consolidate_final_event = soc_property_get(unit, 
   8015                                            spn_BHH_CONSOLIDATED_FINAL_EVENT, 0);
   8016 
   8017         oc->ep_count += oc->bhh_endpoint_count;
   8018 
   8019         if(oc->ep_count >= _BCM_OAM_TRIUMPH3_ENDPOINT_MAX) {
   8020             LOG_ERROR(BSL_LS_BCM_OAM,
   8021                       (BSL_META_U(unit,
   8022                                   "OAM Error: OAM EP count %d not supported \n"), 
   8023                        oc->ep_count));
   8024             _bcm_tr3_oam_control_free(unit, oc);
   8025             return (BCM_E_PARAM);
   8026         }
   8027 #endif /* INCLUDE_BHH */
   8028     }
   8029 
   8030     /* Mem_1: Allocate hash data memory */
   8031     /* size = sizeof(_bcm_oam_hash_data_t) * oc->ep_count; */
   8032     if (SOC_IS_HURRICANE2(unit) || SOC_IS_GREYHOUND(unit) ||
   8033         SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) {
   8034         size = sizeof(_bcm_oam_hash_data_t) * _BCM_OAM_HURRICANE2_ENDPOINT_MAX;
   8035     } else {
   8036         size = sizeof(_bcm_oam_hash_data_t) * _BCM_OAM_TRIUMPH3_ENDPOINT_MAX;
   8037     }
   8038     _BCM_OAM_ALLOC(oc->oam_hash_data, _bcm_oam_hash_data_t, size, "Hash data");
   8039     if (NULL == oc->oam_hash_data) {
   8040         _bcm_tr3_oam_control_free(unit, oc);
   8041         return (BCM_E_MEMORY);
   8042     }
   8043 
   8044     /* Mem_2: Allocate group memory */
   8045     size = sizeof(_bcm_oam_group_data_t) * oc->group_count;
   8046 
   8047     _BCM_OAM_ALLOC(oc->group_info, _bcm_oam_group_data_t, size, "Group Info");
   8048 
   8049     if (NULL == oc->group_info) {
   8050         _bcm_tr3_oam_control_free(unit, oc);
   8051         return (BCM_E_MEMORY);
   8052     }
   8053 
   8054     /* Mem 3: Allocate RMEP H/w to logical index mapping memory */
   8055     size = sizeof(bcm_oam_endpoint_t) * oc->rmep_count;
   8056     _BCM_OAM_ALLOC(oc->remote_endpoints, bcm_oam_endpoint_t, size, "RMEP Mapping");
   8057     if (NULL == oc->remote_endpoints) {
   8058         _bcm_tr3_oam_control_free(unit, oc);
   8059         return (BCM_E_MEMORY);
   8060     }
   8061     /* Initialize the mapping to BCM_OAM_ENDPOINT_INVALID */ 
   8062     for (ep_index = 0; ep_index < oc->rmep_count; ++ep_index) {
   8063         oc->remote_endpoints[ep_index] = BCM_OAM_ENDPOINT_INVALID;
   8064     }
   8065     
   8066 
   8067     
   8068     /* Mem_3: Create application endpoint list. */
   8069     if (SOC_IS_HURRICANE2(unit) || SOC_IS_GREYHOUND(unit) ||
   8070         SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) {
   8071         oc->ep_count = _BCM_OAM_HURRICANE2_ENDPOINT_MAX;
   8072     } else {
   8073         oc->ep_count = _BCM_OAM_TRIUMPH3_ENDPOINT_MAX;
   8074     }
   8075 
   8076     rv = shr_idxres_list_create(&oc->mep_pool, 1, oc->ep_count - 1,
   8077                                 1, oc->ep_count -1, "endpoint pool");
   8078     if (BCM_FAILURE(rv)) {
   8079         _bcm_tr3_oam_control_free(unit, oc);
   8080         return (rv);
   8081     }
   8082 
   8083     /* Mem_3: Create local MEP endpoint list. */
   8084     rv = shr_idxres_list_create(&oc->lmep_pool, 1, oc->lmep_count - 1,
   8085                                 1, oc->lmep_count -1, "lmep pool");
   8086     if (BCM_FAILURE(rv)) {
   8087         _bcm_tr3_oam_control_free(unit, oc);
   8088         return (rv);
   8089     }
   8090 
   8091     /* Mem_3: Create Remote MEP endpoint list. */
   8092     rv = shr_idxres_list_create(&oc->rmep_pool, 1, oc->rmep_count - 1,
   8093                                 1, oc->rmep_count -1, "rmep pool");
   8094     if (BCM_FAILURE(rv)) {
   8095         _bcm_tr3_oam_control_free(unit, oc);
   8096         return (rv);
   8097     }
   8098 
   8099     /* Mem_3: Create MEP Rx state tracker table index endpoint list. */
   8100     rv = shr_idxres_list_create(&oc->ma_idx_pool, 8, oc->ma_idx_count - 1,
   8101                                 8, oc->ma_idx_count -1, "ma_idx pool");
   8102     if (BCM_FAILURE(rv)) {
   8103         _bcm_tr3_oam_control_free(unit, oc);
   8104         return (rv);
   8105 
   8106     }
   8107 
   8108     if(soc_feature(unit, soc_feature_bhh)) {
   8109 #if defined(BCM_TRIUMPH3_SUPPORT) && defined(INCLUDE_BHH)
   8110         /* Mem_3: Create BHH endpoint list. */
   8111         rv = shr_idxres_list_create(&oc->bhh_pool, 0, oc->bhh_endpoint_count - 1,
   8112                                     0, oc->bhh_endpoint_count - 1, "bhh pool");
   8113         if (BCM_FAILURE(rv)) {
   8114             _bcm_tr3_oam_control_free(unit, oc);
   8115             return (rv);
   8116         }
   8117 
   8118         /* Reserve ep pool from mep_pool for BHH, manange BHH mep using bhh_pool */
   8119         rv = shr_idxres_list_reserve(oc->mep_pool, _BCM_OAM_BHH_ENDPOINT_OFFSET, 
   8120                                      _BCM_OAM_BHH_ENDPOINT_OFFSET + oc->bhh_endpoint_count);
   8121                 
   8122         if (BCM_FAILURE(rv)) {
   8123             _bcm_tr3_oam_control_free(unit, oc);
   8124             return (rv);
   8125         }
   8126 #endif /* INCLUDE_BHH */
   8127     }
   8128 
   8129     /* Mem_4: Create group list. */
   8130     rv = shr_idxres_list_create(&oc->group_pool, 1, oc->group_count - 1,
   8131                                 1, oc->group_count - 1, "group pool");
   8132     if (BCM_FAILURE(rv)) {
   8133         _bcm_tr3_oam_control_free(unit, oc);
   8134         return (rv);
   8135     }
   8136 
   8137     
   8138     /* Mem_5: Create MA group and MEP hash table. */
   8139     if (SOC_IS_HURRICANE2(unit) || SOC_IS_GREYHOUND(unit) ||
   8140         SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) {
   8141         rv = shr_htb_create(&oc->ma_mep_htbl, oc->ep_count,
   8142                             sizeof(_bcm_oam_hash_key_t), "MA/MEP Hash");
   8143     } else {
   8144         rv = shr_htb_create(&oc->ma_mep_htbl, _BCM_OAM_TRIUMPH3_ENDPOINT_MAX,
   8145                             sizeof(_bcm_oam_hash_key_t), "MA/MEP Hash");
   8146     }
   8147     if (BCM_FAILURE(rv)) {
   8148         _bcm_tr3_oam_control_free(unit, oc);
   8149         return (rv);
   8150     }
   8151 
   8152     /* 
   8153      * Both TX and RX for one MEP 
   8154      */
   8155     oc->lm_counter_cnt = 
   8156         soc_mem_index_count(unit, OAM_LM_COUNTERSm) / 2;
   8157 
   8158     rv = shr_idxres_list_create(&oc->lm_counter_pool, 0, oc->lm_counter_cnt - 1,
   8159                                 0, oc->lm_counter_cnt - 1, "lm counter pool");
   8160     if (BCM_FAILURE(rv)) {
   8161         _bcm_tr3_oam_control_free(unit, oc);
   8162         return (rv);
   8163     }
   8164 
   8165     for (ep_index = 0; ep_index < oc->ep_count; ++ep_index) {
   8166         oc->oam_hash_data[ep_index].lm_counter_index =
   8167             _BCM_OAM_LM_COUNTER_IDX_INVALID;
   8168     }
   8169 
   8170     /* Create protection mutex. */
   8171     oc->oc_lock = sal_mutex_create("oam_control.lock");
   8172     if (NULL == oc->oc_lock) {
   8173         _bcm_tr3_oam_control_free(unit, oc);
   8174         return (BCM_E_MEMORY);
   8175     }
   8176 #ifdef BCM_HURRICANE2_SUPPORT
   8177     if (SOC_IS_HURRICANE2(unit)) {
   8178         /* Register device OAM interrupt handler call back routine. */
   8179         soc_hurricane2_oam_handler_register(unit, 
   8180                                             _bcm_tr3_oam_handle_interrupt);
   8181         soc_hurricane2_oam_ser_handler_register(unit, 
   8182                                                 _bcm_tr3_oam_ser_handler);
   8183     } else
   8184 #endif
   8185 #ifdef BCM_GREYHOUND_SUPPORT
   8186     if (SOC_IS_GREYHOUND(unit)) {
   8187         /* Register device OAM interrupt handler call back routine. */
   8188         soc_greyhound_oam_handler_register(unit, _bcm_tr3_oam_handle_interrupt);
   8189         soc_greyhound_oam_ser_handler_register(unit, 
   8190                                                _bcm_tr3_oam_ser_handler); 
   8191     } else
   8192 #endif
   8193 #ifdef BCM_HURRICANE3_SUPPORT
   8194     if (SOC_IS_HURRICANE3(unit)) {
   8195         /* Register device OAM interrupt handler call back routine. */
   8196         soc_hr3_oam_handler_register(unit, _bcm_tr3_oam_handle_interrupt);        
   8197         soc_hr3_oam_ser_handler_register(unit, _bcm_tr3_oam_ser_handler);
   8198         
   8199     } else
   8200 #endif
   8201 #ifdef BCM_GREYHOUND2_SUPPORT
   8202     if (SOC_IS_GREYHOUND2(unit)) {
   8203         /* Register device OAM interrupt handler call back routine. */
   8204         soc_gh2_oam_handler_register(unit, _bcm_tr3_oam_handle_interrupt);
   8205         soc_gh2_oam_ser_handler_register(unit,
   8206                                          _bcm_tr3_oam_ser_handler);
   8207     } else
   8208 #endif
   8209     {
   8210 #ifdef BCM_TRIUMPH3_SUPPORT
   8211         /* Register device OAM interrupt handler call back routine. */
   8212         soc_tr3_oam_handler_register(unit, _bcm_tr3_oam_handle_interrupt);
   8213         soc_tr3_oam_ser_handler_register(unit, _bcm_tr3_oam_ser_handler);
   8214 #endif
   8215 
   8216     }
   8217     /* Set up the unit OAM control structure. */
   8218     _oam_control[unit] = oc;
   8219 
   8220     /* Set up OAM module related profile tables. */
   8221     rv = _bcm_oam_profile_tables_init(unit, oc);
   8222     if (BCM_FAILURE(rv)) {
   8223         _bcm_tr3_oam_control_free(unit, oc);
   8224         return (rv);
   8225     }
   8226 
   8227 #if defined(BCM_WARM_BOOT_SUPPORT)
   8228     if (!SOC_WARM_BOOT(unit)) {
   8229         bcm_tr3_oam_scache_alloc(unit);
   8230     }
   8231 
   8232     if (SOC_WARM_BOOT(unit)) {
   8233         rv = _bcm_tr3_oam_reinit(unit);
   8234         if (BCM_FAILURE(rv)) {
   8235             _bcm_tr3_oam_control_free(unit, oc);
   8236             return (rv);
   8237         }
   8238     } else 
   8239 #endif
   8240         {
   8241             /* Enable OAM processing on all ports of this unit. */
   8242             PBMP_ALL_ITER(unit, port) {
   8243                 rv = bcm_esw_port_control_set(unit, port, bcmPortControlOAMEnable,
   8244                                               TRUE);
   8245                 if (BCM_FAILURE(rv)) {
   8246                     _bcm_tr3_oam_control_free(unit, oc);
   8247                     return (rv);
   8248                 }
   8249             }
   8250 
   8251             /* Enable CCM Rx timeouts. */
   8252 #ifdef BCM_HURRICANE2_SUPPORT
   8253             if (SOC_IS_HURRICANE2(unit) || SOC_IS_GREYHOUND(unit) ||
   8254                 SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) {
   8255                 rv = _bcm_hu2_oam_ccm_rx_timeout_set(unit, 1);
   8256             } else 
   8257 #endif /* BCM_HURRICANE2_SUPPORT */
   8258                 {
   8259                     rv = _bcm_oam_ccm_rx_timeout_set(unit, 1);
   8260                 }
   8261             if (BCM_FAILURE(rv)) {
   8262                 _bcm_tr3_oam_control_free(unit, oc);
   8263                 return (rv);
   8264             }
   8265 
   8266             /* Enable CCM Tx control. */
   8267             if(SOC_REG_IS_VALID(unit, OAM_TX_CONTROLr)){
   8268                 rv = _bcm_oam_ccm_tx_config_set(unit, 1);
   8269                 if (BCM_FAILURE(rv)) {
   8270                     _bcm_tr3_oam_control_free(unit, oc);
   8271                     return (rv);
   8272                 }
   8273             }
   8274 
   8275             /* Initailiza the FP group for LM/DM to -1 (Not created). */
   8276             oc->fp_glp_group = -1;
   8277         
   8278             /* 
   8279              * Misc config:
   8280              * 1. Prevent L2 learn for OAM MACs.
   8281              * 2. PFM setting for MCAST packets.
   8282              */
   8283             rv = _bcm_oam_misc_config(unit);
   8284             if (BCM_FAILURE(rv)) {
   8285                 _bcm_tr3_oam_control_free(unit, oc);
   8286                 return (rv);
   8287             }
   8288         }
   8289 
   8290     /*
   8291      * BHH init
   8292      */
   8293     if(soc_feature(unit, soc_feature_bhh)) {
   8294 #if defined(BCM_TRIUMPH3_SUPPORT) && defined(INCLUDE_BHH)
   8295         if(ukernel_not_ready == 0){
   8296             /*
   8297              * Initialize HOST side
   8298              */
   8299             oc->cpu_cosq = soc_property_get(unit, spn_BHH_COSQ, 
   8300                                             BHH_COSQ_INVALID);
   8301 
   8302             /*
   8303              * Allocate DMA buffers
   8304              *
   8305              * DMA buffer will be used to send and receive 'long' messages
   8306              * between SDK Host and uController (BTE).
   8307              */
   8308             oc->dma_buffer_len = sizeof(shr_bhh_msg_ctrl_t);
   8309 
   8310             /* Adding  feature specific for dma_buf_len as currently
   8311              * required buffer length for faults_get can be configurable
   8312              * by user during init. So, taking the max value of either of
   8313              * them for the purpose.Putting it under fature_check for
   8314              * giving flexibility to user.
   8315              */
   8316 #ifdef INCLUDE_OAM_FAULTS_MULTI_GET
   8317             if(soc_feature(unit, soc_feature_faults_multi_ep_get)) {
   8318                 oc->dma_buffer_len = MAX((oc->bhh_endpoint_count * sizeof(uint32)), oc->dma_buffer_len);
   8319             }
   8320 #endif
   8321             oc->dma_buffer = soc_cm_salloc(unit, oc->dma_buffer_len,
   8322                                            "BHH DMA buffer");
   8323             if (!oc->dma_buffer) {
   8324                 _bcm_tr3_oam_control_free(unit, oc);
   8325                 return (BCM_E_MEMORY);
   8326             }
   8327             sal_memset(oc->dma_buffer, 0, oc->dma_buffer_len);
   8328 
   8329             oc->dmabuf_reply = soc_cm_salloc(unit, oc->dma_buffer_len,
   8330                                              "BHH uC reply");
   8331             if (!oc->dmabuf_reply) {
   8332                 _bcm_tr3_oam_control_free(unit, oc);
   8333                 return (BCM_E_MEMORY);
   8334             }
   8335             sal_memset(oc->dmabuf_reply, 0, oc->dma_buffer_len);
   8336 
   8337             /* RX DMA channel (0..3) local to the uC */
   8338             oc->rx_channel = BCM_KT_BHH_RX_CHANNEL;
   8339 
   8340 #if defined(BCM_WARM_BOOT_SUPPORT)
   8341     if (!SOC_WARM_BOOT(unit)) {
   8342 #endif
   8343             /* Set control message data */
   8344             sal_memset(&msg_init, 0, sizeof(msg_init));
   8345             msg_init.num_sessions       = oc->bhh_endpoint_count;
   8346             msg_init.rx_channel         = oc->rx_channel;
   8347             msg_init.node_id            = node_id; 
   8348             sal_memcpy(msg_init.carrier_code, carrier_code, 
   8349                        SHR_BHH_CARRIER_CODE_LEN); 
   8350             msg_init.max_encap_length = oc->bhh_max_encap_length;
   8351             if (bhh_consolidate_final_event) {
   8352                     msg_init.flags |= BHH_SDK_MSG_CTRL_INIT_ONLY_FINAL_EVENT;
   8353             }
   8354 
   8355             /* Pack control message data into DMA buffer */
   8356             buffer     = oc->dma_buffer;
   8357             buffer_ptr = bhh_sdk_msg_ctrl_init_pack(unit, buffer, &msg_init);
   8358             buffer_len = buffer_ptr - buffer;
   8359 
   8360             /* Send BHH Init message to uC */
   8361             rv = _bcm_tr3_oam_bhh_msg_send_receive(unit,
   8362                                          MOS_MSG_SUBCLASS_BHH_INIT,
   8363                                          buffer_len, 0,
   8364                                          MOS_MSG_SUBCLASS_BHH_INIT_REPLY,
   8365                                          &reply_len, _BHH_UC_MSG_TIMEOUT_USECS);
   8366 
   8367             if (BCM_FAILURE(rv) || (reply_len != 0)) {
   8368                 _bcm_tr3_oam_control_free(unit, oc);
   8369                 return (BCM_E_INTERNAL);
   8370             }
   8371 #if defined(BCM_WARM_BOOT_SUPPORT)
   8372     }
   8373 #endif
   8374 
   8375             /*
   8376              * Start event message callback thread
   8377              */
   8378             priority = soc_property_get(unit, spn_BHH_THREAD_PRI, 
   8379                                         BHH_THREAD_PRI_DFLT);
   8380 
   8381             if (oc->event_thread_id == NULL) {
   8382                 if ((oc->event_thread_id =
   8383                      sal_thread_create("bcmBHH", SAL_THREAD_STKSZ,
   8384                                       priority,
   8385                                       _bcm_tr3_oam_bhh_callback_thread,
   8386                                        (void*)oc)) == SAL_THREAD_ERROR) {
   8387                     oc->event_thread_id = NULL;
   8388                     BCM_IF_ERROR_RETURN(bcm_tr3_oam_detach(unit));
   8389                     return (BCM_E_MEMORY);
   8390                 }
   8391             }
   8392             /*
   8393              * End BHH init
   8394              */
   8395         }
   8396         /*
   8397          * Initialize HW
   8398          */
   8399 #ifdef BCM_WARM_BOOT_SUPPORT
   8400         if (SOC_WARM_BOOT(unit)) {
   8401             rv = _bcm_tr3_oam_bhh_cos_map_recover(unit);
   8402         } else
   8403 #endif
   8404         {
   8405             rv = _bcm_tr3_oam_bhh_hw_init(unit);
   8406         }
   8407 
   8408         if (BCM_FAILURE(rv)) {
   8409             BCM_IF_ERROR_RETURN(bcm_tr3_oam_detach(unit));
   8410             return rv;
   8411         }
   8412 #endif /* BCM_TRIUMPH3_SUPPORT && INCLUDE_BHH */
   8413     }
   8414 
   8415     /* OAM initialization complete. */
   8416     _oam_control[unit]->init = TRUE;
   8417     return (BCM_E_NONE);
   8418 }
   8419 
   8420 /*
   8421  * Function:
   8422  *     bcm_tr3_oam_detach
   8423  * Purpose:
   8424  *     Shut down OAM subsystem
   8425  * Parameters:
   8426  *     unit - (IN) BCM device number
   8427  * Returns:
   8428  *     BCM_E_XXX
   8429  */
   8430 int
   8431 bcm_tr3_oam_detach(int unit)
   8432 {
   8433     _bcm_oam_control_t *oc;  /* Pointer to OAM control structure. */
   8434     bcm_port_t         port; /* Port number.                      */
   8435     int                rv;   /* Operation return status.          */
   8436 #if defined(BCM_TRIUMPH3_SUPPORT) && defined(INCLUDE_BHH)
   8437     uint16 reply_len;
   8438     sal_usecs_t timeout = 0;
   8439     int status;
   8440 #endif
   8441 
   8442 
   8443     /* Get the device OAM module handle. */
   8444     oc = _oam_control[unit];
   8445     if (NULL == oc) {
   8446         /* Module already uninitialized. */
   8447         return (BCM_E_NONE);
   8448     }
   8449 
   8450     /* Unregister all OAM interrupt event handlers. */
   8451 #ifdef BCM_HURRICANE2_SUPPORT
   8452     if (SOC_IS_HURRICANE2(unit)) {
   8453         /* Register device OAM interrupt handler call back routine. */
   8454         soc_hurricane2_oam_handler_register(unit, NULL);
   8455     } else
   8456 #endif
   8457 #ifdef BCM_GREYHOUND_SUPPORT
   8458     if (SOC_IS_GREYHOUND(unit)) {
   8459         /* Register device OAM interrupt handler call back routine. */
   8460         soc_greyhound_oam_handler_register(unit, NULL);
   8461         soc_greyhound_oam_ser_handler_register(unit, NULL);
   8462     } else
   8463 #endif
   8464 #ifdef BCM_HURRICANE3_SUPPORT
   8465     if (SOC_IS_HURRICANE3(unit)) {
   8466         /* Register device OAM interrupt handler call back routine. */
   8467         soc_hr3_oam_handler_register(unit, NULL);
   8468         soc_hr3_oam_ser_handler_register(unit, NULL);
   8469     } else
   8470 #endif
   8471 #ifdef BCM_GREYHOUND2_SUPPORT
   8472     if (SOC_IS_GREYHOUND2(unit)) {
   8473         /* Unregister device OAM interrupt handler call back routine. */
   8474         soc_gh2_oam_handler_register(unit, NULL);
   8475         soc_gh2_oam_ser_handler_register(unit, NULL);
   8476     } else
   8477 #endif
   8478     {
   8479 #ifdef BCM_TRIUMPH3_SUPPORT
   8480         soc_tr3_oam_handler_register(unit, NULL);
   8481         soc_tr3_oam_ser_handler_register(unit, NULL);
   8482 #endif 
   8483     }
   8484     if (NULL != oc->oc_lock) {
   8485         _BCM_OAM_LOCK(oc);
   8486     }
   8487 
   8488     rv = _bcm_tr3_oam_events_unregister(unit, oc);
   8489     if (BCM_FAILURE(rv)) {
   8490         if (NULL != oc->oc_lock) {
   8491             _BCM_OAM_UNLOCK(oc);
   8492         }
   8493         return (rv);
   8494     }
   8495 
   8496     /* Disable CCM Rx Timeouts. */
   8497 #ifdef BCM_HURRICANE2_SUPPORT
   8498     if (SOC_IS_HURRICANE2(unit) || SOC_IS_GREYHOUND(unit) ||
   8499         SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) {
   8500         rv = _bcm_hu2_oam_ccm_rx_timeout_set(unit, 1);
   8501     } else 
   8502 #endif /* BCM_HURRICANE2_SUPPORT */
   8503     {
   8504         rv = _bcm_oam_ccm_rx_timeout_set(unit, 0);
   8505     }
   8506     if (BCM_FAILURE(rv)) {
   8507         if (NULL != oc->oc_lock) {
   8508             _BCM_OAM_UNLOCK(oc);
   8509         }
   8510         return (rv);
   8511     }
   8512 
   8513     /* Disable CCM Tx control for the device. */
   8514     if(SOC_REG_IS_VALID(unit, OAM_TX_CONTROLr)){
   8515         rv = _bcm_oam_ccm_tx_config_set(unit, 0);
   8516         if (BCM_FAILURE(rv)) {
   8517             if (NULL != oc->oc_lock) {
   8518                 _BCM_OAM_UNLOCK(oc);
   8519             }
   8520             return (rv);
   8521         }
   8522     }
   8523 
   8524     /* Disable OAM PDU Rx processing on all ports. */
   8525     PBMP_ALL_ITER(unit, port) {
   8526         rv = bcm_esw_port_control_set(unit, port,
   8527                                       bcmPortControlOAMEnable, 0);
   8528         if (BCM_FAILURE(rv)) {
   8529             if (NULL != oc->oc_lock) {
   8530                 _BCM_OAM_UNLOCK(oc);
   8531             }
   8532             return (rv);
   8533         }
   8534     }
   8535 
   8536     /*
   8537      * BHH specific
   8538      */
   8539     if (soc_feature(unit, soc_feature_bhh)) {
   8540 #if defined(BCM_TRIUMPH3_SUPPORT) && defined(INCLUDE_BHH)
   8541         if (oc->ukernel_not_ready == 0) {
   8542             /*
   8543              * Event Handler thread exit signal
   8544              */
   8545             timeout = sal_time_usecs() + 5000000;
   8546             while (NULL !=  oc->event_thread_id) {
   8547                 soc_cmic_uc_msg_receive_cancel(unit, oc->uc_num,
   8548                                                MOS_MSG_CLASS_BHH_EVENT);
   8549 
   8550                 if (sal_time_usecs() < timeout) {
   8551                     /*give some time to already running bhh callback thread
   8552                      * to schedule and exit */
   8553                     sal_usleep(10000);
   8554                 } else {
   8555                     /*timeout*/
   8556                     LOG_ERROR(BSL_LS_BCM_OAM,
   8557                               (BSL_META_U(unit,
   8558                                           "BHH event thread did not exit.\n")));
   8559                     _BCM_OAM_UNLOCK(oc);
   8560                     return BCM_E_INTERNAL;
   8561                 }
   8562             }
   8563 
   8564             /*
   8565              * Send BHH Uninit message to uC
   8566              * Ignore error since that may indicate uKernel was reloaded.
   8567              */
   8568 #if defined(BCM_WARM_BOOT_SUPPORT)
   8569     if (!SOC_WARM_BOOT(unit)) {
   8570 #endif
   8571         SOC_IF_ERROR_RETURN(soc_uc_status(unit, oc->uc_num, &status));
   8572         if (status) {
   8573             rv = _bcm_tr3_oam_bhh_msg_send_receive(unit,
   8574                                               MOS_MSG_SUBCLASS_BHH_UNINIT,
   8575                                               0, 0,
   8576                                               MOS_MSG_SUBCLASS_BHH_UNINIT_REPLY,
   8577                                               &reply_len, 5000000);
   8578             if (BCM_SUCCESS(rv) && (reply_len != 0)) {
   8579                 if (NULL != oc->oc_lock) {
   8580                     _BCM_OAM_UNLOCK(oc);
   8581                 }
   8582                 return BCM_E_INTERNAL;
   8583             }
   8584          }
   8585 #if defined(BCM_WARM_BOOT_SUPPORT)
   8586     }
   8587 #endif
   8588 
   8589             if (!SOC_WARM_BOOT(unit)) {
   8590                 /*
   8591                  * Delete CPU COS queue mapping entries for BHH packets
   8592                  */
   8593                 if (oc->cpu_cosq_ach_error_index >= 0) {
   8594                     rv = bcm_esw_rx_cosq_mapping_delete(unit,
   8595                                                    oc->cpu_cosq_ach_error_index);
   8596                     if (BCM_FAILURE(rv)) {
   8597                         if (NULL != oc->oc_lock) {
   8598                             _BCM_OAM_UNLOCK(oc);
   8599                         }
   8600                         return (rv);
   8601                     }
   8602                     oc->cpu_cosq_ach_error_index = -1;
   8603                 }
   8604 
   8605                 /* Destroy UDF entries installed for BHH, since FP/UDF init happens
   8606                  * before OAM init, they may have already been destroyed hence
   8607                  * BCM_E_NOT_FOUND is not an error for this operation
   8608                  */
   8609                 if (oc->bhh_lm_dm_enable) {
   8610                     if(oc->bhh_udf_mode) {
   8611                         rv = bcm_esw_udf_pkt_format_delete(unit,
   8612                                                          oc->bhh_label_udf_id,
   8613                                                          oc->bhh_udf_pkt_fmt_id);
   8614                         if (rv != BCM_E_NOT_FOUND && BCM_FAILURE(rv)) {
   8615                             if (NULL != oc->oc_lock) {
   8616                                 _BCM_OAM_UNLOCK(oc);
   8617                             }
   8618                             return (rv);
   8619                         }
   8620 
   8621                         rv = bcm_esw_udf_pkt_format_delete(unit,
   8622                                                          oc->bhh_ach_udf_id,
   8623                                                          oc->bhh_udf_pkt_fmt_id);
   8624                         if (rv != BCM_E_NOT_FOUND && BCM_FAILURE(rv)) {
   8625                             if (NULL != oc->oc_lock) {
   8626                                 _BCM_OAM_UNLOCK(oc);
   8627                             }
   8628                             return (rv);
   8629                         }
   8630 
   8631                         rv = bcm_esw_udf_pkt_format_delete(unit,
   8632                                                          oc->bhh_opcode_udf_id,
   8633                                                          oc->bhh_udf_pkt_fmt_id);
   8634                         if (rv != BCM_E_NOT_FOUND && BCM_FAILURE(rv)) {
   8635                             if (NULL != oc->oc_lock) {
   8636                                 _BCM_OAM_UNLOCK(oc);
   8637                             }
   8638                             return (rv);
   8639                         }
   8640 
   8641                         rv = bcm_esw_udf_pkt_format_destroy(unit,
   8642                                                          oc->bhh_udf_pkt_fmt_id);
   8643                         if (rv != BCM_E_NOT_FOUND && BCM_FAILURE(rv)) {
   8644                             if (NULL != oc->oc_lock) {
   8645                                 _BCM_OAM_UNLOCK(oc);
   8646                             }
   8647                             return (rv);
   8648                         }
   8649 
   8650                         rv = bcm_esw_udf_destroy(unit, oc->bhh_label_udf_id);
   8651                         if (rv != BCM_E_NOT_FOUND && BCM_FAILURE(rv)) {
   8652                             if (NULL != oc->oc_lock) {
   8653                                 _BCM_OAM_UNLOCK(oc);
   8654                             }
   8655                             return (rv);
   8656                         }
   8657 
   8658                         rv = bcm_esw_udf_destroy(unit, oc->bhh_ach_udf_id);
   8659                         if (rv != BCM_E_NOT_FOUND && BCM_FAILURE(rv)) {
   8660                             if (NULL != oc->oc_lock) {
   8661                                 _BCM_OAM_UNLOCK(oc);
   8662                             }
   8663                             return (rv);
   8664                         }
   8665 
   8666                         rv = bcm_esw_udf_destroy(unit, oc->bhh_opcode_udf_id);
   8667                         if (rv != BCM_E_NOT_FOUND && BCM_FAILURE(rv)) {
   8668                             if (NULL != oc->oc_lock) {
   8669                                 _BCM_OAM_UNLOCK(oc);
   8670                             }
   8671                             return (rv);
   8672                         }
   8673 
   8674                     } else {
   8675                         rv = bcm_esw_field_data_qualifier_packet_format_delete(unit,
   8676                                                                        oc->bhh_label_qual_id,
   8677                                                                        &(oc->bhh_field_pkt_fmt));
   8678                         if (rv != BCM_E_NOT_FOUND && BCM_FAILURE(rv)) {
   8679                             if (NULL != oc->oc_lock) {
   8680                                 _BCM_OAM_UNLOCK(oc);
   8681                             }
   8682                             return (rv);
   8683                         }
   8684 
   8685                         rv = bcm_esw_field_data_qualifier_packet_format_delete(unit,
   8686                                                                          oc->bhh_ach_qual_id,
   8687                                                                          &(oc->bhh_field_pkt_fmt));
   8688                         if (rv != BCM_E_NOT_FOUND && BCM_FAILURE(rv)) {
   8689                             if (NULL != oc->oc_lock) {
   8690                                 _BCM_OAM_UNLOCK(oc);
   8691                             }
   8692                             return (rv);
   8693                         }
   8694 
   8695                         rv = bcm_esw_field_data_qualifier_packet_format_delete(unit,
   8696                                                                          oc->bhh_opcode_qual_id,
   8697                                                                          &(oc->bhh_field_pkt_fmt));
   8698                         if (rv != BCM_E_NOT_FOUND && BCM_FAILURE(rv)) {
   8699                             if (NULL != oc->oc_lock) {
   8700                                 _BCM_OAM_UNLOCK(oc);
   8701                             }
   8702                             return (rv);
   8703                         }
   8704 
   8705                         rv = bcm_esw_field_data_qualifier_destroy(unit,
   8706                                                                   oc->bhh_label_qual_id);
   8707                         if (rv != BCM_E_NOT_FOUND && BCM_FAILURE(rv)) {
   8708                             if (NULL != oc->oc_lock) {
   8709                                 _BCM_OAM_UNLOCK(oc);
   8710                             }
   8711                             return (rv);
   8712                         }
   8713 
   8714                         rv = bcm_esw_field_data_qualifier_destroy(unit,
   8715                                                                   oc->bhh_ach_qual_id);
   8716                         if (rv != BCM_E_NOT_FOUND && BCM_FAILURE(rv)) {
   8717                             if (NULL != oc->oc_lock) {
   8718                                 _BCM_OAM_UNLOCK(oc);
   8719                             }
   8720                             return (rv);
   8721                         }
   8722 
   8723                         rv = bcm_esw_field_data_qualifier_destroy(unit,
   8724                                                                   oc->bhh_opcode_qual_id);
   8725                         if (rv != BCM_E_NOT_FOUND && BCM_FAILURE(rv)) {
   8726                             if (NULL != oc->oc_lock) {
   8727                                 _BCM_OAM_UNLOCK(oc);
   8728                             }
   8729                             return (rv);
   8730                         }
   8731                     }
   8732                 }
   8733             }
   8734         }
   8735 #endif /* INCLUDE_BHH */
   8736     }
   8737 
   8738     /* Destroy all groups and assoicated endpoints and free the resources. */
   8739     rv = bcm_tr3_oam_group_destroy_all(unit);
   8740     if (BCM_FAILURE(rv)) {
   8741         if (NULL != oc->oc_lock) {
   8742             _BCM_OAM_UNLOCK(oc);
   8743         }
   8744         return (rv);
   8745     }
   8746 
   8747     /* Release the protection mutex. */
   8748     _BCM_OAM_UNLOCK(oc);
   8749 
   8750     /* Free OAM module allocated resources. */
   8751     _bcm_tr3_oam_control_free(unit, oc);
   8752 
   8753     return (BCM_E_NONE);
   8754 }
   8755 
   8756 /*
   8757  * Function:
   8758  *     bcm_tr3_oam_group_create
   8759  * Purpose:
   8760  *     Create or replace an OAM group object
   8761  * Parameters:
   8762  *     unit       - (IN) BCM device number
   8763  *     group_info - (IN/OUT) Pointer to an OAM group information.
   8764  * Returns:
   8765  *     BCM_E_XXX
   8766  */
   8767 int
   8768 bcm_tr3_oam_group_create(int unit, bcm_oam_group_info_t *group_info)
   8769 {
   8770     ma_state_entry_t       ma_state_entry;       /* MA State table entry.     */
   8771     uint8                  grp_name_hw_buf[BCM_OAM_GROUP_NAME_LENGTH]; /* Grp */
   8772                                                  /* name.                     */
   8773     maid_reduction_entry_t maid_reduction_entry; /* MA ID reduction table     */
   8774     _bcm_oam_group_data_t  *ma_group;            /* Pointer to group info.    */
   8775     _bcm_oam_control_t     *oc;                  /* OAM control structure.    */
   8776     int                    rv;                   /* Operation return status.  */
   8777                                                  /* entry.                    */
   8778     uint8                  sw_rdi;               /* Remote defect indicator.  */
   8779 
   8780 #if defined(BCM_TRIUMPH3_SUPPORT) && defined(INCLUDE_BHH)
   8781     bhh_sdk_msg_ctrl_sess_set_t msg_sess;
   8782     uint8 *buffer, *buffer_ptr;
   8783     uint16 buffer_len, reply_len;
   8784     uint32 session_flags = 0;
   8785     _bcm_oam_hash_data_t *h_data_p;
   8786     _bcm_oam_ep_list_t      *cur;
   8787 #endif
   8788 
   8789     /* Validate input parameter. */
   8790     if (NULL == group_info) {
   8791         return (BCM_E_PARAM);
   8792     }
   8793 
   8794     /* Get OAM control structure handle. */
   8795     BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc));
   8796 
   8797     /* Validate group id. */
   8798     if (group_info->flags & BCM_OAM_GROUP_WITH_ID) {
   8799         _BCM_OAM_GROUP_INDEX_VALIDATE(group_info->id);
   8800     }
   8801 
   8802     _BCM_OAM_LOCK(oc);
   8803 
   8804     /*
   8805      * If MA group create is called with replace flag bit set.
   8806      *  - Check and return error if a group does not exist with the ID.
   8807      */
   8808     if (group_info->flags & BCM_OAM_GROUP_REPLACE) {
   8809         if (group_info->flags & BCM_OAM_GROUP_WITH_ID) {
   8810 
   8811             /* Search the list with the MA Group ID value. */
   8812             rv = shr_idxres_list_elem_state(oc->group_pool, group_info->id);
   8813             if (BCM_E_EXISTS != rv) {
   8814                 _BCM_OAM_UNLOCK(oc);
   8815                 LOG_ERROR(BSL_LS_BCM_OAM,
   8816                           (BSL_META_U(unit,
   8817                                       "OAM Error: Group does not exist.\n")));
   8818                 return (BCM_E_PARAM);
   8819             }
   8820         } else {
   8821             _BCM_OAM_UNLOCK(oc);
   8822             LOG_ERROR(BSL_LS_BCM_OAM,
   8823                       (BSL_META_U(unit,
   8824                                   "OAM Error: Replace command needs a valid Group ID.\n")));
   8825             return (BCM_E_PARAM);
   8826         }
   8827     } else if (group_info->flags & BCM_OAM_GROUP_WITH_ID) {
   8828         /*
   8829          * If MA group create is called with ID flag bit set.
   8830          *  - Check and return error if the ID is already in use.
   8831          */
   8832         rv = shr_idxres_list_reserve(oc->group_pool, group_info->id,
   8833                                      group_info->id);
   8834         if (BCM_FAILURE(rv)) {
   8835             _BCM_OAM_UNLOCK(oc);
   8836             return ((rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv);
   8837         }
   8838     } else {
   8839         /* Reserve the next available group index. */
   8840          rv = shr_idxres_list_alloc(oc->group_pool,
   8841                                     (shr_idxres_element_t *) &group_info->id);
   8842         if (BCM_FAILURE(rv)) {
   8843             _BCM_OAM_UNLOCK(oc);
   8844             LOG_ERROR(BSL_LS_BCM_OAM,
   8845                       (BSL_META_U(unit,
   8846                                   "OAM Error: Group allocation (GID=%d)"
   8847                                    " %s\n"), group_info->id, bcm_errmsg(rv)));
   8848             return (rv);
   8849         }
   8850     }
   8851 
   8852     /* Get this group memory to store group information. */
   8853     ma_group = &oc->group_info[group_info->id];
   8854 
   8855     /* Store the group name. */
   8856     sal_memcpy(&ma_group->name, &group_info->name, BCM_OAM_GROUP_NAME_LENGTH);
   8857 
   8858     /* Store Lowest Alarm Priority */
   8859     ma_group->lowest_alarm_priority = group_info->lowest_alarm_priority;
   8860 
   8861     if(!(group_info->flags & BCM_OAM_GROUP_REPLACE)) {
   8862         _BCM_OAM_ALLOC((ma_group->ep_list),_bcm_oam_ep_list_t *,
   8863                sizeof(_bcm_oam_ep_list_t *), "EP list head");
   8864 
   8865         /* Initialize head to NULL.*/
   8866         *ma_group->ep_list =  NULL;
   8867     }
   8868 
   8869     /*
   8870      * Maintenance Association ID - Reduction table update.
   8871      */
   8872 
   8873     /* Prepare group name for hardware write. */
   8874     _bcm_tr3_oam_group_name_mangle(ma_group->name, grp_name_hw_buf);
   8875 
   8876     sal_memset(&maid_reduction_entry, 0, sizeof(maid_reduction_entry_t));
   8877 
   8878     /* Calculate CRC32 value for the group name string and set in entry. */
   8879     soc_MAID_REDUCTIONm_field32_set
   8880         (unit, &maid_reduction_entry, REDUCED_MAIDf,
   8881          soc_draco_crc32(grp_name_hw_buf, BCM_OAM_GROUP_NAME_LENGTH));
   8882 
   8883     /* Check if software RDI flag bit needs to be set in hardware. */
   8884     sw_rdi = ((group_info->flags & BCM_OAM_GROUP_REMOTE_DEFECT_TX) ? 1 : 0);
   8885 
   8886     /* Set RDI status for out going CCM PDUs. */
   8887     soc_MAID_REDUCTIONm_field32_set(unit, &maid_reduction_entry, SW_RDIf,
   8888                                     sw_rdi);
   8889 
   8890     if (soc_feature(unit, soc_feature_bhh)) {
   8891 #if defined(BCM_TRIUMPH3_SUPPORT) && defined(INCLUDE_BHH)
   8892         /* Send message to uC to set the Soft RDI, if RDI flag is set */
   8893         if (group_info->flags & BCM_OAM_GROUP_REMOTE_DEFECT_TX) {
   8894 
   8895            /* Get the endpoint list head pointer. */
   8896            cur = *(ma_group->ep_list);
   8897 
   8898            /* Traverse to the tail of the list. */
   8899            while (NULL != cur) {
   8900                h_data_p = cur->ep_data_p;
   8901                if (NULL == h_data_p) {
   8902                    LOG_ERROR(BSL_LS_BCM_OAM,
   8903                              (BSL_META_U(unit,
   8904                                          "OAM Error: Group=%d endpoints access failed -"
   8905                                           " %s.\n"), group_info->id, bcm_errmsg(BCM_E_INTERNAL)));
   8906                    _BCM_OAM_UNLOCK(oc);
   8907                    return (BCM_E_INTERNAL);
   8908                }
   8909 
   8910                if ((h_data_p->type == bcmOAMEndpointTypeBHHMPLS) ||
   8911                    (h_data_p->type == bcmOAMEndpointTypeBHHMPLSVccv)) {
   8912                    /* Set the RDI flag in session bits */
   8913                    session_flags |= SHR_BHH_SESS_SET_F_RDI;
   8914 
   8915                    /* Get the session is from endpoint */
   8916                    msg_sess.sess_id =
   8917                          BCM_OAM_BHH_GET_UKERNEL_EP(h_data_p->ep_id);
   8918 
   8919                    /* Pack control message data into DMA buffer */
   8920                    msg_sess.flags = session_flags;
   8921 
   8922                    buffer     = oc->dma_buffer;
   8923                    buffer_ptr = bhh_sdk_msg_ctrl_sess_set_pack(buffer, &msg_sess);
   8924                    buffer_len = buffer_ptr - buffer;
   8925 
   8926                    /* Send BHH Session Update message to uC */
   8927                    rv =  _bcm_tr3_oam_bhh_msg_send_receive(unit,
   8928                                                      MOS_MSG_SUBCLASS_BHH_SESS_SET,
   8929                                                      buffer_len, 0,
   8930                                                      MOS_MSG_SUBCLASS_BHH_SESS_SET_REPLY,
   8931                                                      &reply_len, _BHH_UC_MSG_TIMEOUT_USECS);
   8932                    if (BCM_FAILURE(rv)) {
   8933                        LOG_ERROR(BSL_LS_BCM_OAM,
   8934                                 (BSL_META_U(unit,
   8935                                             "OAM Error: ukernel msg failed for"
   8936                                             "%s.\n"), bcm_errmsg(rv)));
   8937                        _BCM_OAM_UNLOCK(oc);
   8938                        return (BCM_E_INTERNAL);
   8939                    }
   8940                }
   8941                cur = cur->next;
   8942            }
   8943         }
   8944 #endif
   8945     }
   8946 
   8947     /* Enable hardware lookup for this entry. */
   8948     soc_MAID_REDUCTIONm_field32_set(unit, &maid_reduction_entry, VALIDf, 1);
   8949 
   8950 
   8951     /* Write entry to hardware. */
   8952     rv = WRITE_MAID_REDUCTIONm(unit, MEM_BLOCK_ALL, group_info->id,
   8953                                &maid_reduction_entry);
   8954     if (SOC_FAILURE(rv)) {
   8955         _BCM_OAM_UNLOCK(oc);
   8956         return rv;
   8957     }
   8958 
   8959     /*
   8960      * Maintenance Association State table update.
   8961      */
   8962     sal_memset(&ma_state_entry, 0, sizeof(ma_state_entry_t));
   8963 
   8964     /*
   8965      * If it a group info replace operation, retain previous group
   8966      * defect status.
   8967      */
   8968     if (group_info->flags & BCM_OAM_GROUP_REPLACE) {
   8969         rv = READ_MA_STATEm(unit, MEM_BLOCK_ALL, group_info->id,
   8970                             &ma_state_entry);
   8971         if (SOC_FAILURE(rv)) {
   8972             _BCM_OAM_UNLOCK(oc);
   8973             return rv;
   8974         }
   8975     }
   8976 
   8977     /* Set the lowest alarm priority info. */
   8978     soc_MA_STATEm_field32_set(unit, &ma_state_entry, LOWESTALARMPRIf,
   8979                               group_info->lowest_alarm_priority);
   8980 
   8981     /* Mark the entry as valid. */
   8982     soc_MA_STATEm_field32_set(unit, &ma_state_entry, VALIDf, 1);
   8983 
   8984     /* Write group information to hardware table. */
   8985     rv = WRITE_MA_STATEm(unit, MEM_BLOCK_ALL, group_info->id, &ma_state_entry);
   8986     if (SOC_FAILURE(rv)) {
   8987         _BCM_OAM_UNLOCK(oc);
   8988         return rv;
   8989     }
   8990 
   8991     /* Make the group as in used status. */
   8992     ma_group->in_use = 1;
   8993 
   8994     _BCM_OAM_UNLOCK(oc);
   8995 
   8996 #ifdef BCM_WARM_BOOT_SUPPORT
   8997     SOC_CONTROL_LOCK(unit);
   8998     SOC_CONTROL(unit)->scache_dirty = 1;
   8999     SOC_CONTROL_UNLOCK(unit);
   9000 #endif
   9001 
   9002     return (BCM_E_NONE);
   9003 }
   9004 
   9005 /*
   9006  * Function:
   9007  *     bcm_tr3_oam_group_get
   9008  * Purpose:
   9009  *     Get an OAM group object
   9010  * Parameters:
   9011  *     unit       - (IN) BCM device number
   9012  *     group      - (IN) OAM Group ID.
   9013  *     group_info - (OUT) Pointer to group information buffer.
   9014  * Returns:
   9015  *      BCM_E_XXX
   9016  */
   9017 int
   9018 bcm_tr3_oam_group_get(int unit, bcm_oam_group_t group,
   9019                       bcm_oam_group_info_t *group_info)
   9020 {
   9021     _bcm_oam_control_t    *oc;      /* Pointer to OAM control structure. */
   9022     _bcm_oam_group_data_t *group_p; /* Pointer to group list.            */
   9023     int                   rv;       /* Operation return status.          */
   9024 
   9025 #if defined(INCLUDE_BHH)
   9026     bhh_sdk_msg_ctrl_sess_get_t msg;
   9027     uint8 *buffer, *buffer_ptr;
   9028     uint16 buffer_len, reply_len;
   9029     _bcm_oam_hash_data_t *h_data_p;
   9030     _bcm_oam_ep_list_t      *cur = NULL;
   9031     int sess_id = 0;
   9032 #endif
   9033 
   9034     /* Validate input parameter. */
   9035     if (NULL == group_info) {
   9036         return (BCM_E_PARAM);
   9037     }
   9038 
   9039     /* Get OAM device control structure. */
   9040     BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc));
   9041 
   9042     /* Validate group index. */
   9043     _BCM_OAM_GROUP_INDEX_VALIDATE(group);
   9044 
   9045     _BCM_OAM_LOCK(oc);
   9046 
   9047     /* Check if the group is in use. */
   9048     rv = shr_idxres_list_elem_state(oc->group_pool, group);
   9049     if (BCM_E_EXISTS != rv) {
   9050         _BCM_OAM_UNLOCK(oc);
   9051         LOG_ERROR(BSL_LS_BCM_OAM,
   9052                   (BSL_META_U(unit,
   9053                               "OAM Error: GID=%d - %s.\n"),
   9054                    group, bcm_errmsg(rv)));
   9055         return (rv);
   9056     }
   9057 
   9058     /* Get pointer to this group in the group list. */
   9059     group_p = oc->group_info;
   9060 
   9061     /* Get the group information. */
   9062     rv = _bcm_tr3_oam_get_group(unit, group, group_p, group_info);
   9063     if (BCM_FAILURE(rv)) {
   9064         _BCM_OAM_UNLOCK(oc);
   9065         LOG_ERROR(BSL_LS_BCM_OAM,
   9066                   (BSL_META_U(unit,
   9067                               "OAM Error: bcm_tr3_oam_group_get Group ID=%d "
   9068                                "- Failed.\n"), group));
   9069         return (rv);
   9070     }
   9071 
   9072     if (soc_feature(unit, soc_feature_bhh)) {
   9073 #if defined(INCLUDE_BHH)
   9074         if (!oc->ukernel_not_ready) {
   9075             group_p = &oc->group_info[group_info->id];
   9076             /* Get the endpoint list head pointer. */
   9077             if (group_p->ep_list != NULL) {
   9078                 cur = *(group_p->ep_list);
   9079             }
   9080 
   9081             while (NULL != cur) {
   9082                 h_data_p = cur->ep_data_p;
   9083                 if (NULL == h_data_p) {
   9084                     LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit,
   9085                                                           "OAM(unit %d) Error: Group=%d endpoints access failed -"
   9086                                                           " %s.\n"), unit, group_info->id,
   9087                                                bcm_errmsg(BCM_E_INTERNAL)));
   9088                     _BCM_OAM_UNLOCK(oc);
   9089                     return (BCM_E_INTERNAL);
   9090                 }
   9091                 if ((h_data_p->type == bcmOAMEndpointTypeBHHMPLS) ||
   9092                     (h_data_p->type == bcmOAMEndpointTypeBHHMPLSVccv)) {
   9093                     sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(h_data_p->ep_id);
   9094                     rv = _bcm_tr3_oam_bhh_msg_send_receive(unit,
   9095                                                            MOS_MSG_SUBCLASS_BHH_SESS_GET,
   9096                                                            sess_id, 0,
   9097                                                            MOS_MSG_SUBCLASS_BHH_SESS_GET_REPLY,
   9098                                                            &reply_len, _BHH_UC_MSG_TIMEOUT_USECS);
   9099                     if (BCM_FAILURE(rv)) {
   9100                         LOG_ERROR(BSL_LS_BCM_OAM,
   9101                                   (BSL_META_U(unit,
   9102                                               "OAM Error: ukernel msg failed for"
   9103                                               "%s.\n"), bcm_errmsg(rv)));
   9104                         _BCM_OAM_UNLOCK(oc);
   9105                         return (rv);
   9106                     }
   9107 
   9108                     /* Pack control message data into DMA buffer */
   9109                     buffer = oc->dma_buffer;
   9110                     buffer_ptr = bhh_sdk_msg_ctrl_sess_get_unpack(buffer, &msg);
   9111                     buffer_len = buffer_ptr - buffer;
   9112 
   9113                     if (reply_len != buffer_len) {
   9114                         rv = BCM_E_INTERNAL;
   9115                         LOG_ERROR(BSL_LS_BCM_OAM,
   9116                                   (BSL_META_U(unit,
   9117                                               "OAM(unit %d) Error: ukernel msg failed for"
   9118                                               " EP=%d %s.\n"), unit, h_data_p->ep_id,
   9119                                    bcm_errmsg(rv)));
   9120                         _BCM_OAM_UNLOCK(oc);
   9121                         return (rv);
   9122                     } else {
   9123                         if(msg.fault_flags & BHH_BTE_EVENT_CCM_TIMEOUT){
   9124                             group_info->faults |= BCM_OAM_BHH_FAULT_CCM_TIMEOUT;
   9125                         }
   9126                         if(msg.fault_flags & BHH_BTE_EVENT_CCM_RDI){
   9127                             group_info->faults |= BCM_OAM_BHH_FAULT_CCM_RDI;
   9128                         }
   9129                         if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_LEVEL){
   9130                             group_info->faults |=
   9131                                 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEG_LEVEL;
   9132                         }
   9133                         if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_ID){
   9134                             group_info->faults |=
   9135                                 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEG_ID;
   9136                         }
   9137                         if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_MEP_ID){
   9138                             group_info->faults |=
   9139                                 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEP_ID;
   9140                         }
   9141                         if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_PERIOD){
   9142                             group_info->faults |=
   9143                                 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_PERIOD;
   9144                         }
   9145                         if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_PRIORITY){
   9146                             group_info->faults |=
   9147                                 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_PRIORITY;
   9148                         }
   9149                         if(msg.fault_flags & BHH_BTE_EVENT_CSF_LOS) {
   9150                             group_info->faults |=
   9151                                 BCM_OAM_ENDPOINT_BHH_FAULT_CSF_LOS;
   9152                         }
   9153                         if(msg.fault_flags & BHH_BTE_EVENT_CSF_FDI) {
   9154                             group_info->faults |=
   9155                                 BCM_OAM_ENDPOINT_BHH_FAULT_CSF_FDI;
   9156                         }
   9157                         if(msg.fault_flags & BHH_BTE_EVENT_CSF_RDI) {
   9158                             group_info->faults |=
   9159                                 BCM_OAM_ENDPOINT_BHH_FAULT_CSF_RDI;
   9160                         }
   9161                     }
   9162                 }
   9163                 cur = cur->next;
   9164             }
   9165         }
   9166 #endif
   9167     }
   9168 
   9169     _BCM_OAM_UNLOCK(oc);
   9170     return (BCM_E_NONE);
   9171 }
   9172 
   9173 /*
   9174  * Function:
   9175  *     bcm_tr3_oam_group_destroy
   9176  * Purpose:
   9177  *     Destroy an OAM group object and its associated endpoints.
   9178  * Parameters:
   9179  *     unit  - (IN) BCM device number
   9180  *     group - (IN) The ID of the OAM group object to destroy
   9181  * Returns:
   9182  *     BCM_E_XXX
   9183  */
   9184 int
   9185 bcm_tr3_oam_group_destroy(int unit,
   9186                           bcm_oam_group_t group)
   9187 {
   9188     _bcm_oam_control_t     *oc;       /* Pointer to OAM control structure. */
   9189     _bcm_oam_group_data_t  *g_info_p; /* Pointer to group list.            */
   9190     int                    rv;        /* Operation return status.          */
   9191     maid_reduction_entry_t maid_reduction_entry; /* MAID_REDUCTION entry.  */
   9192     ma_state_entry_t       ma_state_entry; /* MA_STATE table entry.        */
   9193 
   9194     /* Get OAM device control structure. */
   9195     BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc));
   9196 
   9197     /* Validate group index. */
   9198     _BCM_OAM_GROUP_INDEX_VALIDATE(group);
   9199 
   9200     _BCM_OAM_LOCK(oc);
   9201 
   9202     /* Check if the group is in use. */
   9203     rv = shr_idxres_list_elem_state(oc->group_pool, group);
   9204     if (BCM_E_EXISTS != rv) {
   9205         _BCM_OAM_UNLOCK(oc);
   9206         LOG_ERROR(BSL_LS_BCM_OAM,
   9207                   (BSL_META_U(unit,
   9208                               "OAM Error: GID=%d - %s.\n"),
   9209                    group, bcm_errmsg(rv)));
   9210         return (rv);
   9211     }
   9212 
   9213     /* Get pointer to this group in the group list. */
   9214     g_info_p = &oc->group_info[group];
   9215 
   9216     rv = _bcm_tr3_oam_group_endpoints_destroy(unit, g_info_p);
   9217     if (BCM_FAILURE(rv)) {
   9218         _BCM_OAM_UNLOCK(oc);
   9219         LOG_ERROR(BSL_LS_BCM_OAM,
   9220                   (BSL_META_U(unit,
   9221                               "OAM Error: bcm_tr3_oam_endpoint_destroy_all"
   9222                                " (GID=%d) - %s.\n"), group, bcm_errmsg(rv)));
   9223         return (rv);
   9224     }
   9225 
   9226     sal_memset(&maid_reduction_entry, 0, sizeof(maid_reduction_entry_t));
   9227     rv = WRITE_MAID_REDUCTIONm(unit, MEM_BLOCK_ALL, group,
   9228                           &maid_reduction_entry);
   9229     if (BCM_FAILURE(rv)) {
   9230         _BCM_OAM_UNLOCK(oc);
   9231         LOG_DEBUG(BSL_LS_BCM_OAM,
   9232                   (BSL_META_U(unit,
   9233                               "OAM Error: MAID REDUCTION write "
   9234                                "(GID=%d) - %s.\n"), group, bcm_errmsg(rv)));
   9235         return (rv);
   9236     }
   9237 
   9238     /*
   9239      * Maintenance Association State table update.
   9240      */
   9241     sal_memset(&ma_state_entry, 0, sizeof(ma_state_entry_t));
   9242 
   9243     rv = WRITE_MA_STATEm(unit, MEM_BLOCK_ALL, group, &ma_state_entry);
   9244     if (BCM_FAILURE(rv)) {
   9245         _BCM_OAM_UNLOCK(oc);
   9246         LOG_ERROR(BSL_LS_BCM_OAM,
   9247                   (BSL_META_U(unit,
   9248                               "OAM Error: MA STATE write "
   9249                                "(GID=%d) - %s.\n"), group, bcm_errmsg(rv)));
   9250         return (rv);
   9251     }
   9252 
   9253     /* Return Group ID back to free group. */
   9254     rv = shr_idxres_list_free(oc->group_pool, group);
   9255     if (BCM_FAILURE(rv)) {
   9256         _BCM_OAM_UNLOCK(oc);
   9257         LOG_ERROR(BSL_LS_BCM_OAM,
   9258                   (BSL_META_U(unit,
   9259                               "OAM Error: Idx free failed "
   9260                                "(GID=%d) - %s.\n"), group, bcm_errmsg(rv)));
   9261         return (rv);
   9262     }
   9263 
   9264     _BCM_OAM_UNLOCK(oc);
   9265 
   9266 #ifdef BCM_WARM_BOOT_SUPPORT
   9267     SOC_CONTROL_LOCK(unit);
   9268     SOC_CONTROL(unit)->scache_dirty = 1;
   9269     SOC_CONTROL_UNLOCK(unit);
   9270 #endif
   9271 
   9272     return (BCM_E_NONE);
   9273 }
   9274 
   9275 /*
   9276  * Function:
   9277  *     bcm_tr3_oam_group_destroy_all
   9278  * Purpose:
   9279  *     Destroy all OAM group objects and their associated endpoints.
   9280  * Parameters:
   9281  *     unit  - (IN) BCM device number
   9282  * Returns:
   9283  *     BCM_E_XXX
   9284  */
   9285 int
   9286 bcm_tr3_oam_group_destroy_all(int unit)
   9287 {
   9288     _bcm_oam_control_t *oc;   /* Pointer to OAM control structure.    */
   9289     int                group; /* Maintenance Association group index. */
   9290     int                rv;    /* Operation return status .            */
   9291 
   9292     /* Get device OAM control structure handle. */
   9293     BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc));
   9294 
   9295     _BCM_OAM_LOCK(oc);
   9296 
   9297     for (group = 0; group < oc->group_count; group++) {
   9298 
   9299         /* Check if the group is in use. */
   9300         rv = shr_idxres_list_elem_state(oc->group_pool, group);
   9301         if (BCM_E_EXISTS != rv) {
   9302             continue;
   9303         }
   9304 
   9305         rv = bcm_tr3_oam_group_destroy(unit, group);
   9306         if (BCM_FAILURE(rv)) {
   9307             _BCM_OAM_UNLOCK(oc);
   9308             LOG_ERROR(BSL_LS_BCM_OAM,
   9309                       (BSL_META_U(unit,
   9310                                   "OAM Error: Group destroy failed "
   9311                                    "(GID=%d) - %s.\n"), group, bcm_errmsg(rv)));
   9312             return (rv);
   9313         }
   9314     }
   9315 
   9316     _BCM_OAM_UNLOCK(oc);
   9317 
   9318 #ifdef BCM_WARM_BOOT_SUPPORT
   9319     SOC_CONTROL_LOCK(unit);                                                      
   9320     SOC_CONTROL(unit)->scache_dirty = 1;
   9321     SOC_CONTROL_UNLOCK(unit);
   9322 #endif
   9323 
   9324     return (BCM_E_NONE);
   9325 }
   9326 
   9327 /*
   9328  * Function:
   9329  *     bcm_tr3_oam_group_traverse
   9330  * Purpose:
   9331  *     Traverse the entire set of OAM groups, calling a specified
   9332  *     callback for each one
   9333  * Parameters:
   9334  *     unit  - (IN) BCM device number
   9335  *     cb        - (IN) Pointer to call back function.
   9336  *     user_data - (IN) Pointer to user supplied data.
   9337  * Returns:
   9338  *     BCM_E_XXX
   9339  */
   9340 int
   9341 bcm_tr3_oam_group_traverse(int unit, bcm_oam_group_traverse_cb cb,
   9342                            void *user_data)
   9343 {
   9344     _bcm_oam_control_t    *oc;        /* OAM control structure pointer. */
   9345     bcm_oam_group_info_t  group_info; /* Group information to be set.   */
   9346     bcm_oam_group_t       grp_idx;    /* MA Group index.                */
   9347     _bcm_oam_group_data_t *group_p;   /* Pointer to group list.         */
   9348     int                   rv;         /* Operation return status.       */
   9349 
   9350     if (NULL == cb) {
   9351         return (BCM_E_PARAM);
   9352     }
   9353 
   9354     /* Get device OAM control structure handle. */
   9355     BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc));
   9356 
   9357     _BCM_OAM_LOCK(oc);
   9358 
   9359     /* Initialize to group array pointer. */
   9360     group_p = oc->group_info;
   9361 
   9362     for (grp_idx = 0; grp_idx < oc->group_count; grp_idx++) {
   9363 
   9364         /* Check if the group is in use. */
   9365         if (BCM_E_EXISTS
   9366             == shr_idxres_list_elem_state(oc->group_pool, grp_idx)) {
   9367 
   9368             /* Initialize the group information structure. */
   9369             bcm_oam_group_info_t_init(&group_info);
   9370 
   9371             /* Retrieve group information and set in group_info structure. */
   9372             rv = _bcm_tr3_oam_get_group(unit, grp_idx, group_p, &group_info);
   9373             if (BCM_FAILURE(rv)) {
   9374                 _BCM_OAM_UNLOCK(oc);
   9375                 LOG_ERROR(BSL_LS_BCM_OAM,
   9376                           (BSL_META_U(unit,
   9377                                       "OAM Error: _bcm_tr3_oam_get_group "
   9378                                        "(GID=%d) - %s.\n"), grp_idx, bcm_errmsg(rv)));
   9379                 return (rv);
   9380             }
   9381 
   9382             /* Call the user call back routine with group information. */
   9383             rv = cb(unit, &group_info, user_data);
   9384             if (BCM_FAILURE(rv)) {
   9385                 _BCM_OAM_UNLOCK(oc);
   9386                 LOG_ERROR(BSL_LS_BCM_OAM,
   9387                           (BSL_META_U(unit,
   9388                                       "OAM Error: User call back routine "
   9389                                        "(GID=%d) - %s.\n"), grp_idx, bcm_errmsg(rv)));
   9390                 return (rv);
   9391             }
   9392         }
   9393     }
   9394 
   9395     _BCM_OAM_UNLOCK(oc);
   9396 
   9397     return (BCM_E_NONE);
   9398 }
   9399 
   9400 /*
   9401  * Function:
   9402  *     bcm_tr3_oam_endpoint_create
   9403  * Purpose:
   9404  *     Create or replace an OAM endpoint object
   9405  * Parameters:
   9406  *     unit          - (IN) BCM device number
   9407  *     endpoint_info - (IN/OUT) Pointer to endpoint information buffer.
   9408  * Returns:
   9409  *      BCM_E_XXX
   9410  */
   9411 int
   9412 bcm_tr3_oam_endpoint_create(int unit, bcm_oam_endpoint_info_t *endpoint_info)
   9413 {
   9414     _bcm_oam_hash_data_t *hash_data = NULL; /* Endpoint hash data pointer.  */
   9415     _bcm_oam_hash_data_t h_data_stored;     /* Stored hash data.            */
   9416     _bcm_oam_hash_key_t  hash_key;          /* Hash Key buffer.             */
   9417     int                  ep_req_index;      /* Requested endpoint index.    */
   9418     int                  rv;                /* Operation return status.     */
   9419     _bcm_oam_control_t   *oc;               /* Pointer to OAM control       */
   9420                                             /* structure.                   */
   9421     uint32               sglp = 0;          /* Source global logical port.  */
   9422     uint32               dglp = 0;          /* Dest global logical port.    */
   9423     int                  mep_ccm_tx = 0;    /* Endpoint CCM Tx status.      */
   9424     int                  mep_ccm_rx = 0;    /* Endpoint CCM Rx status.      */
   9425     int                  remote = 0;        /* Remote endpoint status.      */
   9426     bcm_gport_t          tx_gport;
   9427     bcm_trunk_t          trunk_id = BCM_TRUNK_INVALID;
   9428 
   9429 
   9430     LOG_DEBUG(BSL_LS_BCM_OAM,
   9431               (BSL_META_U(unit,
   9432                           "OAM Info: bcm_tr3_oam_endpoint_create "
   9433                            "Endpoint ID=%d.\n"), endpoint_info->id));
   9434 
   9435     /* Validate input parameter. */
   9436     if (NULL == endpoint_info) {
   9437         return (BCM_E_PARAM);
   9438     }
   9439 
   9440     /* Get OAM Control Structure. */
   9441     BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc));
   9442 
   9443     _BCM_OAM_LOCK(oc);
   9444 
   9445 #if defined(KEY_PRINT)
   9446     _bcm_oam_hash_key_print(&hash_key);
   9447 #endif
   9448 
   9449     /* Calculate the hash key for given enpoint input parameters. */
   9450     _bcm_oam_ep_hash_key_construct(unit, oc, endpoint_info, &hash_key);
   9451 
   9452     /* Validate endpoint input parameters. */
   9453     rv = _bcm_tr3_oam_endpoint_params_validate(unit, oc, &hash_key,
   9454                                                endpoint_info);
   9455     if (BCM_FAILURE(rv)) {
   9456         LOG_ERROR(BSL_LS_BCM_OAM,
   9457                   (BSL_META_U(unit,
   9458                               "OAM Error: (EP=%d) - %s.\n"),
   9459                    endpoint_info->id, bcm_errmsg(rv)));
   9460         _BCM_OAM_UNLOCK(oc);
   9461         return (rv);
   9462     }
   9463 
   9464     /* Get MEP CCM Tx status. */
   9465     mep_ccm_tx
   9466         = ((endpoint_info->ccm_period != BCM_OAM_ENDPOINT_CCM_PERIOD_DISABLED)
   9467             ? 1 : 0);
   9468 
   9469     /* Get MEP CCM Rx status. */
   9470     mep_ccm_rx
   9471         = ((endpoint_info->flags & _BCM_OAM_EP_RX_ENABLE) ? 1 : 0);
   9472 
   9473     /* Get MEP remote endpoint status. */
   9474     remote = (endpoint_info->flags & BCM_OAM_ENDPOINT_REMOTE) ? 1 : 0;
   9475 
   9476     if(soc_feature(unit, soc_feature_bhh)) {
   9477 #if defined(BCM_TRIUMPH3_SUPPORT) && defined(INCLUDE_BHH)
   9478         if((endpoint_info->type == bcmOAMEndpointTypeBHHMPLS) ||
   9479            (endpoint_info->type == bcmOAMEndpointTypeBHHMPLSVccv))
   9480         {
   9481             if ((oc->ukernel_not_ready == 1) && 
   9482                     (!(endpoint_info->flags2 & BCM_OAM_ENDPOINT_FLAGS2_REDIRECT_TO_CPU))){
   9483                 LOG_ERROR(BSL_LS_BCM_OAM,
   9484                           (BSL_META_U(unit,
   9485                                       "OAM(unit %d) Error: BTE(ukernel) "
   9486                                       "not ready.\n"), unit));
   9487                 _BCM_OAM_UNLOCK(oc);
   9488                 return (BCM_E_INIT);
   9489             }
   9490 
   9491             rv = bcm_tr3_oam_bhh_endpoint_create(unit, endpoint_info, &hash_key);
   9492             if (BCM_FAILURE(rv)) {
   9493                 LOG_ERROR(BSL_LS_BCM_OAM,
   9494                           (BSL_META_U(unit,
   9495                                       "OAM Error: BHH Endpoint create (EP=%d) - %s.\n"),
   9496                            endpoint_info->id, bcm_errmsg(rv)));
   9497             }
   9498             _BCM_OAM_UNLOCK(oc);
   9499 
   9500             return (rv);
   9501         }
   9502 #endif /* INCLUDE_BHH */
   9503     }
   9504 
   9505     /* Resolve given endpoint gport value to Source GLP and Dest GLP values. */
   9506     rv = _bcm_tr3_oam_endpoint_gport_resolve(unit, endpoint_info, &sglp,
   9507                                              &dglp, &trunk_id, &tx_gport);
   9508     if (BCM_FAILURE(rv)) {
   9509         LOG_ERROR(BSL_LS_BCM_OAM,
   9510                 (BSL_META_U(unit,
   9511                             "OAM Error: Gport resolve (EP=%d) - %s.\n"),
   9512                  endpoint_info->id, bcm_errmsg(rv)));
   9513         _BCM_OAM_UNLOCK(oc);
   9514         return (rv);
   9515     }
   9516 
   9517     /* Replace an existing endpoint. */
   9518     if (endpoint_info->flags & BCM_OAM_ENDPOINT_REPLACE) {
   9519         
   9520         rv = _bcm_tr3_oam_endpoint_destroy(unit, endpoint_info->id);
   9521         if (BCM_FAILURE(rv)) {
   9522             LOG_ERROR(BSL_LS_BCM_OAM,
   9523                       (BSL_META_U(unit,
   9524                                   "OAM Error: Endpoint destroy (EP=%d) - %s.\n"),
   9525                        endpoint_info->id, bcm_errmsg(rv)));
   9526             _BCM_OAM_UNLOCK(oc);
   9527             return (rv);
   9528         }
   9529     }
   9530 
   9531     /* Create a new endpoint with the requested ID. */
   9532     if (endpoint_info->flags & BCM_OAM_ENDPOINT_WITH_ID) {
   9533         ep_req_index = endpoint_info->id;
   9534 
   9535         rv = shr_idxres_list_reserve(oc->mep_pool, ep_req_index,
   9536                 ep_req_index);
   9537         if (BCM_FAILURE(rv)) {
   9538             LOG_ERROR(BSL_LS_BCM_OAM,
   9539                     (BSL_META_U(unit,
   9540                                 "OAM Error: Endpoint reserve (EP=%d) - %s.\n"),
   9541                      endpoint_info->id, bcm_errmsg(rv)));
   9542             _BCM_OAM_UNLOCK(oc);
   9543             return ((rv == BCM_E_RESOURCE) ? BCM_E_EXISTS : rv);
   9544         }
   9545     } else {
   9546 
   9547             /* Allocate the next available endpoint index. */
   9548             rv = shr_idxres_list_alloc(oc->mep_pool,
   9549                                    (shr_idxres_element_t *)&ep_req_index);
   9550             if (BCM_FAILURE(rv)) {
   9551                 LOG_ERROR(BSL_LS_BCM_OAM,
   9552                           (BSL_META_U(unit,
   9553                                       "OAM Error: Endpoint alloc failed - %s.\n"),
   9554                            bcm_errmsg(rv)));
   9555                 _BCM_OAM_UNLOCK(oc);
   9556                 return (rv);
   9557             }
   9558         /* Set the allocated endpoint id value. */
   9559         endpoint_info->id =  ep_req_index;
   9560     }
   9561 
   9562     /* Get the hash data pointer where the data is to be stored. */
   9563     hash_data = &oc->oam_hash_data[ep_req_index];
   9564 
   9565     /* Clear the hash data element contents before storing the values. */
   9566     _BCM_OAM_HASH_DATA_CLEAR(hash_data);
   9567     hash_data->type = endpoint_info->type;
   9568     hash_data->ep_id = endpoint_info->id;
   9569     hash_data->is_remote = remote;
   9570     hash_data->local_tx_enabled = mep_ccm_tx;
   9571     hash_data->local_rx_enabled = mep_ccm_rx;
   9572     hash_data->group_index = endpoint_info->group;
   9573     hash_data->name  = endpoint_info->name;
   9574     hash_data->level = endpoint_info->level;
   9575     hash_data->vlan = endpoint_info->vlan;
   9576     hash_data->gport = endpoint_info->gport;
   9577     hash_data->sglp = sglp;
   9578     hash_data->dglp = dglp;
   9579     hash_data->flags = endpoint_info->flags;
   9580     hash_data->opcode_flags = (endpoint_info->opcode_flags &
   9581             _BCM_TR3_OAM_OPCODE_MASK);
   9582     hash_data->period = endpoint_info->ccm_period;
   9583     hash_data->in_use = 1;
   9584     hash_data->fp_entry_tx = -1;
   9585     hash_data->fp_entry_rx = -1;
   9586     hash_data->fp_entry_trunk[0] = -1;
   9587     hash_data->ts_format = endpoint_info->timestamp_format;
   9588 
   9589     /* Initialize hardware index as invalid indices. */
   9590     hash_data->local_tx_index = _BCM_OAM_INVALID_INDEX;
   9591     hash_data->local_rx_index = _BCM_OAM_INVALID_INDEX;
   9592     hash_data->remote_index = _BCM_OAM_INVALID_INDEX;
   9593 
   9594     if (1 == remote) {
   9595         /* Allocate the next available index for RMEP table. */
   9596         rv = shr_idxres_list_alloc
   9597             (oc->rmep_pool,
   9598              (shr_idxres_element_t *)&hash_data->remote_index);
   9599         if (BCM_FAILURE(rv)) {
   9600             _BCM_OAM_UNLOCK(oc);
   9601             LOG_ERROR(BSL_LS_BCM_OAM,
   9602                     (BSL_META_U(unit,
   9603                                 "OAM Error: RMEP index alloc failed EP:%d %s.\n"),
   9604                      endpoint_info->id, bcm_errmsg(rv)));
   9605             return (rv);
   9606         }
   9607     } else {
   9608 
   9609         /* Allocate the next available index for LMEP table. */
   9610         if (1 == mep_ccm_tx) {
   9611             rv = shr_idxres_list_alloc
   9612                 (oc->lmep_pool,
   9613                  (shr_idxres_element_t *)&hash_data->local_tx_index);
   9614             if (BCM_FAILURE(rv)) {
   9615                 _BCM_OAM_UNLOCK(oc);
   9616                 LOG_ERROR(BSL_LS_BCM_OAM,
   9617                         (BSL_META_U(unit,
   9618                                     "OAM Error: LMEP Tx index alloc failed EP:%d "
   9619                                     "%s.\n"), endpoint_info->id, bcm_errmsg(rv)));
   9620                 return (rv);
   9621             }
   9622         }
   9623 
   9624         /* Allocate the next available index for MA_INDEX table. */
   9625         if (1 == mep_ccm_rx) {
   9626             rv =  _bcm_oam_rx_endpoint_reserve(unit, endpoint_info);
   9627             if (BCM_FAILURE(rv)) {
   9628                 if (1 == mep_ccm_tx) {
   9629                     /* Return Tx index to the LMEP pool. */
   9630                     shr_idxres_list_free(oc->lmep_pool,
   9631                             hash_data->local_tx_index);
   9632                 }
   9633 
   9634                 /* Return endpoint index to MEP pool. */
   9635                 shr_idxres_list_free(oc->mep_pool, endpoint_info->id);
   9636 
   9637                 _BCM_OAM_UNLOCK(oc);
   9638                 LOG_ERROR(BSL_LS_BCM_OAM,
   9639                         (BSL_META_U(unit,
   9640                                     "OAM Error: LMEP Rx index alloc failed EP:%d "
   9641                                     "%s.\n"), endpoint_info->id, bcm_errmsg(rv)));
   9642                 return (rv);
   9643             }
   9644         }
   9645     }
   9646 
   9647 
   9648     rv = shr_htb_insert(oc->ma_mep_htbl, hash_key, hash_data);
   9649     if (BCM_FAILURE(rv)) {
   9650         LOG_ERROR(BSL_LS_BCM_OAM,
   9651                 (BSL_META_U(unit,
   9652                             "OAM Error: Hash table insert failed EP=%d %s.\n"),
   9653                  endpoint_info->id, bcm_errmsg(rv)));
   9654         _BCM_OAM_UNLOCK(oc);
   9655         return (rv);
   9656     }
   9657 
   9658     if (1 == remote) {
   9659         rv = _bcm_oam_remote_mep_hw_set(unit, endpoint_info);
   9660         if (BCM_FAILURE(rv)) {
   9661             LOG_DEBUG(BSL_LS_BCM_OAM,
   9662                       (BSL_META_U(unit,
   9663                                   "OAM Error: Remote MEP set failed EP=%d %s.\n"),
   9664                        endpoint_info->id, bcm_errmsg(rv)));
   9665             /*
   9666              * If not a replace operation, return the allocated indices
   9667              * to free pool.
   9668              */
   9669             if (!(endpoint_info->flags & BCM_OAM_ENDPOINT_REPLACE)) {
   9670                 shr_idxres_list_free(oc->mep_pool, endpoint_info->id);
   9671                 shr_idxres_list_free(oc->rmep_pool, hash_data->remote_index);
   9672 
   9673                 /* Return entry to hash data free pool. */
   9674                 shr_htb_find(oc->ma_mep_htbl, hash_key,
   9675                             (shr_htb_data_t *) &h_data_stored, 1);
   9676 
   9677                 /* Clear contents of hash data element. */
   9678                 _BCM_OAM_HASH_DATA_CLEAR(hash_data);
   9679             }
   9680             _BCM_OAM_UNLOCK(oc);
   9681             return (rv);
   9682         }
   9683     } else {
   9684         if (mep_ccm_tx) {
   9685 
   9686             rv = _bcm_oam_local_tx_mep_hw_set(unit, endpoint_info);
   9687 
   9688 
   9689             if (BCM_FAILURE(rv)) {
   9690                 LOG_ERROR(BSL_LS_BCM_OAM,
   9691                           (BSL_META_U(unit,
   9692                                       "OAM Error: Tx config failed for EP=%d %s.\n"),
   9693                            endpoint_info->id, bcm_errmsg(rv)));
   9694                 /*
   9695                  * If not a replace operation, return the allocated indices
   9696                  * to free pool.
   9697                  */
   9698                 if (!(endpoint_info->flags & BCM_OAM_ENDPOINT_REPLACE)) {
   9699                     shr_idxres_list_free(oc->mep_pool, endpoint_info->id);
   9700                     shr_idxres_list_free(oc->lmep_pool,
   9701                                          hash_data->local_tx_index);
   9702 
   9703                     /* Return entry to hash data entry to free pool. */
   9704                     shr_htb_find(oc->ma_mep_htbl, hash_key,
   9705                                  (shr_htb_data_t *)&h_data_stored, 1);
   9706 
   9707                     /* Clear contents of hash data element. */
   9708                     _BCM_OAM_HASH_DATA_CLEAR(hash_data);
   9709                 }
   9710                 _BCM_OAM_UNLOCK(oc);
   9711                 return (rv);
   9712             }
   9713         }
   9714 
   9715         if (mep_ccm_rx) {
   9716 
   9717             rv = _bcm_oam_local_rx_mep_hw_set(unit, endpoint_info);
   9718 
   9719 
   9720             if (BCM_FAILURE(rv)) {
   9721                 LOG_ERROR(BSL_LS_BCM_OAM,
   9722                           (BSL_META_U(unit,
   9723                                       "OAM Error: Rx config failed for EP=%d %s.\n"),
   9724                            endpoint_info->id, bcm_errmsg(rv)));
   9725                 /*
   9726                  * If not a replace operation, return the allocated indices
   9727                  * to free pool.
   9728                  */
   9729                 if (!(endpoint_info->flags & BCM_OAM_ENDPOINT_REPLACE)) {
   9730                     shr_idxres_list_free(oc->ma_idx_pool,
   9731                                          hash_data->local_rx_index);
   9732 
   9733                     shr_idxres_list_free(oc->mep_pool, endpoint_info->id);
   9734 
   9735                     if (1 == mep_ccm_tx) {
   9736                         shr_idxres_list_free(oc->lmep_pool,
   9737                                              hash_data->local_tx_index);
   9738                     }
   9739 
   9740                     /* Return entry to hash data entry to free pool. */
   9741                     shr_htb_find(oc->ma_mep_htbl, hash_key,
   9742                                  (shr_htb_data_t *)&h_data_stored, 1);
   9743 
   9744                     /* Clear contents of hash data element. */
   9745                     _BCM_OAM_HASH_DATA_CLEAR(hash_data);
   9746 
   9747                 }
   9748 
   9749                 /* Clear contents of hash data element. */
   9750                 _BCM_OAM_UNLOCK(oc);
   9751                 return (rv);
   9752             } else {
   9753                 if ( endpoint_info->flags & 
   9754                      (BCM_OAM_ENDPOINT_LOSS_MEASUREMENT | 
   9755                       BCM_OAM_ENDPOINT_DELAY_MEASUREMENT)) {
   9756                       
   9757                     rv  = _bcm_tr3_oam_loss_delay_measurement_add(unit, 
   9758                                                 oc, hash_data, endpoint_info);
   9759                     if (BCM_FAILURE(rv)) {
   9760                         LOG_ERROR(BSL_LS_BCM_OAM,
   9761                                   (BSL_META_U(unit,
   9762                                               "OAM Error: FP insert failed for "
   9763                                               "LM DM over EP=%d %s.\n"), endpoint_info->id, 
   9764                                    bcm_errmsg(rv)));
   9765                         
   9766                         /*
   9767                          * If not a replace operation, return the allocated 
   9768                          * indices to free pool.
   9769                          */
   9770                         if (!(endpoint_info->flags & BCM_OAM_ENDPOINT_REPLACE)){
   9771                             shr_idxres_list_free(oc->ma_idx_pool,
   9772                                                  hash_data->local_rx_index);
   9773 
   9774                            shr_idxres_list_free(oc->mep_pool,endpoint_info->id);
   9775 
   9776                             if (1 == mep_ccm_tx) {
   9777                                 shr_idxres_list_free(oc->lmep_pool,
   9778                                                      hash_data->local_tx_index);
   9779                             }
   9780 
   9781                             /* Return entry to hash data entry to free pool. */
   9782                             shr_htb_find(oc->ma_mep_htbl, hash_key,
   9783                                          (shr_htb_data_t *)&h_data_stored, 1);
   9784 
   9785                             /* Clear contents of hash data element. */
   9786                             _BCM_OAM_HASH_DATA_CLEAR(hash_data);
   9787                         }
   9788 
   9789 
   9790                         /* Unlock OAM Control Structure. */
   9791                         _BCM_OAM_UNLOCK(oc);
   9792                         return (rv);
   9793                     }
   9794                 }
   9795             }
   9796         }
   9797     }
   9798 
   9799     rv = _bcm_oam_group_ep_list_add(unit, endpoint_info->group,
   9800             endpoint_info->id);
   9801     if (BCM_FAILURE(rv)) {
   9802         LOG_ERROR(BSL_LS_BCM_OAM,
   9803                   (BSL_META_U(unit,
   9804                               "OAM Error: Tx config failed for EP=%d %s.\n"),
   9805                    endpoint_info->id, bcm_errmsg(rv)));
   9806         _BCM_OAM_UNLOCK(oc);
   9807         return (rv);
   9808     }
   9809 
   9810     _BCM_OAM_UNLOCK(oc);
   9811 
   9812 /*SDK-147457:HW WAR to fix the issue of wrong LMEP index being written
   9813   while deleting and adding same MEP in a loop */
   9814 #ifdef BCM_HURRICANE2_SUPPORT
   9815     sal_usleep(3400);
   9816 #endif /* BCM_HURRICANE2_SUPPORT */
   9817 
   9818 #ifdef BCM_WARM_BOOT_SUPPORT
   9819     SOC_CONTROL_LOCK(unit);
   9820     SOC_CONTROL(unit)->scache_dirty = 1;
   9821     SOC_CONTROL_UNLOCK(unit);
   9822 #endif
   9823 
   9824     return (BCM_E_NONE);
   9825 }
   9826 
   9827  /*
   9828  * Function:
   9829  *      bcm_tr3_oam_endpoint_get
   9830  * Purpose:
   9831  *      Get an OAM endpoint object
   9832  * Parameters:
   9833  *     unit          - (IN) BCM device number
   9834  *     endpoint      - (IN) Endpoint ID
   9835  *     endpoint_info - (OUT) Pointer to OAM endpoint information buffer.
   9836  * Returns:
   9837  *     BCM_E_XXX
   9838  */
   9839 int
   9840 bcm_tr3_oam_endpoint_get(int unit, bcm_oam_endpoint_t endpoint,
   9841                          bcm_oam_endpoint_info_t *endpoint_info)
   9842 {
   9843     _bcm_oam_hash_data_t *h_data_p;  /* Pointer to endpoint hash data.    */
   9844     int                  rv;         /* Operation return status.          */
   9845     _bcm_oam_control_t   *oc;        /* Pointer to OAM control structure. */
   9846     rmep_entry_t         rmep_entry; /* Remote MEP entry buffer.          */
   9847     lmep_entry_t         lmep_entry; /* Local MEP entry buffer.           */
   9848     lmep_da_entry_t      dmac_entry; /* Local MEP entry buffer.           */
   9849     uint8                pri_map[BCM_OAM_INTPRI_MAX];
   9850     int                  i;
   9851 #if defined(BCM_TRIUMPH3_SUPPORT) && defined(INCLUDE_BHH)
   9852     bhh_sdk_msg_ctrl_sess_get_t msg;
   9853     uint8 *buffer, *buffer_ptr;
   9854     uint16 buffer_len, reply_len;
   9855     int sess_id = 0;
   9856     bcm_l3_egress_t l3_egress;
   9857     bcm_l3_intf_t l3_intf;
   9858 #endif
   9859 #ifdef BCM_HURRICANE2_SUPPORT
   9860     uint32  rval = 0;
   9861     uint8   tx_disable = 0;
   9862 #endif /* BCM_HURRICANE2_SUPPORT */
   9863 
   9864     if (NULL == endpoint_info) {
   9865         return (BCM_E_PARAM);
   9866     }
   9867 
   9868     BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc));
   9869 
   9870     /* Validate endpoint index value. */
   9871     _BCM_OAM_EP_INDEX_VALIDATE(endpoint);
   9872 
   9873     _BCM_OAM_LOCK(oc);
   9874 
   9875     h_data_p =  &oc->oam_hash_data[endpoint];
   9876     if (NULL == h_data_p) {
   9877         _BCM_OAM_UNLOCK(oc);
   9878         return (BCM_E_INTERNAL);
   9879     }
   9880 
   9881     if (0 == h_data_p->in_use) {
   9882         _BCM_OAM_UNLOCK(oc);
   9883         return (BCM_E_NOT_FOUND);
   9884     }
   9885     LOG_DEBUG(BSL_LS_BCM_OAM,
   9886               (BSL_META_U(unit,
   9887                           "OAM Info: Endpoint (EP=%d) remote=%d local_tx=%d"
   9888                            "local_tx_idx=%d local_rx_en=%d local_rx_idx=%d\n"),
   9889                endpoint, h_data_p->is_remote, h_data_p->local_tx_enabled,
   9890                h_data_p->local_tx_index, h_data_p->local_rx_enabled,
   9891                h_data_p->local_rx_index));
   9892 
   9893     if (bcmOAMEndpointTypeEthernet == h_data_p->type) {
   9894         if (1 == h_data_p->is_remote) {
   9895             sal_memset(&rmep_entry, 0, sizeof(rmep_entry_t));
   9896 
   9897             /* Get hardware table entry information.  */
   9898             rv = READ_RMEPm(unit, MEM_BLOCK_ANY, h_data_p->remote_index,
   9899                             &rmep_entry);
   9900             if (BCM_FAILURE(rv)) {
   9901                 LOG_ERROR(BSL_LS_BCM_OAM,
   9902                           (BSL_META_U(unit,
   9903                                       "OAM Error: RMEP table read failed for"
   9904                                       " EP=%d %s.\n"), endpoint, bcm_errmsg(rv)));
   9905                 _BCM_OAM_UNLOCK(oc);
   9906                 return (rv);
   9907             }
   9908 
   9909             rv = _bcm_tr3_oam_read_clear_faults(unit, h_data_p->remote_index,
   9910                                                 RMEPm, (uint32 *) &rmep_entry,
   9911                                                 (void *) endpoint_info);
   9912             if (BCM_FAILURE(rv)) {
   9913                 LOG_ERROR(BSL_LS_BCM_OAM,
   9914                           (BSL_META_U(unit,
   9915                                       "OAM Error: RMEP table read failed for"
   9916                                       " EP=%d %s.\n"), endpoint, bcm_errmsg(rv)));
   9917                 _BCM_OAM_UNLOCK(oc);
   9918                 return (rv);
   9919             }
   9920             if (endpoint_info->flags2 & BCM_OAM_ENDPOINT_FLAGS2_GET_FAULTS_ONLY) {
   9921                 endpoint_info->flags2 &= ~BCM_OAM_ENDPOINT_FLAGS2_GET_FAULTS_ONLY;
   9922                 _BCM_OAM_UNLOCK(oc);
   9923                 return BCM_E_NONE;
   9924             }
   9925         } else {
   9926             if (1 == h_data_p->local_tx_enabled) {
   9927                 sal_memset(&lmep_entry, 0, sizeof(lmep_entry_t));
   9928 #ifdef BCM_HURRICANE2_SUPPORT
   9929                 rv = _bcm_oam_modify_oam_tx_control (unit, &rval, 1,
   9930                                                      &tx_disable);
   9931                 if (BCM_FAILURE(rv)) {
   9932                     LOG_ERROR(BSL_LS_BCM_OAM,
   9933                             (BSL_META_U(unit,
   9934                            "OAM Error: in _bcm_oam_modify_oam_tx_control \n")));
   9935                     return (rv);
   9936                 }
   9937 #endif /* BCM_HURRICANE2_SUPPORT */
   9938                 /* Get hardware table entry information.  */
   9939                 rv = READ_LMEPm(unit, MEM_BLOCK_ANY, h_data_p->local_tx_index,
   9940                                 &lmep_entry);
   9941                 if (BCM_FAILURE(rv)) {
   9942                     LOG_ERROR(BSL_LS_BCM_OAM,
   9943                               (BSL_META_U(unit,
   9944                                           "OAM Error: LMEP table read failed for"
   9945                                           " EP=%d %s.\n"), endpoint, bcm_errmsg(rv)));
   9946                     _BCM_OAM_UNLOCK(oc);
   9947                     return (rv);
   9948                 }
   9949 
   9950                 soc_LMEPm_mac_addr_get(unit, &lmep_entry, SAf,
   9951                                        endpoint_info->src_mac_address);
   9952                 endpoint_info->pkt_pri = soc_LMEPm_field32_get(unit,
   9953                                                                &lmep_entry,
   9954                                                                LMEP_PRIORITYf);
   9955                 endpoint_info->int_pri = soc_LMEPm_field32_get(unit,
   9956                                                                &lmep_entry,
   9957                                                                INT_PRIf);
   9958                 endpoint_info->port_state = (soc_LMEPm_field32_get(unit,
   9959                                                 &lmep_entry, PORT_TLVf)
   9960                                                 ? BCM_OAM_PORT_TLV_UP
   9961                                                     : BCM_OAM_PORT_TLV_BLOCKED);
   9962                 endpoint_info->interface_state = soc_LMEPm_field32_get(unit,
   9963                                                     &lmep_entry, INTERFACE_TLVf);
   9964 
   9965                 sal_memset(&dmac_entry, 0, sizeof(lmep_da_entry_t));
   9966 
   9967                 /* Get hardware table entry information. */
   9968                 rv = READ_LMEP_DAm(unit, MEM_BLOCK_ANY, h_data_p->local_tx_index,
   9969                                    &dmac_entry);
   9970 #ifdef BCM_HURRICANE2_SUPPORT
   9971                 if (tx_disable) {
   9972                     rv = _bcm_oam_modify_oam_tx_control (unit, &rval, 0,
   9973                                                          &tx_disable);
   9974                     if (BCM_FAILURE(rv)) {
   9975                         LOG_ERROR(BSL_LS_BCM_OAM,
   9976                                 (BSL_META_U(unit,
   9977                            "OAM Error: in _bcm_oam_modify_oam_tx_control \n")));
   9978                         return (rv);
   9979                     }
   9980                 }
   9981 #endif /* BCM_HURRICANE2_SUPPORT */
   9982                 if (BCM_FAILURE(rv)) {
   9983                     LOG_ERROR(BSL_LS_BCM_OAM,
   9984                               (BSL_META_U(unit,
   9985                                           "OAM Error: LMEP_DA table read failed for"
   9986                                           " EP=%d %s.\n"), endpoint, bcm_errmsg(rv)));
   9987                     _BCM_OAM_UNLOCK(oc);
   9988                     return (rv);
   9989                 }
   9990 
   9991 #ifdef BCM_HURRICANE2_SUPPORT
   9992                 if (SOC_IS_HURRICANE2(unit) || SOC_IS_GREYHOUND(unit) ||
   9993                     SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) {
   9994                     soc_mem_mac_addr_get(unit, LMEP_DAm, &dmac_entry, MACDAf,
   9995                                          endpoint_info->dst_mac_address);
   9996  
   9997                 } else 
   9998 #endif /* BCM_HURRICANE2_SUPPORT */
   9999                 {
  10000                     soc_mem_mac_addr_get(unit, LMEP_DAm, &dmac_entry, DAf,
  10001                                          endpoint_info->dst_mac_address);
  10002                 }
  10003             }
  10004         }
  10005     }
  10006     else if (soc_feature(unit, soc_feature_bhh) && 
  10007             ((h_data_p->type == bcmOAMEndpointTypeBHHMPLS) || 
  10008              (h_data_p->type == bcmOAMEndpointTypeBHHMPLSVccv))) {
  10009 #if defined(BCM_TRIUMPH3_SUPPORT) && defined(INCLUDE_BHH)
  10010         sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(endpoint);
  10011         rv = _bcm_tr3_oam_bhh_msg_send_receive(unit,
  10012                                                MOS_MSG_SUBCLASS_BHH_SESS_GET,
  10013                                                sess_id, 0,
  10014                                                MOS_MSG_SUBCLASS_BHH_SESS_GET_REPLY,
  10015                                                &reply_len, _BHH_UC_MSG_TIMEOUT_USECS);
  10016         if (BCM_FAILURE(rv)) {
  10017             LOG_ERROR(BSL_LS_BCM_OAM,
  10018                       (BSL_META_U(unit,
  10019                                   "OAM Error: ukernel msg failed for"
  10020                                   " EP=%d %s.\n"), endpoint, bcm_errmsg(rv)));
  10021             _BCM_OAM_UNLOCK(oc);
  10022             return (rv);
  10023         }
  10024 
  10025         /* Pack control message data into DMA buffer */
  10026         buffer = oc->dma_buffer;
  10027         buffer_ptr = bhh_sdk_msg_ctrl_sess_get_unpack(buffer, &msg);
  10028         buffer_len = buffer_ptr - buffer;
  10029 
  10030         if (reply_len != buffer_len) {
  10031             rv = BCM_E_INTERNAL;
  10032             LOG_ERROR(BSL_LS_BCM_OAM,
  10033                       (BSL_META_U(unit,
  10034                                   "OAM Error: ukernel msg failed for"
  10035                                   " EP=%d %s.\n"), endpoint, bcm_errmsg(rv)));
  10036             _BCM_OAM_UNLOCK(oc);
  10037             return (rv);
  10038         } else {
  10039             endpoint_info->int_pri = msg.tx_cos;
  10040             endpoint_info->pkt_pri = msg.tx_pri;
  10041             endpoint_info->mpls_exp = msg.priority;
  10042 
  10043             if(endpoint_info->flags & BCM_OAM_ENDPOINT_REMOTE){
  10044                 endpoint_info->name       = msg.remote_mep_id;
  10045                 endpoint_info->ccm_period = msg.remote_period;
  10046             } else {
  10047                 endpoint_info->name       = msg.mep_id;
  10048                 endpoint_info->ccm_period = msg.local_period;
  10049             }
  10050 
  10051             if(msg.fault_flags & BHH_BTE_EVENT_CCM_TIMEOUT){
  10052                 endpoint_info->faults |= BCM_OAM_BHH_FAULT_CCM_TIMEOUT;
  10053             }
  10054             if(msg.fault_flags & BHH_BTE_EVENT_CCM_RDI){
  10055                 endpoint_info->faults |= BCM_OAM_BHH_FAULT_CCM_RDI;
  10056             }
  10057             if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_LEVEL){
  10058                 endpoint_info->faults |=
  10059                     BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEG_LEVEL;
  10060             }
  10061             if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_ID){
  10062                 endpoint_info->faults |=
  10063                     BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEG_ID;
  10064             }
  10065             if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_MEP_ID){
  10066                 endpoint_info->faults |=
  10067                     BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEP_ID;
  10068             }
  10069             if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_PERIOD){
  10070                 endpoint_info->faults |=
  10071                     BCM_OAM_BHH_FAULT_CCM_UNKNOWN_PERIOD;
  10072             }
  10073             if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_PRIORITY){
  10074                 endpoint_info->faults |=
  10075                     BCM_OAM_BHH_FAULT_CCM_UNKNOWN_PRIORITY;
  10076             }
  10077             if(msg.fault_flags & BHH_BTE_EVENT_CSF_LOS) {
  10078                 endpoint_info->faults |= BCM_OAM_ENDPOINT_BHH_FAULT_CSF_LOS;
  10079             }
  10080             if(msg.fault_flags & BHH_BTE_EVENT_CSF_FDI) {
  10081                 endpoint_info->faults |= BCM_OAM_ENDPOINT_BHH_FAULT_CSF_FDI;
  10082             }
  10083             if(msg.fault_flags & BHH_BTE_EVENT_CSF_RDI) {
  10084                 endpoint_info->faults |= BCM_OAM_ENDPOINT_BHH_FAULT_CSF_RDI;
  10085             }
  10086         }
  10087 
  10088         endpoint_info->intf_id    = h_data_p->egress_if;
  10089         endpoint_info->cpu_qid    =  h_data_p->cpu_qid;
  10090         endpoint_info->mpls_label = h_data_p->label;
  10091         endpoint_info->gport      = h_data_p->gport;
  10092         endpoint_info->vpn        = h_data_p->vpn;
  10093         endpoint_info->vccv_type  = h_data_p->vccv_type;
  10094         endpoint_info->egress_label.label = h_data_p->egr_label;
  10095         endpoint_info->egress_label.exp = h_data_p->egr_label_exp;
  10096         endpoint_info->egress_label.ttl = h_data_p->egr_label_ttl;
  10097 
  10098         /*
  10099          * Get MAC address
  10100          */
  10101         bcm_l3_egress_t_init(&l3_egress);
  10102         bcm_l3_intf_t_init(&l3_intf);
  10103 
  10104         if (BCM_FAILURE
  10105             (bcm_esw_l3_egress_get(unit, h_data_p->egress_if, &l3_egress))) {
  10106             _BCM_OAM_UNLOCK(oc);
  10107             return (BCM_E_INTERNAL);
  10108         }
  10109 
  10110         l3_intf.l3a_intf_id = l3_egress.intf;
  10111         if (BCM_FAILURE(bcm_esw_l3_intf_get(unit, &l3_intf))) {
  10112             _BCM_OAM_UNLOCK(oc);
  10113             return (BCM_E_INTERNAL);
  10114         }
  10115 
  10116         sal_memcpy(endpoint_info->src_mac_address, l3_intf.l3a_mac_addr, _BHH_MAC_ADDR_LENGTH);
  10117 #else
  10118         _BCM_OAM_UNLOCK(oc);
  10119         return (BCM_E_UNAVAIL);
  10120 #endif /* INCLUDE_BHH */
  10121     }
  10122     else {
  10123         _BCM_OAM_UNLOCK(oc);
  10124         return (BCM_E_PARAM);
  10125     }
  10126 
  10127     /* BHH MEP Id & period already filled from uC msg */
  10128     if (!(h_data_p->type == bcmOAMEndpointTypeBHHMPLS ||
  10129           h_data_p->type == bcmOAMEndpointTypeBHHMPLSVccv)) {
  10130         endpoint_info->name = h_data_p->name;
  10131         endpoint_info->ccm_period = h_data_p->period;
  10132     }
  10133 
  10134     endpoint_info->id = endpoint;
  10135     endpoint_info->group = h_data_p->group_index;
  10136     endpoint_info->vlan = h_data_p->vlan;
  10137     endpoint_info->level = h_data_p->level;
  10138     endpoint_info->gport = h_data_p->gport;
  10139     endpoint_info->flags |= h_data_p->flags;
  10140     endpoint_info->flags &= ~(BCM_OAM_ENDPOINT_WITH_ID);
  10141     endpoint_info->opcode_flags = h_data_p->opcode_flags;
  10142     endpoint_info->type = h_data_p->type;
  10143     endpoint_info->trunk_index = h_data_p->trunk_index;
  10144 
  10145     if(h_data_p->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT) {
  10146         for(i = 0; i < BCM_OAM_INTPRI_MAX; i++) {
  10147             rv = READ_ING_SERVICE_PRI_MAPm(unit, MEM_BLOCK_ANY,
  10148                                            (h_data_p->pri_map_index *
  10149                                                         BCM_OAM_INTPRI_MAX) + i,
  10150                                            &pri_map);
  10151             if (SOC_FAILURE(rv)) {
  10152                 _BCM_OAM_UNLOCK(oc);
  10153                 return rv;
  10154             }
  10155             endpoint_info->pri_map[i] =
  10156                 soc_ING_SERVICE_PRI_MAPm_field32_get(unit, &pri_map, OFFSETf);
  10157         }
  10158         endpoint_info->pri_map_id = h_data_p->pri_map_index;
  10159     }
  10160 
  10161     _BCM_OAM_UNLOCK(oc);
  10162 /*SDK-147457:HW WAR to fix the issue of wrong LMEP index being written
  10163   while deleting and adding same MEP in a loop */
  10164 #ifdef BCM_HURRICANE2_SUPPORT
  10165     sal_usleep(3400);
  10166 #endif /* BCM_HURRICANE2_SUPPORT */
  10167 
  10168     return (BCM_E_NONE);
  10169 }
  10170 
  10171 
  10172 /*
  10173  * Function:
  10174  *     bcm_tr3_oam_endpoint_destroy
  10175  * Purpose:
  10176  *     Destroy an OAM endpoint object
  10177  * Parameters:
  10178  *     unit     - (IN) BCM device number
  10179  *     endpoint - (IN) Endpoint ID to destroy.
  10180  * result =s:
  10181  *     BCM_E_XXX
  10182  */
  10183 int
  10184 bcm_tr3_oam_endpoint_destroy(int unit, bcm_oam_endpoint_t endpoint)
  10185 {
  10186     _bcm_oam_control_t *oc; /* Pointer to OAM control structure. */
  10187     int rv;                 /* Operation return status.          */
  10188 
  10189     BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc));
  10190     /* Validate endpoint index value. */
  10191     _BCM_OAM_EP_INDEX_VALIDATE(endpoint);
  10192 
  10193     _BCM_OAM_LOCK(oc);
  10194 
  10195     rv = _bcm_tr3_oam_endpoint_destroy(unit, endpoint);
  10196     if (BCM_FAILURE(rv)) {
  10197         LOG_ERROR(BSL_LS_BCM_OAM,
  10198                   (BSL_META_U(unit,
  10199                               "OAM Error: Endpoint destroy EP=%d failed - "
  10200                               "%s.\n"), endpoint, bcm_errmsg(rv)));
  10201     }
  10202 
  10203     _BCM_OAM_UNLOCK(oc);
  10204     return (rv);
  10205 }
  10206 
  10207 /*
  10208  * Function:
  10209  *     bcm_tr3_oam_endpoint_destroy_all
  10210  * Purpose:
  10211  *     Destroy all OAM endpoint objects associated with a group.
  10212  * Parameters:
  10213  *     unit  - (IN) BCM device number
  10214  *     group - (IN) The OAM group whose endpoints should be destroyed
  10215  * Returns:
  10216  *     BCM_E_XXX
  10217  */
  10218 int
  10219 bcm_tr3_oam_endpoint_destroy_all(int unit, bcm_oam_group_t group)
  10220 {
  10221     _bcm_oam_control_t    *oc; /* Pointer to OAM control structure. */
  10222     int                   rv;  /* Operation return status.          */
  10223     _bcm_oam_group_data_t *g_info_p;
  10224 
  10225     /* Get OAM device control structure. */
  10226     BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc));
  10227 
  10228     /* Validate group index. */
  10229     _BCM_OAM_GROUP_INDEX_VALIDATE(group);
  10230 
  10231     _BCM_OAM_LOCK(oc);
  10232 
  10233     /* Check if the group is in use. */
  10234     rv = shr_idxres_list_elem_state(oc->group_pool, group);
  10235     if (BCM_E_EXISTS != rv) {
  10236         _BCM_OAM_UNLOCK(oc);
  10237         LOG_ERROR(BSL_LS_BCM_OAM,
  10238                   (BSL_META_U(unit,
  10239                               "OAM Error: Group ID=%d does not exist.\n"),
  10240                    group));
  10241         return (rv);
  10242     }
  10243 
  10244     /* Get the group data pointer. */
  10245     g_info_p = &oc->group_info[group];
  10246     rv = _bcm_tr3_oam_group_endpoints_destroy(unit, g_info_p);
  10247     if (BCM_FAILURE(rv)) {
  10248         LOG_ERROR(BSL_LS_BCM_OAM,
  10249                   (BSL_META_U(unit,
  10250                               "OAM Error: Group (GID=%d) endpoints destroy"
  10251                               " failed - %s.\n"), group, bcm_errmsg(rv)));
  10252         _BCM_OAM_UNLOCK(oc);
  10253         return (rv);
  10254     }
  10255     _BCM_OAM_UNLOCK(oc);
  10256     return (rv);
  10257 }
  10258 
  10259 /*
  10260  * Function:
  10261  *     bcm_tr3_oam_endpoint_traverse
  10262  * Purpose:
  10263  *     Traverse the set of OAM endpoints associated with the
  10264  *     specified group, calling a specified callback for each one
  10265  * Parameters:
  10266  *     unit      - (IN) BCM device number
  10267  *     group     - (IN) The OAM group whose endpoints should be traversed
  10268  *     cb        - (IN) A pointer to the callback function to call for each OAM
  10269  *                      endpoint in the specified group
  10270  *     user_data - (IN) Pointer to user data to supply in the callback
  10271  * Returns:
  10272  *      BCM_E_XXX
  10273  */
  10274 int
  10275 bcm_tr3_oam_endpoint_traverse(int unit, bcm_oam_group_t group,
  10276                               bcm_oam_endpoint_traverse_cb cb,
  10277                               void *user_data)
  10278 {
  10279     _bcm_oam_control_t      *oc; /* Pointer to OAM control structure. */
  10280     int                     rv;  /* Operation return status.          */
  10281     bcm_oam_endpoint_info_t ep_info;
  10282     _bcm_oam_hash_data_t    *h_data_p;
  10283     _bcm_oam_ep_list_t      *cur;
  10284     _bcm_oam_group_data_t   *g_info_p;
  10285 
  10286     /* Validate input parameter. */
  10287     if (NULL == cb) {
  10288         return (BCM_E_PARAM);
  10289     }
  10290 
  10291     /* Get OAM device control structure. */
  10292     BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc));
  10293 
  10294     /* Validate group index. */
  10295     _BCM_OAM_GROUP_INDEX_VALIDATE(group);
  10296 
  10297     _BCM_OAM_LOCK(oc);
  10298 
  10299     /* Check if the group is in use. */
  10300     rv = shr_idxres_list_elem_state(oc->group_pool, group);
  10301     if (BCM_E_EXISTS != rv) {
  10302         _BCM_OAM_UNLOCK(oc);
  10303         LOG_ERROR(BSL_LS_BCM_OAM,
  10304                   (BSL_META_U(unit,
  10305                               "OAM Error: Group ID=%d does not exist.\n"),
  10306                    group));
  10307         return (rv);
  10308     }
  10309 
  10310     /* Get the group data pointer. */
  10311     g_info_p = &oc->group_info[group];
  10312 
  10313     /* Get the endpoint list head pointer. */
  10314     cur = *(g_info_p->ep_list);
  10315     if (NULL == cur) {
  10316         _BCM_OAM_UNLOCK(oc);
  10317         LOG_DEBUG(BSL_LS_BCM_OAM,
  10318                   (BSL_META_U(unit,
  10319                               "OAM Info: No endpoints in group GID=%d.\n"),
  10320                    group));
  10321         return (BCM_E_NONE);
  10322     }
  10323 
  10324     /* Traverse from Head to Tail */
  10325     while (NULL != cur) {
  10326         h_data_p = cur->ep_data_p;
  10327         if (NULL == h_data_p) {
  10328             LOG_ERROR(BSL_LS_BCM_OAM,
  10329                       (BSL_META_U(unit,
  10330                                   "OAM Error: Group=%d endpoints access failed -"
  10331                                   " %s.\n"), group, bcm_errmsg(BCM_E_INTERNAL)));
  10332             _BCM_OAM_UNLOCK(oc);
  10333             return (BCM_E_INTERNAL);
  10334         }
  10335         bcm_oam_endpoint_info_t_init(&ep_info);
  10336 
  10337         rv = bcm_tr3_oam_endpoint_get(unit, h_data_p->ep_id, &ep_info);
  10338         if (BCM_FAILURE(rv)) {
  10339             _BCM_OAM_UNLOCK(oc);
  10340             LOG_ERROR(BSL_LS_BCM_OAM,
  10341                       (BSL_META_U(unit,
  10342                                   "OAM Error: EP=%d info get failed %s.\n"),
  10343                        h_data_p->ep_id, bcm_errmsg(rv)));
  10344             return (rv);
  10345         }
  10346 
  10347         /* Get the next node handle before calling the callback as current
  10348          * node may move to the head if modification is performed in the 
  10349          * callback */
  10350         cur = cur->next;
  10351 
  10352         rv = cb(unit, &ep_info, user_data);
  10353         if (BCM_FAILURE(rv)) {
  10354             _BCM_OAM_UNLOCK(oc);
  10355             LOG_ERROR(BSL_LS_BCM_OAM,
  10356                       (BSL_META_U(unit,
  10357                                   "OAM Error: EP=%d callback failed - %s.\n"),
  10358                        h_data_p->ep_id, bcm_errmsg(rv)));
  10359             return (rv);
  10360         }
  10361     }
  10362     _BCM_OAM_UNLOCK(oc);
  10363     return (rv);
  10364 }
  10365 
  10366 /*
  10367  * Function:
  10368  *     bcm_tr3_oam_event_register
  10369  * Purpose:
  10370  *     Register a callback for handling OAM events
  10371  * Parameters:
  10372  *     unit        - (IN) BCM device number
  10373  *     event_types - (IN) The set of OAM events for which the specified
  10374  *                        callback should be called.
  10375  *     cb          - (IN) A pointer to the callback function to call for
  10376  *                        the specified OAM events
  10377  *     user_data   - (IN) Pointer to user data to supply in the callback
  10378  * Returns:
  10379  *      BCM_E_XXX
  10380  */
  10381 int
  10382 bcm_tr3_oam_event_register(int unit, bcm_oam_event_types_t event_types,
  10383                            bcm_oam_event_cb cb, void *user_data)
  10384 {
  10385     _bcm_oam_control_t       *oc;
  10386     _bcm_oam_event_handler_t *event_h_p;
  10387     _bcm_oam_event_handler_t *prev_p = NULL;
  10388     bcm_oam_event_type_t     e_type;
  10389     uint32                   rval;
  10390     int                      hw_update = 0;
  10391     uint32                   event_bmp;
  10392     int                      rv = BCM_E_NONE;     /* Operation return status. */
  10393 
  10394     /* Validate event callback input parameter. */
  10395     if (NULL == cb) {
  10396         return (BCM_E_PARAM);
  10397     }
  10398 
  10399     /* Check if an event is set for register in the events bitmap. */
  10400     SHR_BITTEST_RANGE(event_types.w, 0, bcmOAMEventCount, event_bmp);
  10401     if (0 == event_bmp) {
  10402         /* No events specified. */
  10403         LOG_ERROR(BSL_LS_BCM_OAM,
  10404                   (BSL_META_U(unit,
  10405                               "OAM Error: No events specified for register.\n")));
  10406         return (BCM_E_PARAM);
  10407     }
  10408 
  10409     BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc));
  10410 
  10411     _BCM_OAM_LOCK(oc);
  10412 
  10413     for (event_h_p = oc->event_handler_list_p; event_h_p != NULL;
  10414          event_h_p = event_h_p->next_p) {
  10415         if (event_h_p->cb == cb) {
  10416             break;
  10417         }
  10418         prev_p = event_h_p;
  10419     }
  10420 
  10421     if (NULL == event_h_p) {
  10422 
  10423         _BCM_OAM_ALLOC(event_h_p, _bcm_oam_event_handler_t,
  10424              sizeof(_bcm_oam_event_handler_t), "OAM event handler");
  10425 
  10426         if (NULL == event_h_p) {
  10427             _BCM_OAM_UNLOCK(oc);
  10428             LOG_ERROR(BSL_LS_BCM_OAM,
  10429                       (BSL_META_U(unit,
  10430                                   "OAM Error: Event handler alloc failed -"
  10431                                   " %s.\n"), bcm_errmsg(BCM_E_MEMORY)));
  10432             return (BCM_E_MEMORY);
  10433         }
  10434 
  10435         event_h_p->next_p = NULL;
  10436         event_h_p->cb = cb;
  10437 
  10438         SHR_BITCLR_RANGE(event_h_p->event_types.w, 0, bcmOAMEventCount);
  10439         if (prev_p != NULL) {
  10440             prev_p->next_p = event_h_p;
  10441         } else {
  10442             oc->event_handler_list_p = event_h_p;
  10443         }
  10444     }
  10445 
  10446     rv = READ_CCM_INTERRUPT_CONTROLr(unit, &rval);
  10447     if (BCM_FAILURE(rv)) {
  10448         _BCM_OAM_UNLOCK(oc);
  10449         LOG_ERROR(BSL_LS_BCM_OAM,
  10450                   (BSL_META_U(unit,
  10451                               "OAM Error: CCM interrupt control read failed -"
  10452                               " %s.\n"), bcm_errmsg(rv)));
  10453         return (rv);
  10454     }
  10455 
  10456     for (e_type = 0; e_type < bcmOAMEventCount; ++e_type) {
  10457         if (SHR_BITGET(event_types.w, e_type)) {
  10458             if(soc_feature(unit, soc_feature_bhh)) {
  10459 #if defined(BCM_TRIUMPH3_SUPPORT) && defined(INCLUDE_BHH)
  10460                 /*
  10461                 * BHH events are generated by the uKernel
  10462                 */
  10463                 if ((e_type == bcmOAMEventBHHLBTimeout) ||
  10464                     (e_type == bcmOAMEventBHHLBDiscoveryUpdate) ||
  10465                     (e_type == bcmOAMEventBHHCCMTimeout) ||
  10466                     (e_type == bcmOAMEventBHHCCMTimeoutClear) ||
  10467                     (e_type == bcmOAMEventBHHCCMState) ||
  10468                     (e_type == bcmOAMEventBHHCCMRdi) ||
  10469                     (e_type == bcmOAMEventBHHCCMUnknownMegLevel) ||
  10470                     (e_type == bcmOAMEventBHHCCMUnknownMegId) ||
  10471                     (e_type == bcmOAMEventBHHCCMUnknownMepId) ||
  10472                     (e_type == bcmOAMEventBHHCCMUnknownPeriod) ||
  10473                     (e_type == bcmOAMEventBHHCCMUnknownPriority) ||
  10474                     (e_type == bcmOAMEventBHHCCMRdiClear) ||
  10475                     (e_type == bcmOAMEventBHHCCMUnknownMegLevelClear) ||
  10476                     (e_type == bcmOAMEventBHHCCMUnknownMegIdClear) ||
  10477                     (e_type == bcmOAMEventBHHCCMUnknownMepIdClear) ||
  10478                     (e_type == bcmOAMEventBHHCCMUnknownPeriodClear) ||
  10479                     (e_type == bcmOAMEventBHHCCMUnknownPriorityClear) ||
  10480                     (e_type == bcmOAMEventCsfLos) ||
  10481                     (e_type == bcmOAMEventCsfFdi) ||
  10482                     (e_type == bcmOAMEventCsfRdi) ||
  10483                     (e_type == bcmOAMEventCsfDci)) {
  10484                     SHR_BITSET(event_h_p->event_types.w, e_type);
  10485                     oc->event_handler_cnt[e_type] += 1;
  10486                     continue;
  10487                 }
  10488 #endif
  10489             }
  10490             if (!soc_reg_field_valid
  10491                     (unit, CCM_INTERRUPT_CONTROLr,
  10492                      _tr3_oam_intr_en_fields[e_type].field)) {
  10493                 continue;
  10494             }
  10495 
  10496             if (!SHR_BITGET(event_h_p->event_types.w, e_type)) {
  10497                 /* Add this event to the registered events list. */
  10498                 SHR_BITSET(event_h_p->event_types.w, e_type);
  10499                 oc->event_handler_cnt[e_type] += 1;
  10500                 if (1 == oc->event_handler_cnt[e_type]) {
  10501                     hw_update = 1;
  10502                      soc_reg_field_set
  10503                         (unit, CCM_INTERRUPT_CONTROLr, &rval,
  10504                          _tr3_oam_intr_en_fields[e_type].field, 1);
  10505                 }
  10506             }
  10507         }
  10508     }
  10509 
  10510     event_h_p->user_data = user_data;
  10511 
  10512     if (1 == hw_update) {
  10513         rv = WRITE_CCM_INTERRUPT_CONTROLr(unit, rval);
  10514         if (BCM_FAILURE(rv)) {
  10515             _BCM_OAM_UNLOCK(oc);
  10516             LOG_ERROR(BSL_LS_BCM_OAM,
  10517                       (BSL_META_U(unit,
  10518                                   "OAM Error: CCM interrupt control write failed -"
  10519                                   " %s.\n"), bcm_errmsg(rv)));
  10520             return (rv);
  10521         }
  10522     }
  10523 
  10524     if (soc_feature(unit, soc_feature_bhh)) {
  10525 #if defined(BCM_TRIUMPH3_SUPPORT) && defined(INCLUDE_BHH)
  10526         /* 
  10527          * Update BHH Events mask 
  10528          */
  10529         rv = _bcm_tr3_oam_bhh_event_mask_set(unit);
  10530 #endif /* INCLUDE_BHH */
  10531     }
  10532 
  10533     _BCM_OAM_UNLOCK(oc);
  10534 
  10535     return (rv);
  10536 }
  10537 
  10538 /*
  10539  * Function:
  10540  *     bcm_tr3_oam_event_unregister
  10541  * Purpose:
  10542  *     Remove a registered event from the event handler list.
  10543  * Parameters:
  10544  *     unit        - (IN) BCM device number
  10545  *     event_types - (IN) The set of OAM events for which the specified
  10546  *                        callback should not be called
  10547  *     cb          - (IN) A pointer to the callback function to unregister
  10548  *                        from the specified OAM events
  10549  * Returns:
  10550  *      BCM_E_XXX
  10551  */
  10552 int
  10553 bcm_tr3_oam_event_unregister(int unit, bcm_oam_event_types_t event_types,
  10554                              bcm_oam_event_cb cb)
  10555 {
  10556  
  10557     _bcm_oam_control_t       *oc;
  10558     _bcm_oam_event_handler_t *event_h_p;
  10559     _bcm_oam_event_handler_t *prev_p = NULL;
  10560     bcm_oam_event_type_t     e_type;
  10561     uint32                   rval;
  10562     int                      hw_update = 0;
  10563     uint32                   event_bmp;
  10564     int                      rv = BCM_E_NONE;     /* Operation return status. */
  10565   
  10566     /* Validate event callback input parameter. */
  10567     if (NULL == cb) {
  10568         return (BCM_E_PARAM);
  10569     }
  10570 
  10571     /* Check if an event is set for unregister in the events bitmap. */
  10572     SHR_BITTEST_RANGE(event_types.w, 0, bcmOAMEventCount, event_bmp);
  10573     if (0 == event_bmp) {
  10574         /* No events specified. */
  10575         LOG_ERROR(BSL_LS_BCM_OAM,
  10576                   (BSL_META_U(unit,
  10577                               "OAM Error: No events specified for register.\n")));
  10578         return (BCM_E_PARAM);
  10579     }
  10580 
  10581     BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc));
  10582 
  10583     _BCM_OAM_LOCK(oc);
  10584 
  10585     for (event_h_p = oc->event_handler_list_p; event_h_p != NULL;
  10586          event_h_p = event_h_p->next_p) {
  10587         if (event_h_p->cb == cb) {
  10588             break;
  10589         }
  10590         prev_p = event_h_p;
  10591     }
  10592 
  10593     if (NULL == event_h_p) {
  10594         _BCM_OAM_UNLOCK(oc);
  10595         return (BCM_E_NOT_FOUND);
  10596     }
  10597  
  10598     rv = READ_CCM_INTERRUPT_CONTROLr(unit, &rval);
  10599     if (BCM_FAILURE(rv)) {
  10600         _BCM_OAM_UNLOCK(oc);
  10601         LOG_ERROR(BSL_LS_BCM_OAM,
  10602                   (BSL_META_U(unit,
  10603                               "OAM Error: CCM interrupt control read failed -"
  10604                                " %s.\n"), bcm_errmsg(rv)));
  10605         return (rv);
  10606     }
  10607 
  10608     for (e_type = 0; e_type < bcmOAMEventCount; ++e_type) {
  10609 
  10610         if (SHR_BITGET(event_types.w, e_type)) {
  10611             if(soc_feature(unit, soc_feature_bhh)) {
  10612 #if defined(BCM_TRIUMPH3_SUPPORT) && defined(INCLUDE_BHH)
  10613                 /*
  10614                 * BHH events are generated by the uKernel
  10615                 */
  10616                 if ((e_type == bcmOAMEventBHHLBTimeout) ||
  10617                     (e_type == bcmOAMEventBHHLBDiscoveryUpdate) ||
  10618                     (e_type == bcmOAMEventBHHCCMTimeout) ||
  10619                     (e_type == bcmOAMEventBHHCCMTimeoutClear) ||
  10620                     (e_type == bcmOAMEventBHHCCMState) ||
  10621                     (e_type == bcmOAMEventBHHCCMRdi) ||
  10622                     (e_type == bcmOAMEventBHHCCMUnknownMegLevel) ||
  10623                     (e_type == bcmOAMEventBHHCCMUnknownMegId) ||
  10624                     (e_type == bcmOAMEventBHHCCMUnknownMepId) ||
  10625                     (e_type == bcmOAMEventBHHCCMUnknownPeriod) ||
  10626                     (e_type == bcmOAMEventBHHCCMUnknownPriority) ||
  10627                     (e_type == bcmOAMEventBHHCCMRdiClear) ||
  10628                     (e_type == bcmOAMEventBHHCCMUnknownMegLevelClear) ||
  10629                     (e_type == bcmOAMEventBHHCCMUnknownMegIdClear) ||
  10630                     (e_type == bcmOAMEventBHHCCMUnknownMepIdClear) ||
  10631                     (e_type == bcmOAMEventBHHCCMUnknownPeriodClear) ||
  10632                     (e_type == bcmOAMEventBHHCCMUnknownPriorityClear) ||
  10633                     (e_type == bcmOAMEventCsfLos) ||
  10634                     (e_type == bcmOAMEventCsfFdi) ||
  10635                     (e_type == bcmOAMEventCsfRdi) ||
  10636                     (e_type == bcmOAMEventCsfDci)) {
  10637                     SHR_BITCLR(event_h_p->event_types.w, e_type);
  10638                     oc->event_handler_cnt[e_type] -= 1;
  10639                     continue;
  10640                 }
  10641 #endif
  10642             }
  10643 
  10644             if (!soc_reg_field_valid
  10645                     (unit, CCM_INTERRUPT_CONTROLr,
  10646                      _tr3_oam_intr_en_fields[e_type].field)) {
  10647                 _BCM_OAM_UNLOCK(oc);
  10648                 return (BCM_E_UNAVAIL);
  10649             }
  10650 
  10651             if ((oc->event_handler_cnt[e_type] > 0)
  10652                 && SHR_BITGET(event_h_p->event_types.w, e_type)) {
  10653 
  10654                 /* Remove this event from the registered events list. */
  10655                 SHR_BITCLR(event_h_p->event_types.w, e_type);
  10656 
  10657                 oc->event_handler_cnt[e_type] -= 1;
  10658 
  10659                 if (0 == oc->event_handler_cnt[e_type]) {
  10660                     hw_update = 1;
  10661                      soc_reg_field_set
  10662                         (unit, CCM_INTERRUPT_CONTROLr, &rval,
  10663                          _tr3_oam_intr_en_fields[e_type].field, 0);
  10664                 }
  10665             }
  10666         }
  10667     }
  10668 
  10669     if (1 == hw_update) {
  10670         rv = WRITE_CCM_INTERRUPT_CONTROLr(unit, rval);
  10671         if (BCM_FAILURE(rv)) {
  10672             _BCM_OAM_UNLOCK(oc);
  10673             LOG_ERROR(BSL_LS_BCM_OAM,
  10674                       (BSL_META_U(unit,
  10675                                   "OAM Error: CCM interrupt control write failed -"
  10676                                    " %s.\n"), bcm_errmsg(rv)));
  10677             return (rv);
  10678         }
  10679     }
  10680 
  10681     SHR_BITTEST_RANGE(event_h_p->event_types.w, 0, bcmOAMEventCount, event_bmp);
  10682 
  10683     if (0 == event_bmp) {
  10684 
  10685         if (NULL != prev_p) {
  10686 
  10687             prev_p->next_p = event_h_p->next_p;
  10688             
  10689         } else {
  10690 
  10691             oc->event_handler_list_p = event_h_p->next_p;
  10692 
  10693         }
  10694         sal_free(event_h_p);
  10695     }
  10696 
  10697     if(soc_feature(unit, soc_feature_bhh)) {
  10698 #if defined(BCM_TRIUMPH3_SUPPORT) && defined(INCLUDE_BHH)
  10699         /* 
  10700          * Update BHH Events mask 
  10701          */
  10702         rv = _bcm_tr3_oam_bhh_event_mask_set(unit);
  10703 #endif /* INCLUDE_BHH */
  10704     }
  10705 
  10706     _BCM_OAM_UNLOCK(oc);
  10707 
  10708     return (rv);
  10709 }
  10710 
  10711 #if defined(BCM_TRIUMPH3_SUPPORT) && defined(INCLUDE_BHH)
  10712 /*
  10713  * Function:
  10714  *      bcm_tr3_oam_mpls_tp_channel_type_tx_get
  10715  * Purpose:
  10716  *      Get MPLS TP(BHH) ACH Channel type
  10717  * Parameters:
  10718  *      unit                (IN)  BCM device number
  10719  *      channel_type        (IN)  Channel type is ignored in XGS devices
  10720  *      Value               (OUT) User define MPLS TP(BHH) ACH channel type
  10721  *
  10722  * Returns:
  10723  *      BCM_E_NONE          No error
  10724  *      BCM_E_XXXX          Error
  10725  */
  10726 int
  10727 bcm_tr3_oam_mpls_tp_channel_type_tx_get(int unit,
  10728                                         bcm_oam_mpls_tp_channel_type_t channel_type,
  10729                                         int *value)
  10730 {
  10731     *value = tr3_oam_mpls_tp_ach_channel_type;
  10732     return BCM_E_NONE;
  10733 }
  10734 
  10735 /*
  10736  * Function:
  10737  *      bcm_ml_oam_opcodes_count_profile_delete
  10738  * Purpose:
  10739  *      Update MPLS TP(BHH) ACH Channel type with user defined value
  10740  * Parameters:
  10741  *      unit                (IN) BCM device number
  10742  *      channel_type        (IN) Channel type is ignored in XGS devices
  10743  *      Value               (IN) User define MPLS TP(BHH) ACH channel type
  10744  *
  10745  * Returns:
  10746  *      BCM_E_NONE          No error
  10747  *      BCM_E_XXXX          Error
  10748  */
  10749 int
  10750 bcm_tr3_oam_mpls_tp_channel_type_tx_set(int unit,
  10751                                         bcm_oam_mpls_tp_channel_type_t channel_type,
  10752                                         int value)
  10753 {
  10754     uint8               *buffer, *buffer_ptr;
  10755     uint16              buffer_len, reply_len;
  10756     int                 rv = BCM_E_NONE;
  10757     uint32              *msg;
  10758     _bcm_oam_control_t  *oc;
  10759 
  10760     BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc));
  10761     _BCM_OAM_LOCK(oc);
  10762 
  10763     if (oc->ukernel_not_ready) {
  10764         _BCM_OAM_UNLOCK(oc);
  10765         return BCM_E_INIT;
  10766     }
  10767 
  10768     if ((value != SHR_BHH_ACH_CHANNEL_TYPE) &&
  10769         (value != SHR_BHH_ACH_CHANNEL_TYPE_1)) {
  10770         _BCM_OAM_UNLOCK(oc);
  10771         return BCM_E_CONFIG;
  10772     }
  10773 
  10774     tr3_oam_mpls_tp_ach_channel_type = value;
  10775     msg = (uint32 *)&tr3_oam_mpls_tp_ach_channel_type;
  10776 
  10777     /* Pack control message data into DMA buffer */
  10778     buffer     = oc->dma_buffer;
  10779     buffer_ptr = bhh_sdk_msg_ctrl_ach_channel_type_msg_pack(buffer, msg);
  10780     buffer_len = buffer_ptr - buffer;
  10781 
  10782     rv = _bcm_tr3_oam_bhh_msg_send_receive(unit,
  10783                           MOS_MSG_SUBCLASS_BHH_ACH_CHANNEL_TYPE,
  10784                           buffer_len, 0,
  10785                           MOS_MSG_SUBCLASS_BHH_ACH_CHANNEL_TYPE_REPLY,
  10786                           &reply_len, _BHH_UC_MSG_TIMEOUT_USECS);
  10787 
  10788     if (BCM_FAILURE(rv)) {
  10789         _BCM_OAM_UNLOCK(oc);
  10790         return (rv);
  10791     }
  10792 
  10793     _BCM_OAM_UNLOCK(oc);
  10794     return BCM_E_NONE;
  10795 }
  10796 
  10797 /*
  10798  * Function:
  10799  *      _bcm_tr3_oam_bhh_fp_set
  10800  * Purpose:
  10801  *      Sets BHH FP for LM/DM in HW device.
  10802  * Parameters:
  10803  *      unit            - (IN) Unit number.
  10804  *      module_id       - (IN) Module id.
  10805  *      port_id         - (IN) Port.
  10806  *      is_local        - (IN) Indicates if module id is local.
  10807  *      endpoint_config - (IN) Pointer to BHH endpoint structure.
  10808  * Returns:
  10809  *      BCM_E_XXX
  10810  * Notes:
  10811  */
  10812 STATIC int
  10813 _bcm_tr3_oam_bhh_fp_set(int unit, _bcm_oam_hash_data_t *hash_data, uint32 nhi,
  10814                         bcm_oam_endpoint_info_t *endpoint_info)
  10815 {
  10816     int rv = BCM_E_NONE;
  10817     _bcm_oam_control_t *oc;
  10818     bcm_gport_t gport;
  10819     bcm_module_t module_id;
  10820     bcm_port_t port_id;
  10821     bcm_trunk_t trunk_id;
  10822     int         local_id;
  10823     void *entries[1];
  10824     int i;
  10825     uint32 mem_entries[BCM_OAM_INTPRI_MAX], profile_index;
  10826     bcm_mpls_label_t label = hash_data->label << 12;
  10827     uint32 label_mask = SHR_BHH_MPLS_LABEL_MASK;
  10828     uint16 ach_type = tr3_oam_mpls_tp_ach_channel_type;
  10829     uint16 ach_mask = 0xFFFF;
  10830     uint8 op_code;
  10831     uint8 op_mask;
  10832 
  10833     /* Lock already taken by the calling routine. */
  10834     BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc));
  10835 
  10836     if(oc->bhh_lmdm_group == 0) {
  10837         BCM_IF_ERROR_RETURN(bcm_esw_field_group_create(unit, 
  10838                             oc->bhh_lmdm_qset, 
  10839                             BCM_FIELD_GROUP_PRIO_ANY, &oc->bhh_lmdm_group));
  10840         oc->bhh_lmdm_entry_count = 0;
  10841     }
  10842 
  10843     rv = _bcm_esw_gport_resolve(unit,
  10844             hash_data->gport, &module_id, &port_id, &trunk_id, &local_id);
  10845     if (BCM_FAILURE(rv)) {
  10846         LOG_ERROR(BSL_LS_BCM_OAM,
  10847                   (BSL_META_U(unit,
  10848                               "BHH Error: Gport resolve (EP=%d) - %s.\n"),
  10849                    hash_data->ep_id, bcm_errmsg(rv)));
  10850         return (rv);
  10851     }
  10852 
  10853     if (BCM_TRUNK_INVALID != trunk_id) {
  10854         BCM_GPORT_TRUNK_SET(gport, trunk_id);
  10855     } else if (module_id != 0) {
  10856         /* Modport */
  10857         BCM_GPORT_MODPORT_SET(gport, module_id, port_id);
  10858     } else {
  10859         /* Local port */
  10860         BCM_IF_ERROR_RETURN(bcm_esw_port_gport_get(unit, port_id, &gport));
  10861     }
  10862 
  10863     if(hash_data->flags & BCM_OAM_ENDPOINT_DELAY_MEASUREMENT) {
  10864         BCM_IF_ERROR_RETURN(bcm_esw_field_entry_create(unit,
  10865                             oc->bhh_lmdm_group,
  10866                             &hash_data->bhh_dm_entry_rx));
  10867         if (SOC_GPORT_IS_TRUNK(gport)) {
  10868             BCM_IF_ERROR_RETURN(
  10869                     bcm_esw_field_qualify_SrcTrunk(unit,
  10870                                                    hash_data->bhh_dm_entry_rx,
  10871                                                    trunk_id,
  10872                                                    BCM_FIELD_EXACT_MATCH_MASK));
  10873         } else {
  10874             BCM_IF_ERROR_RETURN(
  10875                     bcm_esw_field_qualify_SrcPort(unit,
  10876                                                   hash_data->bhh_dm_entry_rx,
  10877                                                   0, 0x3f, gport,
  10878                                                   BCM_FIELD_EXACT_MATCH_MASK));
  10879         }
  10880         BCM_IF_ERROR_RETURN(bcm_esw_field_qualify_OuterVlanId(unit, 
  10881                             hash_data->bhh_dm_entry_rx,
  10882                             hash_data->vlan, 0x0fff));
  10883 
  10884         op_code = SHR_BHH_OPCODE_DM_PREFIX;
  10885         op_mask = SHR_BHH_OPCODE_DM_MASK;
  10886          if (oc->bhh_udf_mode) {
  10887              BCM_IF_ERROR_RETURN(
  10888                          bcm_esw_field_qualify_udf(unit,
  10889                                                    hash_data->bhh_dm_entry_rx,
  10890                                                    oc->bhh_label_udf_id,
  10891                                                    SHR_BHH_MPLS_LABEL_LENGTH,
  10892                                                    (uint8 *)&label,
  10893                                                    (uint8 *)&label_mask));
  10894 
  10895             BCM_IF_ERROR_RETURN(
  10896                         bcm_esw_field_qualify_udf(unit,
  10897                                                   hash_data->bhh_dm_entry_rx,
  10898                                                   oc->bhh_ach_qual_id,
  10899                                                   SHR_BHH_ACH_TYPE_LENGTH,
  10900                                                   (uint8 *)&ach_type,
  10901                                                   (uint8 *)&ach_mask));
  10902 
  10903             BCM_IF_ERROR_RETURN(
  10904                         bcm_esw_field_qualify_udf(unit,
  10905                                                   hash_data->bhh_dm_entry_rx,
  10906                                                   oc->bhh_opcode_qual_id,
  10907                                                   SHR_BHH_OPCODE_LEN,
  10908                                                   &op_code,
  10909                                                   &op_mask));
  10910         } else {
  10911             BCM_IF_ERROR_RETURN(
  10912                         bcm_esw_field_qualify_data(unit,
  10913                                                    hash_data->bhh_dm_entry_rx,
  10914                                                    oc->bhh_label_qual_id,
  10915                                                    (uint8 *)&label,
  10916                                                    (uint8 *)&label_mask,
  10917                                                    SHR_BHH_MPLS_LABEL_LENGTH));
  10918 
  10919             BCM_IF_ERROR_RETURN(
  10920                         bcm_esw_field_qualify_data(unit,
  10921                                                    hash_data->bhh_dm_entry_rx,
  10922                                                    oc->bhh_ach_qual_id,
  10923                                                    (uint8 *)&ach_type,
  10924                                                    (uint8 *)&ach_mask,
  10925                                                    SHR_BHH_ACH_TYPE_LENGTH));
  10926 
  10927             BCM_IF_ERROR_RETURN(
  10928                         bcm_esw_field_qualify_data(unit,
  10929                                                    hash_data->bhh_dm_entry_rx,
  10930                                                    oc->bhh_opcode_qual_id,
  10931                                                    &op_code,
  10932                                                    &op_mask,
  10933                                                    SHR_BHH_OPCODE_LEN));
  10934         }
  10935         BCM_IF_ERROR_RETURN(bcm_esw_field_action_add(unit, 
  10936                             hash_data->bhh_dm_entry_rx,
  10937                             bcmFieldActionOamDmEnable, 1, 0));
  10938         BCM_IF_ERROR_RETURN(bcm_esw_field_action_add(unit, 
  10939                             hash_data->bhh_dm_entry_rx,
  10940                             bcmFieldActionOamDmTimeFormat, 1, 0)); /* NTP */
  10941         BCM_IF_ERROR_RETURN(bcm_esw_field_action_add(unit, 
  10942                             hash_data->bhh_dm_entry_rx,
  10943                             bcmFieldActionOamLmepEnable, 0, 0));
  10944         BCM_IF_ERROR_RETURN(bcm_esw_field_action_add(unit,
  10945                             hash_data->bhh_dm_entry_rx,
  10946                             bcmFieldActionOamLmDmSampleEnable, 1, 0));
  10947         BCM_IF_ERROR_RETURN(bcm_esw_field_entry_install(unit, 
  10948                             hash_data->bhh_dm_entry_rx));
  10949         if(hash_data->bhh_dm_entry_rx)
  10950             oc->bhh_lmdm_entry_count++;
  10951     }
  10952 
  10953     if(hash_data->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT) {
  10954         /* Allocate the next available endpoint index. */
  10955         rv = shr_idxres_list_alloc(oc->lm_counter_pool,
  10956                           (shr_idxres_element_t *)&hash_data->lm_counter_index);
  10957         if (BCM_FAILURE(rv)) {
  10958             rv = (rv == BCM_E_RESOURCE) ? (BCM_E_FULL) : rv;
  10959                 LOG_ERROR(BSL_LS_BCM_OAM,
  10960                           (BSL_META_U(unit,
  10961                                       "BHH Error: lm counter idx alloc failed - %s.\n"),
  10962                            bcm_errmsg(rv)));
  10963             return (rv);
  10964         }
  10965 
  10966         /* Assign Pri Mapping pointer */
  10967         for (i = 0; i < BCM_OAM_INTPRI_MAX ; i++) {
  10968             mem_entries[i] = endpoint_info->pri_map[i];
  10969             if (SOC_MEM_FIELD_VALID(unit, ING_SERVICE_PRI_MAPm, OFFSET_VALIDf)) {
  10970                 soc_mem_field32_set(unit, ING_SERVICE_PRI_MAPm, &mem_entries[i],
  10971                         OFFSET_VALIDf, 1);
  10972             }
  10973         }
  10974 
  10975         soc_mem_lock(unit, ING_SERVICE_PRI_MAPm);
  10976         entries[0] = &mem_entries;
  10977         rv = soc_profile_mem_add(unit, &oc->ing_service_pri_map,
  10978                 (void *) &entries, BCM_OAM_INTPRI_MAX, &profile_index);
  10979         if (BCM_FAILURE(rv)) {
  10980             LOG_ERROR(BSL_LS_BCM_OAM,
  10981                       (BSL_META_U(unit,
  10982                                   "BHH Error: Adding ING_SERVICE_PRI_MAP entry"
  10983                                    " - %s.\n"), bcm_errmsg(rv)));
  10984             soc_mem_unlock(unit, ING_SERVICE_PRI_MAPm);
  10985             return (rv);
  10986         }
  10987         hash_data->pri_map_index = profile_index/BCM_OAM_INTPRI_MAX;
  10988         soc_mem_unlock(unit, ING_SERVICE_PRI_MAPm);
  10989 
  10990         /* policy to get lm counter value into DCBs*/
  10991         BCM_IF_ERROR_RETURN(bcm_esw_field_entry_create(unit,
  10992                             oc->bhh_lmdm_group,
  10993                             &hash_data->bhh_lm_entry_rx));
  10994         if (SOC_GPORT_IS_TRUNK(gport)) {
  10995             BCM_IF_ERROR_RETURN(
  10996                     bcm_esw_field_qualify_SrcTrunk(unit,
  10997                                                    hash_data->bhh_lm_entry_rx,
  10998                                                    trunk_id,
  10999                                                    BCM_FIELD_EXACT_MATCH_MASK));
  11000         } else {
  11001             BCM_IF_ERROR_RETURN(
  11002                     bcm_esw_field_qualify_SrcPort(unit,
  11003                                                   hash_data->bhh_lm_entry_rx,
  11004                                                   0, 0x3f, gport,
  11005                                                   BCM_FIELD_EXACT_MATCH_MASK));
  11006         }
  11007         BCM_IF_ERROR_RETURN(bcm_esw_field_qualify_OuterVlanId(unit,
  11008                             hash_data->bhh_lm_entry_rx,
  11009                             hash_data->vlan, 0x0fff));
  11010 
  11011         op_code = SHR_BHH_OPCODE_LM_PREFIX;
  11012         op_mask = SHR_BHH_OPCODE_LM_MASK;
  11013         if(oc->bhh_udf_mode) {
  11014             BCM_IF_ERROR_RETURN(
  11015                         bcm_esw_field_qualify_udf(unit,
  11016                                                   hash_data->bhh_lm_entry_rx,
  11017                                                   oc->bhh_label_udf_id,
  11018                                                   SHR_BHH_MPLS_LABEL_LENGTH,
  11019                                                   (uint8 *)&label,
  11020                                                   (uint8 *)&label_mask));
  11021 
  11022             BCM_IF_ERROR_RETURN(
  11023                         bcm_esw_field_qualify_udf(unit,
  11024                                                   hash_data->bhh_lm_entry_rx,
  11025                                                   oc->bhh_ach_udf_id,
  11026                                                   SHR_BHH_ACH_TYPE_LENGTH,
  11027                                                   (uint8 *)&ach_type,
  11028                                                   (uint8 *)&ach_mask));
  11029 
  11030             BCM_IF_ERROR_RETURN(
  11031                         bcm_esw_field_qualify_udf(unit,
  11032                                                   hash_data->bhh_lm_entry_rx,
  11033                                                   oc->bhh_opcode_udf_id,
  11034                                                   SHR_BHH_OPCODE_LEN,
  11035                                                   &op_code,
  11036                                                   &op_mask));
  11037         } else {
  11038             BCM_IF_ERROR_RETURN(
  11039                         bcm_esw_field_qualify_data(unit,
  11040                                                    hash_data->bhh_lm_entry_rx,
  11041                                                    oc->bhh_label_qual_id,
  11042                                                    (uint8 *)&label,
  11043                                                    (uint8 *)&label_mask,
  11044                                                    SHR_BHH_MPLS_LABEL_LENGTH));
  11045 
  11046             BCM_IF_ERROR_RETURN(
  11047                         bcm_esw_field_qualify_data(unit,
  11048                                                    hash_data->bhh_lm_entry_rx,
  11049                                                    oc->bhh_ach_qual_id,
  11050                                                    (uint8 *)&ach_type,
  11051                                                    (uint8 *)&ach_mask,
  11052                                                    SHR_BHH_ACH_TYPE_LENGTH));
  11053 
  11054             BCM_IF_ERROR_RETURN(
  11055                         bcm_esw_field_qualify_data(unit,
  11056                                                    hash_data->bhh_lm_entry_rx,
  11057                                                    oc->bhh_opcode_qual_id,
  11058                                                    &op_code,
  11059                                                    &op_mask,
  11060                                                    SHR_BHH_OPCODE_LEN));
  11061         }
  11062 
  11063         BCM_IF_ERROR_RETURN(bcm_esw_field_action_add(unit,
  11064                             hash_data->bhh_lm_entry_rx,
  11065                             bcmFieldActionOamLmEnable, 1, 0));
  11066         BCM_IF_ERROR_RETURN(bcm_esw_field_action_add(unit,
  11067                             hash_data->bhh_lm_entry_rx,
  11068                             bcmFieldActionOamLmepEnable, 0, 0));
  11069         BCM_IF_ERROR_RETURN(bcm_esw_field_action_add(unit,
  11070                             hash_data->bhh_lm_entry_rx,
  11071                             bcmFieldActionOamLmBasePtr,
  11072                             hash_data->lm_counter_index, 0));
  11073         BCM_IF_ERROR_RETURN(bcm_esw_field_action_add(unit,
  11074                             hash_data->bhh_lm_entry_rx,
  11075                             bcmFieldActionOamServicePriMappingPtr,
  11076                             hash_data->pri_map_index, 0));
  11077         BCM_IF_ERROR_RETURN(bcm_esw_field_action_add(unit,
  11078                             hash_data->bhh_lm_entry_rx,
  11079                             bcmFieldActionOamTx, 0, 0));
  11080         BCM_IF_ERROR_RETURN(bcm_esw_field_action_add(unit,
  11081                             hash_data->bhh_lm_entry_rx,
  11082                             bcmFieldActionOamLmDmSampleEnable, 1, 0));
  11083         BCM_IF_ERROR_RETURN(bcm_esw_field_entry_install(unit, 
  11084                             hash_data->bhh_lm_entry_rx));
  11085         if(hash_data->bhh_lm_entry_rx)
  11086             oc->bhh_lmdm_entry_count++;
  11087 
  11088         /* Count the Rx packets */
  11089 
  11090         BCM_IF_ERROR_RETURN(bcm_esw_field_entry_create(unit,
  11091                             oc->bhh_lmdm_group,
  11092                             &hash_data->bhh_entry_pkt_rx));
  11093         if (SOC_GPORT_IS_TRUNK(gport)) {
  11094             BCM_IF_ERROR_RETURN(
  11095                     bcm_esw_field_qualify_SrcTrunk(unit,
  11096                                                    hash_data->bhh_entry_pkt_rx,
  11097                                                    trunk_id,
  11098                                                    BCM_FIELD_EXACT_MATCH_MASK));
  11099         } else {
  11100             BCM_IF_ERROR_RETURN(
  11101                     bcm_esw_field_qualify_SrcPort(unit,
  11102                                                   hash_data->bhh_entry_pkt_rx,
  11103                                                   0, 0x3f, gport,
  11104                                                   BCM_FIELD_EXACT_MATCH_MASK));
  11105         }
  11106         BCM_IF_ERROR_RETURN(bcm_esw_field_qualify_OuterVlanId(unit, 
  11107                             hash_data->bhh_entry_pkt_rx, 
  11108                             hash_data->vlan, 0x0fff));
  11109 
  11110         if (oc->bhh_udf_mode) {
  11111             BCM_IF_ERROR_RETURN(
  11112                         bcm_esw_field_qualify_udf(unit,
  11113                                                   hash_data->bhh_entry_pkt_rx,
  11114                                                   oc->bhh_label_udf_id,
  11115                                                   SHR_BHH_MPLS_LABEL_LENGTH,
  11116                                                   (uint8 *)&label,
  11117                                                   (uint8 *)&label_mask));
  11118 
  11119         } else {
  11120             BCM_IF_ERROR_RETURN(
  11121                         bcm_esw_field_qualify_data(unit,
  11122                                                    hash_data->bhh_entry_pkt_rx,
  11123                                                    oc->bhh_label_qual_id,
  11124                                                    (uint8 *)&label,
  11125                                                    (uint8 *)&label_mask,
  11126                                                    SHR_BHH_MPLS_LABEL_LENGTH));
  11127         }
  11128         BCM_IF_ERROR_RETURN(bcm_esw_field_action_add(unit, 
  11129                             hash_data->bhh_entry_pkt_rx,
  11130                             bcmFieldActionOamLmEnable, 1, 0));
  11131         BCM_IF_ERROR_RETURN(bcm_esw_field_action_add(unit, 
  11132                             hash_data->bhh_entry_pkt_rx,
  11133                             bcmFieldActionOamLmepEnable,
  11134                             1, 0));
  11135         BCM_IF_ERROR_RETURN(bcm_esw_field_action_add(unit, 
  11136                             hash_data->bhh_entry_pkt_rx,
  11137                             bcmFieldActionOamLmBasePtr,
  11138                             hash_data->lm_counter_index, 0));
  11139         BCM_IF_ERROR_RETURN(bcm_esw_field_action_add(unit,
  11140                             hash_data->bhh_entry_pkt_rx,
  11141                             bcmFieldActionOamServicePriMappingPtr,
  11142                             hash_data->pri_map_index, 0));
  11143         BCM_IF_ERROR_RETURN(bcm_esw_field_action_add(unit,
  11144                             hash_data->bhh_entry_pkt_rx,
  11145                             bcmFieldActionOamTx, 0, 0));
  11146         BCM_IF_ERROR_RETURN(bcm_esw_field_entry_install(unit, 
  11147                             hash_data->bhh_entry_pkt_rx));
  11148         if(hash_data->bhh_entry_pkt_rx)
  11149             oc->bhh_lmdm_entry_count++;
  11150 
  11151         /* Count the Tx packets */
  11152 
  11153         BCM_IF_ERROR_RETURN(bcm_esw_field_entry_create(unit,
  11154                             oc->bhh_lmdm_group,
  11155                             &hash_data->bhh_entry_pkt_tx));
  11156         if (SOC_GPORT_IS_TRUNK(gport)) {
  11157             BCM_IF_ERROR_RETURN(
  11158                     bcm_esw_field_qualify_DstTrunk(unit,
  11159                                                    hash_data->bhh_entry_pkt_tx,
  11160                                                    trunk_id,
  11161                                                    BCM_FIELD_EXACT_MATCH_MASK));
  11162         } else {
  11163             BCM_IF_ERROR_RETURN(
  11164                     bcm_esw_field_qualify_DstPort(unit,
  11165                                                   hash_data->bhh_entry_pkt_tx,
  11166                                                   0, 0x3f, gport,
  11167                                                   BCM_FIELD_EXACT_MATCH_MASK));
  11168         }
  11169 
  11170         BCM_IF_ERROR_RETURN(bcm_esw_field_qualify_OuterVlanId(unit, 
  11171                             hash_data->bhh_entry_pkt_tx,
  11172                             hash_data->vlan, 0x0fff));
  11173         BCM_IF_ERROR_RETURN(bcm_esw_field_qualify_DstL3Egress(unit, 
  11174                             hash_data->bhh_entry_pkt_tx, endpoint_info->intf_id));
  11175         BCM_IF_ERROR_RETURN(bcm_esw_field_action_add(unit, 
  11176                             hash_data->bhh_entry_pkt_tx,
  11177                             bcmFieldActionOamLmEnable, 1, 0));
  11178         BCM_IF_ERROR_RETURN(bcm_esw_field_action_add(unit,
  11179                             hash_data->bhh_entry_pkt_tx,
  11180                             bcmFieldActionOamLmepEnable, 1, 0));
  11181         BCM_IF_ERROR_RETURN(bcm_esw_field_action_add(unit, 
  11182                             hash_data->bhh_entry_pkt_tx,
  11183                             bcmFieldActionOamLmBasePtr,
  11184                             hash_data->lm_counter_index, 0));
  11185         BCM_IF_ERROR_RETURN(bcm_esw_field_action_add(unit, 
  11186                             hash_data->bhh_entry_pkt_tx,
  11187                             bcmFieldActionOamServicePriMappingPtr,
  11188                             hash_data->pri_map_index, 0));
  11189         BCM_IF_ERROR_RETURN(bcm_esw_field_action_add(unit, 
  11190                             hash_data->bhh_entry_pkt_tx,
  11191                             bcmFieldActionOamTx, 1, 0));
  11192         BCM_IF_ERROR_RETURN(bcm_esw_field_entry_install(unit, 
  11193                             hash_data->bhh_entry_pkt_tx));
  11194         if(hash_data->bhh_entry_pkt_tx)
  11195             oc->bhh_lmdm_entry_count++;
  11196 
  11197     }
  11198 
  11199 
  11200     return rv;
  11201 }
  11202 
  11203 /*
  11204  * Function:
  11205  *      _bcm_tr3_oam_bhh_encap_hw_set
  11206  * Purpose:
  11207  *      Sets BHH encapsulation type in HW device.
  11208  * Parameters:
  11209  *      unit            - (IN) Unit number.
  11210  *      module_id       - (IN) Module id.
  11211  *      port_id         - (IN) Port.
  11212  *      is_local        - (IN) Indicates if module id is local.
  11213  *      endpoint_config - (IN) Pointer to BHH endpoint structure.
  11214  * Returns:
  11215  *      BCM_E_XXX
  11216  * Notes:
  11217  */
  11218 STATIC int
  11219 _bcm_tr3_oam_bhh_encap_hw_set(int unit, _bcm_oam_hash_data_t *h_data_p,
  11220                          bcm_module_t module_id, bcm_port_t port_id,
  11221                          int is_local, bcm_oam_endpoint_info_t *endpoint_info)
  11222 {
  11223     int rv = BCM_E_NONE;
  11224     l2_entry_1_entry_t l2_entry_1;
  11225 #if defined(BCM_TRIUMPH_SUPPORT) && defined(BCM_MPLS_SUPPORT)
  11226     bcm_l3_egress_t l3_egress;
  11227     int ingress_if;
  11228     int i;
  11229     int num_entries;
  11230     mpls_entry_1_entry_t mpls_entry;
  11231     mpls_entry_1_entry_t mpls_key;
  11232     int mpls_index = 0;
  11233     int nhi = 0;
  11234     int vccv_type = 0;
  11235 #endif /* BCM_TRIUMPH_SUPPORT &&  BCM_MPLS_SUPPORT */
  11236 
  11237     switch(h_data_p->type) {
  11238     case bcmOAMEndpointTypeBHHMPLS:
  11239     case bcmOAMEndpointTypeBHHMPLSVccv:
  11240 
  11241 #if defined(BCM_TRIUMPH3_SUPPORT) && defined(BCM_MPLS_SUPPORT)
  11242 
  11243         /* Insert mpls label field to L2_ENTRY table. */
  11244         sal_memset(&l2_entry_1, 0, sizeof(l2_entry_1));
  11245         
  11246         soc_mem_field32_set(unit, L2_ENTRY_1m, &l2_entry_1, KEY_TYPEf, 12);
  11247         
  11248         soc_mem_field32_set(unit, L2_ENTRY_1m, &l2_entry_1, 
  11249                                               BFD__SESSION_IDENTIFIER_TYPEf, 1);
  11250        
  11251         soc_mem_field32_set(unit, L2_ENTRY_1m, &l2_entry_1, BFD__LABELf,
  11252                                                     h_data_p->label);
  11253         soc_mem_field32_set(unit, L2_ENTRY_1m, &l2_entry_1, VALIDf, 1);
  11254 
  11255         if (!is_local) {
  11256             /* Set BHH_REMOTE = 1, DST_MOD, DST_PORT */
  11257             soc_mem_field32_set(unit, L2_ENTRY_1m, &l2_entry_1, BFD__REMOTEf, 1);
  11258             soc_mem_field32_set(unit, L2_ENTRY_1m, &l2_entry_1, BFD__MODULE_IDf,
  11259                                 module_id); 
  11260             soc_mem_field32_set(unit, L2_ENTRY_1m, &l2_entry_1, BFD__DGPPf,
  11261                                 port_id);
  11262             soc_mem_field32_set(unit, L2_ENTRY_1m, &l2_entry_1, BFD__INT_PRIf,
  11263                                 endpoint_info->int_pri);
  11264         } else {
  11265 #if 0
  11266 
  11267             soc_mem_field32_set(unit, L2Xm, &l2_entry, BFD_RX_SESSION_INDEXf,
  11268                                 h_data_p->bhh_endpoint_index);
  11269 #endif
  11270             soc_mem_field32_set(unit, L2_ENTRY_1m, &l2_entry_1, BFD__INT_PRIf,
  11271                                 h_data_p->cpu_qid); 
  11272         }
  11273 
  11274         soc_mem_insert(unit, L2_ENTRY_1m, MEM_BLOCK_ANY, &l2_entry_1);
  11275 
  11276         SOC_IF_ERROR_RETURN(bcm_tr_mpls_lock (unit));
  11277 
  11278         sal_memset(&mpls_key, 0, sizeof(mpls_key));
  11279         soc_MPLS_ENTRYm_field32_set(unit, &mpls_key, MPLS__MPLS_LABELf,
  11280                                     h_data_p->label);
  11281         soc_MPLS_ENTRYm_field32_set(unit, &mpls_key, KEY_TYPEf, 16);
  11282         soc_MPLS_ENTRYm_field32_set(unit, &mpls_key, VALIDf, 1);
  11283 
  11284         rv = soc_mem_search(unit, MPLS_ENTRYm, MEM_BLOCK_ANY, &mpls_index,
  11285                             &mpls_key, &mpls_entry, 0);
  11286         if (SOC_FAILURE(rv)) {
  11287             bcm_tr_mpls_unlock(unit);
  11288             return rv;
  11289         }
  11290 
  11291         if ((soc_MPLS_ENTRYm_field32_get(unit, &mpls_entry,
  11292                                          VALIDf) != 0x1)) {
  11293             bcm_tr_mpls_unlock (unit);
  11294             return (BCM_E_PARAM);
  11295         }
  11296 
  11297         if (h_data_p->type == bcmOAMEndpointTypeBHHMPLSVccv) {
  11298             /* Get the control channel type */
  11299             vccv_type = soc_MPLS_ENTRYm_field32_get(unit, &mpls_entry,
  11300                                                     MPLS__PW_CC_TYPEf);
  11301 
  11302             if (vccv_type == 0) { /* No VCCV type configured */
  11303                 soc_MPLS_ENTRYm_field32_set(unit, &mpls_entry,
  11304                                             MPLS__PW_CC_TYPEf,
  11305                                             (h_data_p->vccv_type + 1));
  11306 
  11307             } else if (vccv_type != (h_data_p->vccv_type + 1)) {
  11308                 /* Endpoint add configuration conflicts with MPLS
  11309                  * port add config
  11310                  */
  11311                 bcm_tr_mpls_unlock(unit);
  11312                 return BCM_E_PARAM;
  11313             }
  11314         }
  11315 
  11316 
  11317         soc_MPLS_ENTRYm_field32_set(unit, &mpls_entry,
  11318                                     MPLS__SESSION_IDENTIFIER_TYPEf, 1);
  11319         soc_MPLS_ENTRYm_field32_set(unit, &mpls_entry, MPLS__BFD_ENABLEf, 1);
  11320         rv = soc_mem_write(unit, MPLS_ENTRYm,
  11321                                           MEM_BLOCK_ANY, mpls_index,
  11322                                           &mpls_entry);
  11323         if (rv != SOC_E_NONE) {
  11324             bcm_tr_mpls_unlock(unit);
  11325             return rv;
  11326         }
  11327 
  11328          /*
  11329          * PW CC-3
  11330          *
  11331          * Set MPLS entry DECAP_USE_TTL=0 for corresponding
  11332          * Tunnel Terminator label.
  11333          */
  11334         if (h_data_p->type == bcmOAMEndpointTypeBHHMPLSVccv) {
  11335             if (h_data_p->vccv_type == bcmOamBhhVccvTtl) {
  11336                 rv = bcm_esw_l3_egress_get(unit, h_data_p->egress_if,
  11337                                            &l3_egress);
  11338                 if (rv != BCM_E_NONE) {
  11339                     bcm_tr_mpls_unlock(unit);
  11340                     return rv;
  11341                 }
  11342 
  11343                 /* Look for Tunnel Terminator label */
  11344                 num_entries = soc_mem_index_count(unit, MPLS_ENTRYm);
  11345                 for (i = 0; i < num_entries; i++) {
  11346                     rv = READ_MPLS_ENTRYm(unit, MEM_BLOCK_ANY, i, &mpls_entry);
  11347                     if (rv != SOC_E_NONE) {
  11348                         bcm_tr_mpls_unlock(unit);
  11349                         return rv;
  11350                     }
  11351 
  11352                     if (!soc_MPLS_ENTRYm_field32_get(unit, &mpls_entry, VALIDf)) {
  11353                         continue;
  11354                     }
  11355                     if (soc_MPLS_ENTRYm_field32_get(unit, &mpls_entry,
  11356                                               MPLS__MPLS_ACTION_IF_BOSf) == 0x1) {
  11357                         continue;    /* L2_SVP */
  11358                     }
  11359 
  11360                     ingress_if = soc_MPLS_ENTRYm_field32_get(unit, &mpls_entry,
  11361                                                              MPLS__L3_IIFf);
  11362                     if (ingress_if == l3_egress.intf) {
  11363                         /* Label found */
  11364                         soc_MPLS_ENTRYm_field32_set(unit, &mpls_entry,
  11365                                                     MPLS__DECAP_USE_TTLf, 0);
  11366                         rv = soc_mem_write(unit, MPLS_ENTRYm,
  11367                                             MEM_BLOCK_ALL, i,
  11368                                             &mpls_entry);
  11369                         if (rv != SOC_E_NONE) {
  11370                             bcm_tr_mpls_unlock(unit);
  11371                             return rv;
  11372                         }
  11373                         break;
  11374                     }
  11375                 }
  11376             }
  11377         }
  11378         bcm_tr_mpls_unlock (unit);
  11379 #endif /* BCM_TRIUMPH3_SUPPORT &&  BCM_MPLS_SUPPORT */
  11380         break;
  11381 
  11382     default:
  11383         rv = BCM_E_UNAVAIL;
  11384         break;
  11385     }
  11386 
  11387     
  11388     if((h_data_p->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT) ||
  11389         (h_data_p->flags & BCM_OAM_ENDPOINT_DELAY_MEASUREMENT))
  11390     {
  11391         rv = _bcm_tr3_oam_bhh_fp_set(unit, h_data_p, nhi, endpoint_info);
  11392     }
  11393 
  11394     return (rv);
  11395 }
  11396 
  11397 /*
  11398  * Function:
  11399  *      _bcm_tr3_oam_bhh_encap_data_dump
  11400  * Purpose:
  11401  *      Dumps buffer contents.
  11402  * Parameters:
  11403  *      buffer  - (IN) Buffer to dump data.
  11404  *      length  - (IN) Length of buffer.
  11405  * Returns:
  11406  *      None
  11407  */
  11408 void
  11409 _bcm_tr3_oam_bhh_encap_data_dump(uint8 *buffer, int length)
  11410 {
  11411     int i;
  11412 
  11413     LOG_CLI((BSL_META("\nBHH encapsulation (length=%d):\n"), length));
  11414 
  11415     for (i = 0; i < length; i++) {
  11416         if ((i % 16) == 0) {
  11417             LOG_CLI((BSL_META("\n")));
  11418         }
  11419         LOG_CLI((BSL_META(" %02x"), buffer[i]));
  11420     }
  11421 
  11422     LOG_CLI((BSL_META("\n")));
  11423     return;
  11424 }
  11425 
  11426 STATIC int
  11427 _bcm_tr3_oam_bhh_ach_header_get(uint32 packet_flags, _ach_header_t *ach)
  11428 {
  11429     sal_memset(ach, 0, sizeof(*ach));
  11430 
  11431     ach->f_nibble = SHR_BHH_ACH_FIRST_NIBBLE;
  11432     ach->version  = SHR_BHH_ACH_VERSION;
  11433     ach->reserved = 0;
  11434 
  11435     ach->channel_type = tr3_oam_mpls_tp_ach_channel_type;
  11436 
  11437     return (BCM_E_NONE);
  11438 }
  11439 
  11440 STATIC int
  11441 _bcm_tr3_oam_bhh_mpls_label_get(uint32 label, uint8 exp, uint8 s, uint8 ttl,
  11442                            _mpls_label_t *mpls)
  11443 {
  11444     sal_memset(mpls, 0, sizeof(*mpls));
  11445 
  11446     mpls->label = label;
  11447     mpls->exp   = exp & 0x07;
  11448     mpls->s     = s;
  11449     if(ttl)
  11450         mpls->ttl   = ttl;
  11451     else
  11452         mpls->ttl   = _BHH_MPLS_DFLT_TTL;
  11453 
  11454     return (BCM_E_NONE);
  11455 }
  11456 
  11457 STATIC int
  11458 _bcm_tr3_oam_bhh_mpls_gal_label_get(_mpls_label_t *mpls, uint8 oam_exp)
  11459 {
  11460     return _bcm_tr3_oam_bhh_mpls_label_get(SHR_BHH_MPLS_GAL_LABEL,
  11461                                       oam_exp, 1, 1, mpls);
  11462 }
  11463 
  11464 STATIC int
  11465 _bcm_tr3_oam_bhh_mpls_labels_get(int unit, _bcm_oam_hash_data_t *h_data_p,
  11466                                 uint32 packet_flags,
  11467                                 int max_count, 
  11468                                 _mpls_label_t *pw_label,
  11469                                 _mpls_label_t *mpls,
  11470                                 int *mpls_count, bcm_if_t *l3_intf_id)
  11471 {
  11472     int count = 0;
  11473     bcm_l3_egress_t l3_egress;
  11474     bcm_mpls_port_t mpls_port;
  11475     bcm_mpls_egress_label_t label_array[_BHH_MPLS_MAX_LABELS];
  11476     bcm_mpls_egress_label_t tmp_label;
  11477     int label_count;
  11478     int i = 0;
  11479 
  11480      /* Get L3 objects */
  11481     bcm_l3_egress_t_init(&l3_egress);
  11482     if (BCM_FAILURE(bcm_esw_l3_egress_get(unit, h_data_p->egress_if, &l3_egress))) {
  11483         return (BCM_E_PARAM);
  11484     }
  11485 
  11486     /* Look for a tunnel associated with this interface */
  11487     if (BCM_SUCCESS
  11488         (bcm_esw_mpls_tunnel_initiator_get(unit, l3_egress.intf,
  11489                                            _BHH_MPLS_MAX_LABELS,
  11490                                            label_array, &label_count))) {
  11491         /* We need to swap the labels configured in tunnel initiator as
  11492          * it returns labels in reverse order than how it should be in pkt.
  11493          */
  11494         for (i = 0; i < (label_count / 2); i++) {
  11495             sal_memcpy(&tmp_label, &label_array[i], sizeof(tmp_label));
  11496             sal_memcpy(&label_array[i], &label_array[label_count - 1 - i],
  11497                        sizeof(tmp_label));
  11498             sal_memcpy(&label_array[label_count - 1 - i], &tmp_label,
  11499                        sizeof(tmp_label));
  11500         }
  11501 
  11502         /* Add VRL Label */
  11503         if (h_data_p->type == bcmOAMEndpointTypeBHHMPLS) {
  11504             if ((l3_egress.mpls_label != BCM_MPLS_LABEL_INVALID) &&
  11505                 (h_data_p->egr_label != BCM_MPLS_LABEL_INVALID)  &&
  11506                 (label_count < _BHH_MPLS_MAX_LABELS) ) {
  11507 
  11508                 label_array[label_count].label = l3_egress.mpls_label;
  11509                 label_array[label_count].exp = l3_egress.mpls_exp;
  11510                 label_array[label_count].ttl = l3_egress.mpls_ttl;
  11511                 label_count++;
  11512             }
  11513             /* Traverse through Label stack and match on control label, this
  11514              * label should be the one just above GAL in the label stack, any
  11515              * following labels should not be added.
  11516              */
  11517             for (i = 0;  i < label_count; i++) {
  11518                 if (label_array[i].label == h_data_p->egr_label) {
  11519                     label_count = i + 1;
  11520                     label_array[i].exp = h_data_p->egr_label_exp;
  11521                     if (soc_property_get(unit, spn_MPLS_OAM_EGRESS_LABEL_TTL, 0) &&
  11522                         h_data_p->egr_label_ttl) {
  11523                         label_array[i].ttl = h_data_p->egr_label_ttl;
  11524                     }
  11525                     break;
  11526                 }
  11527             }
  11528         }
  11529     }
  11530 
  11531         /* MPLS Router Alert */
  11532     if (packet_flags & _BHH_ENCAP_PKT_MPLS_ROUTER_ALERT) {
  11533         /* Ignore overrun error as RAL is only added for PW MEPs and so overrun
  11534          * condition will not exist.
  11535          */
  11536         /* coverity[overrun-local] */
  11537         label_array[label_count].label = SHR_BHH_MPLS_ROUTER_ALERT_LABEL;
  11538         label_array[label_count].exp = 0;
  11539         label_array[label_count].ttl = 0;
  11540         label_count++;
  11541     }
  11542 
  11543     /* Use GPORT to resolve interface */
  11544     if (BCM_GPORT_IS_MPLS_PORT(h_data_p->gport)) {
  11545         /* Get mpls port and label info */
  11546         bcm_mpls_port_t_init(&mpls_port);
  11547         mpls_port.mpls_port_id = h_data_p->gport;
  11548         if (BCM_FAILURE(bcm_esw_mpls_port_get(unit, h_data_p->vpn,
  11549                                               &mpls_port))) {
  11550             return (BCM_E_PARAM);
  11551         }
  11552         if (h_data_p->type == bcmOAMEndpointTypeBHHMPLSVccv &&
  11553             h_data_p->vccv_type == bcmOamBhhVccvTtl) {
  11554             mpls_port.egress_label.ttl = 0x1;
  11555         }
  11556         label_array[label_count].label = mpls_port.egress_label.label;
  11557         if (h_data_p->egr_label == mpls_port.egress_label.label) {
  11558             label_array[label_count].exp = h_data_p->egr_label_exp;
  11559             if (soc_property_get(unit, spn_MPLS_OAM_EGRESS_LABEL_TTL, 0) &&
  11560                 h_data_p->egr_label_ttl) {
  11561                 label_array[label_count].ttl = h_data_p->egr_label_ttl;
  11562             }
  11563         } else {
  11564             label_array[label_count].exp   = mpls_port.egress_label.exp;
  11565             label_array[label_count].ttl   = mpls_port.egress_label.ttl;
  11566         }
  11567         label_count++;
  11568     }
  11569 
  11570     for (i=0;  i < label_count; i++) {
  11571         _bcm_tr3_oam_bhh_mpls_label_get(label_array[i].label,
  11572                                         label_array[i].exp,
  11573                                         0,
  11574                                         label_array[i].ttl,
  11575                                         &mpls[count++]);
  11576     }
  11577 
  11578     /* Set Bottom of Stack if there is no GAL label */
  11579     if (!(packet_flags & _BHH_ENCAP_PKT_GAL)) {
  11580         mpls[count-1].s = 1;
  11581     }
  11582 
  11583     *mpls_count = count;
  11584 
  11585     return (BCM_E_NONE);
  11586 
  11587 }
  11588 
  11589 STATIC int
  11590 _bcm_tr3_oam_bhh_l2_header_get(int unit, _bcm_oam_hash_data_t *h_data_p,
  11591                                 bcm_port_t port, uint16 etype,
  11592                                 _l2_header_t *l2)
  11593 {
  11594     uint16 tpid;
  11595     bcm_l3_egress_t l3_egress;
  11596     bcm_l3_intf_t l3_intf;
  11597     bcm_vlan_control_vlan_t vc;
  11598     int tpid_select;
  11599     bcm_pbmp_t pbmp, ubmp;
  11600 
  11601     sal_memset(l2, 0, sizeof(*l2));
  11602     /* Get L3 interfaces */
  11603     bcm_l3_egress_t_init(&l3_egress);
  11604     bcm_l3_intf_t_init(&l3_intf);
  11605 
  11606     if (BCM_FAILURE
  11607         (bcm_esw_l3_egress_get(unit, h_data_p->egress_if, &l3_egress))) {
  11608         return (BCM_E_PARAM);
  11609     }
  11610 
  11611     l3_intf.l3a_intf_id = l3_egress.intf;
  11612     if (BCM_FAILURE(bcm_esw_l3_intf_get(unit, &l3_intf))) {
  11613         return (BCM_E_PARAM);
  11614     }
  11615 
  11616     /* Get TPID */
  11617     BCM_IF_ERROR_RETURN(bcm_esw_vlan_control_port_get(unit,
  11618                                                       port,
  11619                                                       bcmVlanPortOuterTpidSelect,
  11620                                                       &tpid_select));
  11621     if (tpid_select == BCM_PORT_OUTER_TPID) {
  11622         BCM_IF_ERROR_RETURN(bcm_esw_port_tpid_get(unit, port, &tpid));
  11623     } else {
  11624         BCM_IF_ERROR_RETURN(
  11625                      bcm_esw_vlan_control_vlan_get(unit, l3_intf.l3a_vid, &vc));
  11626         tpid = vc.outer_tpid;
  11627     }
  11628 
  11629     sal_memcpy(l2->dst_mac, l3_egress.mac_addr, _BHH_MAC_ADDR_LENGTH);
  11630     sal_memcpy(l2->src_mac, l3_intf.l3a_mac_addr, _BHH_MAC_ADDR_LENGTH);
  11631     l2->vlan_tag.tpid     = tpid;
  11632     l2->vlan_tag.tci.prio = h_data_p->vlan_pri;
  11633     l2->vlan_tag.tci.cfi  = 0;
  11634     l2->vlan_tag.tci.vid  = l3_intf.l3a_vid;
  11635 
  11636     BCM_IF_ERROR_RETURN(bcm_esw_vlan_port_get(unit,
  11637                                               l2->vlan_tag.tci.vid,
  11638                                               &pbmp,
  11639                                               &ubmp));
  11640     if (BCM_PBMP_MEMBER(ubmp, port)) {
  11641         l2->vlan_tag.tpid = 0;  /* Set to 0 to indicate untagged */
  11642     }
  11643 
  11644     if (l3_intf.l3a_inner_vlan != 0) {
  11645         BCM_IF_ERROR_RETURN(bcm_esw_port_inner_tpid_get(unit, port, &tpid));
  11646         l2->vlan_tag_inner.tpid     = tpid;
  11647         l2->vlan_tag_inner.tci.prio = h_data_p->inner_vlan_pri;
  11648         l2->vlan_tag_inner.tci.cfi  = 0;
  11649         l2->vlan_tag_inner.tci.vid  = l3_intf.l3a_inner_vlan;
  11650     }
  11651     l2->etype             = etype;
  11652 
  11653     return BCM_E_NONE;
  11654 }
  11655 STATIC uint8 *
  11656 _bcm_tr3_oam_bhh_ach_header_pack(uint8 *buffer, _ach_header_t *ach)
  11657 {
  11658     uint32  tmp;
  11659 
  11660     tmp = ((ach->f_nibble & 0xf) << 28) | ((ach->version & 0xf) << 24) |
  11661         (ach->reserved << 16) | ach->channel_type;
  11662 
  11663     _BHH_ENCAP_PACK_U32(buffer, tmp);
  11664 
  11665     return (buffer);
  11666 }
  11667 
  11668 STATIC uint8 *
  11669 _bcm_tr3_oam_bhh_mpls_label_pack(uint8 *buffer, _mpls_label_t *mpls)
  11670 {
  11671     uint32  tmp;
  11672 
  11673     tmp = ((mpls->label & 0xfffff) << 12) | ((mpls->exp & 0x7) << 9) |
  11674         ((mpls->s & 0x1) << 8) | mpls->ttl;
  11675     _BHH_ENCAP_PACK_U32(buffer, tmp);
  11676 
  11677     return (buffer);
  11678 }
  11679 
  11680 STATIC uint8 *
  11681 _bcm_tr3_oam_bhh_l2_header_pack(uint8 *buffer, _l2_header_t *l2)
  11682 {
  11683     uint32  tmp;
  11684     int     i;
  11685 
  11686     for (i = 0; i < _BHH_MAC_ADDR_LENGTH; i++) {
  11687         _BHH_ENCAP_PACK_U8(buffer, l2->dst_mac[i]);
  11688     }
  11689 
  11690     for (i = 0; i < _BHH_MAC_ADDR_LENGTH; i++) {
  11691         _BHH_ENCAP_PACK_U8(buffer, l2->src_mac[i]);
  11692     }
  11693 
  11694     /* Vlan Tag tpid = 0 indicates untagged */
  11695     if (0 != l2->vlan_tag.tpid) {
  11696         tmp =  (l2->vlan_tag.tpid            << 16) |
  11697               ((l2->vlan_tag.tci.prio & 0x7) << 13) |
  11698               ((l2->vlan_tag.tci.cfi  & 0x1) << 12) |
  11699                (l2->vlan_tag.tci.vid  & 0xfff);
  11700         _BHH_ENCAP_PACK_U32(buffer, tmp);
  11701     }
  11702 
  11703     /*Inner Vlan Tag inner_tpid = 0 indicates single tag  */
  11704     if (0 != l2->vlan_tag_inner.tpid) {
  11705         tmp = (l2->vlan_tag_inner.tpid            << 16) |
  11706              ((l2->vlan_tag_inner.tci.prio & 0x7) << 13) |
  11707              ((l2->vlan_tag_inner.tci.cfi  & 0x1) << 12) |
  11708               (l2->vlan_tag_inner.tci.vid  & 0xfff);
  11709         _BHH_ENCAP_PACK_U32(buffer, tmp);
  11710     }
  11711     _BHH_ENCAP_PACK_U16(buffer, l2->etype);
  11712 
  11713     return (buffer);
  11714 }
  11715 /*
  11716  * Function:
  11717  *      _bcm_tr3_oam_bhh_encap_build_pack
  11718  * Purpose:
  11719  *      Builds and packs the BHH packet encapsulation for a given
  11720  *      BHH tunnel type.
  11721  * Parameters:
  11722  *      unit            - (IN) Unit number.
  11723  *      port            - (IN) Port.
  11724  *      endpoint_config - (IN/OUT) Pointer to BHH endpoint structure.
  11725  *      packet_flags    - (IN) Flags for building packet.
  11726  *      buffer          - (OUT) Buffer returning BHH encapsulation.
  11727  * Returns:
  11728  *      BCM_E_XXX
  11729  * Notes:
  11730  *      The returning BHH encapsulation includes only all the
  11731  *      encapsulation headers/labels and does not include
  11732  *      the BHH control packet.
  11733  */
  11734 STATIC int
  11735 _bcm_tr3_oam_bhh_encap_build_pack(int unit, bcm_port_t port,
  11736                              _bcm_oam_hash_data_t *h_data_p,
  11737                              uint32 packet_flags,
  11738                              uint8 *buffer,
  11739                             uint32 *encap_length)
  11740 {
  11741     uint8          *cur_ptr = buffer;
  11742     uint16         etype = 0;
  11743     bcm_if_t       l3_intf_id = -1;
  11744     _ach_header_t  ach;
  11745     _mpls_label_t  mpls_gal;
  11746     _mpls_label_t  mpls_labels[_BHH_MPLS_MAX_LABELS];
  11747     _mpls_label_t  pw_label;
  11748     int            mpls_count = 0;
  11749     _l2_header_t   l2;
  11750     int i;
  11751 
  11752 
  11753     /*
  11754      * Get necessary headers/labels information.
  11755      *
  11756      * Following order is important since some headers/labels
  11757      * may depend on previous header/label information.
  11758      */
  11759     if (packet_flags & _BHH_ENCAP_PKT_G_ACH) {
  11760         BCM_IF_ERROR_RETURN
  11761             (_bcm_tr3_oam_bhh_ach_header_get(packet_flags, &ach));
  11762     }
  11763 
  11764     if (packet_flags & _BHH_ENCAP_PKT_GAL) {
  11765         if (h_data_p->egr_label == SHR_BHH_MPLS_GAL_LABEL) {
  11766             BCM_IF_ERROR_RETURN
  11767                 (_bcm_tr3_oam_bhh_mpls_gal_label_get(&mpls_gal,
  11768                                                      h_data_p->egr_label_exp));
  11769         } else {
  11770             BCM_IF_ERROR_RETURN
  11771                 (_bcm_tr3_oam_bhh_mpls_gal_label_get(&mpls_gal, 0));
  11772         }
  11773     }
  11774 
  11775     if (packet_flags & _BHH_ENCAP_PKT_MPLS) {
  11776         etype = SHR_BHH_L2_ETYPE_MPLS_UCAST;
  11777         BCM_IF_ERROR_RETURN
  11778             (_bcm_tr3_oam_bhh_mpls_labels_get(unit, h_data_p,
  11779                                              packet_flags,    
  11780                                              _BHH_MPLS_MAX_LABELS,
  11781                                              &pw_label,
  11782                                              mpls_labels, 
  11783                                              &mpls_count,
  11784                                              &l3_intf_id));
  11785     }
  11786 
  11787     /* Always build L2 Header */
  11788     BCM_IF_ERROR_RETURN
  11789         (_bcm_tr3_oam_bhh_l2_header_get(unit, 
  11790                                        h_data_p,
  11791                                        port, 
  11792                                        etype, 
  11793                                        &l2));
  11794 
  11795     /*
  11796      * Pack header/labels into given buffer (network packet format).
  11797      *
  11798      * Following packing order must be followed to correctly
  11799      * build the packet encapsulation.
  11800      */
  11801     cur_ptr = buffer;
  11802 
  11803     /* L2 Header is always present */
  11804     cur_ptr = _bcm_tr3_oam_bhh_l2_header_pack(cur_ptr, &l2);
  11805 
  11806     if (packet_flags & _BHH_ENCAP_PKT_MPLS) {
  11807         for (i = 0;i < mpls_count;i++) {
  11808             cur_ptr = _bcm_tr3_oam_bhh_mpls_label_pack(cur_ptr, &mpls_labels[i]);
  11809         }
  11810     }
  11811 
  11812     if (packet_flags & _BHH_ENCAP_PKT_GAL) {    
  11813         cur_ptr = _bcm_tr3_oam_bhh_mpls_label_pack(cur_ptr, &mpls_gal);
  11814     }
  11815 
  11816     if (packet_flags & _BHH_ENCAP_PKT_G_ACH) {
  11817         cur_ptr = _bcm_tr3_oam_bhh_ach_header_pack(cur_ptr, &ach);
  11818     }
  11819 
  11820 
  11821     /* Set BHH encapsulation length */
  11822     *encap_length = cur_ptr - buffer;
  11823 
  11824     return (BCM_E_NONE);
  11825 }
  11826 
  11827 /*
  11828  * Function:
  11829  *      _bcm_tr3_oam_bhh_encap_create
  11830  * Purpose:
  11831  *      Creates a BHH packet encapsulation.
  11832  * Parameters:
  11833  *      unit            - (IN) Unit number.
  11834  *      port_id         - (IN) Port.
  11835  *      endpoint_config - (IN/OUT) Pointer to BHH endpoint structure.
  11836  *      encap_data      - (OUT) Buffer returning BHH encapsulation.
  11837  * Returns:
  11838  *      BCM_E_XXX
  11839  * Notes:
  11840  *      The returning BHH encapsulation buffer includes all the
  11841  *      corresponding headers/labels EXCEPT for the BHH control packet.
  11842  */
  11843 STATIC int
  11844 _bcm_tr3_oam_bhh_encap_create(int unit, bcm_port_t port_id,
  11845                          _bcm_oam_hash_data_t *h_data_p,
  11846                          uint8 *encap_data,
  11847                          uint8  *encap_type,
  11848                          uint32 *encap_length)
  11849 {
  11850     uint32 packet_flags;
  11851     _bcm_oam_control_t *oc;
  11852 
  11853     BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc));
  11854 
  11855     packet_flags = 0;
  11856 
  11857     /*
  11858      * Get BHH encapsulation packet format flags
  11859      *
  11860      * Also, perform the following for each BHH tunnel type:
  11861      * - Check for valid parameter values
  11862      * - Set specific values required by the BHH tunnel definition 
  11863      *   (e.g. such as ttl=1,...)
  11864      */
  11865     switch (h_data_p->type) {
  11866     case bcmOAMEndpointTypeBHHMPLS:
  11867         packet_flags |=
  11868             (_BHH_ENCAP_PKT_MPLS |
  11869              _BHH_ENCAP_PKT_GAL |
  11870              _BHH_ENCAP_PKT_G_ACH);
  11871         break;
  11872 
  11873     case bcmOAMEndpointTypeBHHMPLSVccv:
  11874         switch(h_data_p->vccv_type) {
  11875 
  11876         case bcmOamBhhVccvChannelAch:
  11877             packet_flags |=
  11878                 (_BHH_ENCAP_PKT_MPLS |
  11879                  _BHH_ENCAP_PKT_PW |
  11880                  _BHH_ENCAP_PKT_G_ACH);
  11881         break;
  11882 
  11883         case bcmOamBhhVccvRouterAlert:
  11884             packet_flags |=
  11885                 (_BHH_ENCAP_PKT_MPLS |
  11886                  _BHH_ENCAP_PKT_PW |
  11887                  _BHH_ENCAP_PKT_MPLS_ROUTER_ALERT |
  11888                  _BHH_ENCAP_PKT_G_ACH); 
  11889             break;
  11890 
  11891         case bcmOamBhhVccvTtl:
  11892             packet_flags |=
  11893                 (_BHH_ENCAP_PKT_MPLS |
  11894                  _BHH_ENCAP_PKT_PW |
  11895                  _BHH_ENCAP_PKT_G_ACH); 
  11896             break;
  11897 
  11898     case bcmOamBhhVccvGal13:
  11899             packet_flags |=
  11900                 (_BHH_ENCAP_PKT_MPLS |
  11901                  _BHH_ENCAP_PKT_PW |
  11902                  _BHH_ENCAP_PKT_GAL  |
  11903                  _BHH_ENCAP_PKT_G_ACH);
  11904             break;
  11905 
  11906     default:
  11907         return (BCM_E_PARAM);
  11908         break;
  11909     }
  11910         break;
  11911 
  11912     default:
  11913         return (BCM_E_PARAM);
  11914     }
  11915 
  11916     /* Build header/labels and pack in buffer */
  11917     BCM_IF_ERROR_RETURN
  11918         (_bcm_tr3_oam_bhh_encap_build_pack(unit, port_id,
  11919                                       h_data_p,
  11920                                       packet_flags,
  11921                                       encap_data,
  11922                                   encap_length));
  11923 
  11924     /* Set encap type (indicates uC side that checksum is required) */
  11925     *encap_type = SHR_BHH_ENCAP_TYPE_RAW;
  11926 #ifdef _BHH_DEBUG_DUMP
  11927     _bcm_tr3_oam_bhh_encap_data_dump(encap_data, *encap_length);
  11928 #endif
  11929 
  11930     if (*encap_length > oc->bhh_max_encap_length) {
  11931         LOG_ERROR(BSL_LS_BCM_OAM,
  11932                 (BSL_META_U(unit,
  11933                 "OAM(unit %d) Error: Encap length greater than max,"
  11934                 "encap_length=%u max=%u\n"),
  11935                  unit, *encap_length, oc->bhh_max_encap_length));
  11936         return BCM_E_CONFIG;
  11937     }
  11938 
  11939     return (BCM_E_NONE);
  11940 }
  11941 
  11942 /*
  11943  * Function:
  11944  *      _bcm_tr3_oam_bhh_appl_callback
  11945  * Purpose:
  11946  *      Update FW BHH appl state
  11947  * Parameters:
  11948  *      unit  - (IN) Unit number.
  11949  *      uC    - (IN) core number.
  11950  *      stage - (IN) core reset stage.
  11951  *      user_data - (IN) data pointer.
  11952  * Returns:
  11953  *      BCM_E_XXX
  11954  * Notes:
  11955  */
  11956 
  11957 int _bcm_tr3_oam_bhh_appl_callback(int unit,
  11958                                     int uC,
  11959                                     soc_cmic_uc_shutdown_stage_t stage,
  11960                                     void *user_data) {
  11961     _bcm_oam_control_t *oc;
  11962 
  11963     BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc));
  11964     _BCM_OAM_LOCK(oc);
  11965     oc->ukernel_not_ready = 1;
  11966 
  11967     _BCM_OAM_UNLOCK(oc);
  11968 
  11969     return BCM_E_NONE;
  11970 }
  11971 
  11972 /*
  11973  * Function:
  11974  *      bcm_tr3_oam_bhh_endpoint_create
  11975  * Purpose:
  11976  *      Initialize the HW for BHH packet processing.
  11977  *      Configure:
  11978  *      - Copy to CPU BHH error packets
  11979  *      - CPU COS Queue for BHH packets
  11980  *      - RX DMA channel
  11981  * Parameters:
  11982  *      unit - (IN) Unit number.
  11983  * Returns:
  11984  *      BCM_E_XXX
  11985  * Notes:
  11986  */
  11987 int
  11988 bcm_tr3_oam_bhh_endpoint_create(int unit, 
  11989                                 bcm_oam_endpoint_info_t *endpoint_info,
  11990                                 _bcm_oam_hash_key_t  *hash_key)
  11991 {
  11992     _bcm_oam_control_t *oc;
  11993     _bcm_oam_hash_data_t *hash_data = NULL; /* Endpoint hash data pointer.  */
  11994     _bcm_oam_group_data_t *group_p;  /* Pointer to group data.            */
  11995     int                  ep_req_index;      /* Requested endpoint index.    */
  11996     int                  rv = BCM_E_NONE;   /* Operation return status.     */
  11997     int                  is_remote = 0;        /* Remote endpoint status.   */
  11998     int                  is_replace;
  11999     uint32               sglp = 0;          /* Source global logical port.  */
  12000     uint32               dglp = 0;          /* Dest global logical port.    */
  12001     bcm_port_t           port_id;
  12002     bcm_trunk_t          trunk_id;
  12003     bcm_module_t         module_id;
  12004     bhh_sdk_msg_ctrl_sess_set_t msg_sess;
  12005     bhh_sdk_msg_ctrl_rmep_create_t msg_rmep_create;
  12006     uint8 *buffer, *buffer_ptr;
  12007     uint16 buffer_len, reply_len;
  12008     int encap = 0;
  12009     uint32 session_flags;
  12010     int bhh_pool_ep_idx = 0;
  12011     uint8 group_sw_rdi = 0;
  12012     bcm_gport_t tx_gport;
  12013 
  12014     LOG_DEBUG(BSL_LS_BCM_OAM,
  12015               (BSL_META_U(unit,
  12016                           "BHH Info: bcm_tr3_oam_bhh_endpoint_create"
  12017                            "Endpoint ID=%d.\n"), endpoint_info->id));
  12018 
  12019     _BCM_OAM_BHH_IS_VALID(unit);
  12020 
  12021     /* Validate input parameter. */
  12022     if (NULL == endpoint_info) {
  12023         return (BCM_E_PARAM);
  12024     }
  12025 
  12026     if ((endpoint_info->type == bcmOAMEndpointTypeBHHMPLSVccv) && 
  12027         (endpoint_info->vccv_type > bcmOamBhhVccvTtl))
  12028     {
  12029         LOG_ERROR(BSL_LS_BCM_OAM,
  12030                 (BSL_META_U(unit,
  12031                             "BHH Error: vccv type %d not supported (EP=%d)\n"),
  12032                  endpoint_info->vccv_type, endpoint_info->id));
  12033         return (BCM_E_PARAM);
  12034     }
  12035     /* Lock already taken by the calling routine. */
  12036     BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc));
  12037 
  12038     /* Get MEP remote endpoint status. */
  12039     is_remote = (endpoint_info->flags & BCM_OAM_ENDPOINT_REMOTE) ? 1 : 0;
  12040 
  12041 
  12042     is_replace = ((endpoint_info->flags & BCM_OAM_ENDPOINT_REPLACE) != 0);
  12043 
  12044     /* Validate EP Id if BCM_OAM_ENDPOINT_WITH_ID flag is set */
  12045     if (endpoint_info->flags & BCM_OAM_ENDPOINT_WITH_ID) {
  12046         if((endpoint_info->id < _BCM_OAM_BHH_ENDPOINT_OFFSET) ||
  12047            (endpoint_info->id >= (_BCM_OAM_BHH_ENDPOINT_OFFSET
  12048                                   + oc->bhh_endpoint_count))) {
  12049             return (BCM_E_PARAM);
  12050         }
  12051     }
  12052 
  12053     /* Validate remote EP Id if BCM_OAM_ENDPOINT_REMOTE flag is set */
  12054     if (is_remote) {
  12055         if((endpoint_info->local_id < _BCM_OAM_BHH_ENDPOINT_OFFSET) ||
  12056            (endpoint_info->local_id >= (_BCM_OAM_BHH_ENDPOINT_OFFSET
  12057                                         + oc->bhh_endpoint_count))) {
  12058             return (BCM_E_PARAM);
  12059         }
  12060     }
  12061 
  12062     if((endpoint_info->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT) ||
  12063         (endpoint_info->flags & BCM_OAM_ENDPOINT_DELAY_MEASUREMENT))
  12064     {
  12065         if (!oc->bhh_lm_dm_enable) {
  12066             LOG_ERROR(BSL_LS_BCM_OAM,
  12067                       (BSL_META_U(unit,
  12068                                   "BHH Error: LM/DM not enabled (EP=%d)\n"),
  12069                        endpoint_info->id));
  12070             return (BCM_E_DISABLED);
  12071         }
  12072     }
  12073 
  12074 
  12075     /* Create a new endpoint with the requested ID. */
  12076     if (endpoint_info->flags & BCM_OAM_ENDPOINT_WITH_ID) {
  12077         hash_data = &oc->oam_hash_data[endpoint_info->id];
  12078 
  12079         if (is_replace && !hash_data->in_use)
  12080         {
  12081             return (BCM_E_NOT_FOUND);
  12082         }
  12083         else if (!is_replace && hash_data->in_use)
  12084         {
  12085             return (BCM_E_EXISTS);
  12086         }
  12087 
  12088         ep_req_index = endpoint_info->id;
  12089         bhh_pool_ep_idx = BCM_OAM_BHH_GET_UKERNEL_EP(ep_req_index);
  12090 
  12091         if((ep_req_index < _BCM_OAM_BHH_ENDPOINT_OFFSET) ||
  12092            (ep_req_index >= (_BCM_OAM_BHH_ENDPOINT_OFFSET + oc->bhh_endpoint_count))) {
  12093             rv = BCM_E_PARAM;
  12094         }
  12095 
  12096         if(BCM_FAILURE(rv)) {
  12097             LOG_ERROR(BSL_LS_BCM_OAM,
  12098                       (BSL_META_U(unit,
  12099                                   "BHH Error: Endpoint check (EP=%d) - %s.\n"),
  12100                        endpoint_info->id, bcm_errmsg(rv)));
  12101             return (rv);
  12102         }
  12103 
  12104         if(!is_replace) {
  12105             rv = shr_idxres_list_reserve(oc->bhh_pool, bhh_pool_ep_idx,
  12106                                      bhh_pool_ep_idx);
  12107             if (BCM_FAILURE(rv)) {
  12108                 rv = (rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv;
  12109                 LOG_ERROR(BSL_LS_BCM_OAM,
  12110                           (BSL_META_U(unit,
  12111                                       "BHH Error: Endpoint reserve (EP=%d) - %s.\n"),
  12112                            endpoint_info->id, bcm_errmsg(rv)));
  12113                 return (rv);
  12114             }
  12115         }
  12116     } else {
  12117 
  12118         if (is_replace)
  12119         {
  12120             /* Replace specified with no ID */
  12121 
  12122             return (BCM_E_PARAM);
  12123         }
  12124 
  12125         /* BHH uses local and remote same index */
  12126         if(endpoint_info->flags & BCM_OAM_ENDPOINT_REMOTE) {
  12127             ep_req_index = endpoint_info->local_id;
  12128             bhh_pool_ep_idx = BCM_OAM_BHH_GET_UKERNEL_EP(ep_req_index);
  12129         }
  12130         else {
  12131             /* Allocate the next available endpoint index. */
  12132             rv = shr_idxres_list_alloc(oc->bhh_pool,
  12133                                    (shr_idxres_element_t *)&bhh_pool_ep_idx);
  12134             if (BCM_FAILURE(rv)) {
  12135                 rv = (rv == BCM_E_RESOURCE) ? (BCM_E_FULL) : rv;
  12136                 LOG_ERROR(BSL_LS_BCM_OAM,
  12137                           (BSL_META_U(unit,
  12138                                       "BHH Error: Endpoint alloc failed - %s.\n"),
  12139                            bcm_errmsg(rv)));
  12140                 return (rv);
  12141             }
  12142             /* Set the allocated endpoint id value. */
  12143             ep_req_index = BCM_OAM_BHH_GET_SDK_EP(bhh_pool_ep_idx);
  12144         }
  12145         endpoint_info->id =  ep_req_index;
  12146     }
  12147 
  12148     /* Get the hash data pointer where the data is to be stored. */
  12149     hash_data = &oc->oam_hash_data[ep_req_index];
  12150     group_p = &oc->group_info[endpoint_info->group];
  12151 
  12152     /*
  12153      *The uKernel is not provisioned until both endpoints (local and remote)
  12154      * are provisioned in the host.
  12155      */
  12156     if (is_remote) {
  12157 
  12158         if (!hash_data->in_use) {
  12159             return (BCM_E_NOT_FOUND);
  12160         } else if (hash_data->flags & BCM_OAM_ENDPOINT_REMOTE) {
  12161             return (BCM_E_EXISTS);
  12162         }
  12163 
  12164         /*
  12165          * Now that both ends are provisioned the uKernel can be 
  12166          * configured.
  12167          */
  12168         msg_rmep_create.sess_id = bhh_pool_ep_idx;
  12169         msg_rmep_create.flags = 0;
  12170         msg_rmep_create.enable = 1;
  12171         msg_rmep_create.remote_mep_id = endpoint_info->name;
  12172         msg_rmep_create.period = _tr3_ccm_intervals[
  12173                    _bcm_tr3_oam_ccm_msecs_to_hw_encode(endpoint_info->ccm_period)];
  12174 
  12175         /* Pack control message data into DMA buffer */
  12176         buffer     = oc->dma_buffer;
  12177         buffer_ptr = bhh_sdk_msg_ctrl_rmep_create_pack(buffer, &msg_rmep_create);
  12178         buffer_len = buffer_ptr - buffer;
  12179 
  12180         /* Send BHH Session Update message to uC */
  12181         rv = _bcm_tr3_oam_bhh_msg_send_receive(unit,
  12182                           MOS_MSG_SUBCLASS_BHH_RMEP_CREATE,
  12183                           buffer_len, 0,
  12184                           MOS_MSG_SUBCLASS_BHH_RMEP_CREATE_REPLY,
  12185                           &reply_len, _BHH_UC_MSG_TIMEOUT_USECS);
  12186         if (BCM_FAILURE(rv) || (reply_len != 0)) {
  12187             LOG_ERROR(BSL_LS_BCM_OAM,
  12188                       (BSL_META_U(unit,
  12189                                   "BHH Error: Endpoint destroy (EP=%d) - %s.\n"),
  12190                        endpoint_info->id, bcm_errmsg(rv)));
  12191             return (BCM_E_INTERNAL);
  12192         }
  12193     } else {
  12194 
  12195         /* Get the Trunk, Port and Modid info for this Gport */
  12196         BCM_IF_ERROR_RETURN(
  12197                    _bcm_tr3_oam_endpoint_gport_resolve(unit, endpoint_info,
  12198                                                        &sglp, &dglp, &trunk_id,
  12199                                                        &tx_gport));
  12200         port_id = BCM_GPORT_MODPORT_PORT_GET(tx_gport);
  12201         module_id = BCM_GPORT_MODPORT_MODID_GET(tx_gport);
  12202 
  12203         /* Clear the hash data element contents before storing the values. */
  12204         _BCM_OAM_HASH_DATA_CLEAR(hash_data);
  12205         hash_data->type = endpoint_info->type;
  12206         hash_data->ep_id = endpoint_info->id;
  12207         hash_data->group_index = endpoint_info->group;
  12208         hash_data->level = endpoint_info->level;
  12209         hash_data->vlan = endpoint_info->vlan;
  12210         hash_data->vlan_pri = endpoint_info->pkt_pri;
  12211         hash_data->inner_vlan_pri = endpoint_info->inner_pkt_pri;
  12212         hash_data->gport = endpoint_info->gport;
  12213         hash_data->trunk_index = endpoint_info->trunk_index;
  12214         hash_data->sglp = sglp;
  12215         hash_data->dglp = dglp;
  12216         hash_data->flags = endpoint_info->flags;
  12217         hash_data->period = endpoint_info->ccm_period;
  12218         hash_data->vccv_type = endpoint_info->vccv_type;
  12219         hash_data->vpn  = endpoint_info->vpn;
  12220         hash_data->name      = endpoint_info->name;
  12221         hash_data->egress_if = endpoint_info->intf_id;
  12222         hash_data->cpu_qid   = endpoint_info->cpu_qid;
  12223         hash_data->label     = endpoint_info->mpls_label;
  12224         hash_data->gport     = endpoint_info->gport;
  12225         hash_data->flags     = endpoint_info->flags;
  12226         hash_data->local_tx_enabled = 0;
  12227         hash_data->local_rx_enabled = 0;
  12228         hash_data->egr_label = endpoint_info->egress_label.label;
  12229         hash_data->egr_label_exp = endpoint_info->egress_label.exp;
  12230         hash_data->egr_label_ttl = endpoint_info->egress_label.ttl;
  12231 
  12232         /* Initialize hardware index as invalid indices. */
  12233         hash_data->local_tx_index = _BCM_OAM_INVALID_INDEX;
  12234         hash_data->local_rx_index = _BCM_OAM_INVALID_INDEX;
  12235         hash_data->remote_index = _BCM_OAM_INVALID_INDEX;
  12236 
  12237 #if 0
  12238     /* hash collision!!! Is this needed for BHH? */
  12239         rv = shr_htb_insert(oc->ma_mep_htbl, hash_key, hash_data);
  12240         if (BCM_FAILURE(rv)) {
  12241             LOG_ERROR(BSL_LS_BCM_OAM,
  12242                       (BSL_META_U(unit,
  12243                                   "BHH Error: Hash table insert failed EP=%d %s.\n"),
  12244                        endpoint_info->id, bcm_errmsg(rv)));
  12245             return (rv);
  12246         }
  12247 #endif
  12248 
  12249         /* Create or Update */
  12250         session_flags = (is_replace) ? 0 : SHR_BHH_SESS_SET_F_CREATE;
  12251 
  12252         /* Set Endpoint config entry */
  12253         hash_data->bhh_endpoint_index = ep_req_index;
  12254 
  12255         /* Set Encapsulation in HW */
  12256         if (!is_replace || (endpoint_info->flags & BCM_BHH_ENDPOINT_ENCAP_SET)) {
  12257             rv = _bcm_tr3_oam_bhh_encap_hw_set(unit, hash_data, module_id,
  12258                           port_id, 1, endpoint_info);
  12259             if(BCM_FAILURE(rv)) {
  12260                 /* Return ID back to free MEP ID pool.*/
  12261                 BCM_IF_ERROR_RETURN(shr_idxres_list_free(oc->bhh_pool, bhh_pool_ep_idx));
  12262                 LOG_ERROR(BSL_LS_BCM_OAM,
  12263                           (BSL_META_U(unit,
  12264                                       "BHH Error: Encap set fail (EP=%d) - %s.\n"),
  12265                            endpoint_info->id, bcm_errmsg(rv)));
  12266                 return (rv);
  12267             }
  12268             encap = 1;
  12269         }
  12270 
  12271         /* Set control message data */
  12272         sal_memset(&msg_sess, 0, sizeof(msg_sess));
  12273 
  12274         /*
  12275          * Set the BHH encapsulation data
  12276          *
  12277          * The function _bcm_tr3_oam_bhh_encap_create() is called first
  12278          * since this sets some fields in 'hash_data' which are
  12279          * used in the message.
  12280          */
  12281         if (encap) {
  12282             rv = _bcm_tr3_oam_bhh_encap_create(unit,
  12283                     port_id,
  12284                     hash_data,
  12285                     msg_sess.encap_data,
  12286                     &msg_sess.encap_type,
  12287                     &msg_sess.encap_length);
  12288 
  12289             if(BCM_FAILURE(rv))
  12290             {
  12291                 /* Return ID back to free MEP ID pool.*/
  12292                 BCM_IF_ERROR_RETURN(shr_idxres_list_free(oc->bhh_pool, bhh_pool_ep_idx));
  12293                 LOG_ERROR(BSL_LS_BCM_OAM,
  12294                           (BSL_META_U(unit,
  12295                                       "BHH Error: Endpoint destroy (EP=%d) - %s.\n"),
  12296                            endpoint_info->id, bcm_errmsg(rv)));
  12297                 return (rv);
  12298             }
  12299         }
  12300 
  12301         /*
  12302          * Endpoint can be one of: CCM, LB, LM or DM. The default is CCM,
  12303          * all others modes must be specified via a config flag.
  12304  */
  12305         if (endpoint_info->flags & BCM_OAM_ENDPOINT_LOOPBACK)
  12306             session_flags |= SHR_BHH_SESS_SET_F_LB;
  12307         else if (endpoint_info->flags & BCM_OAM_ENDPOINT_DELAY_MEASUREMENT)
  12308             session_flags |= SHR_BHH_SESS_SET_F_DM;
  12309         else if (endpoint_info->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT)
  12310             session_flags |= SHR_BHH_SESS_SET_F_LM;
  12311         else
  12312             session_flags |= SHR_BHH_SESS_SET_F_CCM;
  12313 
  12314         if (endpoint_info->flags & BCM_OAM_ENDPOINT_INTERMEDIATE)
  12315             session_flags |= SHR_BHH_SESS_SET_F_MIP;
  12316 
  12317         _bcm_tr3_oam_get_group_sw_rdi (unit, endpoint_info->group,
  12318                 &group_sw_rdi);
  12319         if (group_sw_rdi) {
  12320             session_flags |= SHR_BHH_SESS_SET_F_RDI;
  12321         }
  12322         /*
  12323            if (!local_tx_enabled)
  12324            session_flags |= SHR_BHH_SESS_SET_F_PASSIVE;*/
  12325 
  12326         msg_sess.sess_id = bhh_pool_ep_idx;
  12327         msg_sess.flags   = session_flags;
  12328 
  12329         msg_sess.mel     = hash_data->level;
  12330         msg_sess.mep_id  = hash_data->name;
  12331         sal_memcpy(msg_sess.meg_id, group_p->name, BCM_OAM_GROUP_NAME_LENGTH);
  12332 
  12333         msg_sess.period = _tr3_ccm_intervals[
  12334             _bcm_tr3_oam_ccm_msecs_to_hw_encode(endpoint_info->ccm_period)];
  12335         msg_sess.if_num  = endpoint_info->intf_id;
  12336         msg_sess.tx_port = port_id;
  12337         if (BCM_TRUNK_INVALID == trunk_id) {
  12338             msg_sess.rx_port = port_id;
  12339         } else {
  12340             msg_sess.rx_port = trunk_id;
  12341             msg_sess.trunk_valid = 1;
  12342         }
  12343         msg_sess.tx_cos  = endpoint_info->int_pri;
  12344         msg_sess.tx_pri  = endpoint_info->pkt_pri;
  12345         msg_sess.tx_qnum = SOC_INFO(unit).port_uc_cosq_base[port_id] + endpoint_info->int_pri;
  12346         msg_sess.lm_counter_index =
  12347             hash_data->lm_counter_index | _BCM_OAM_LM_COUNTER_TX_OFFSET;
  12348 
  12349         msg_sess.mpls_label = endpoint_info->mpls_label;
  12350 
  12351         switch (endpoint_info->type) {
  12352         case bcmOAMEndpointTypeBHHMPLS:
  12353             msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_LSP;
  12354             msg_sess.priority   = endpoint_info->mpls_exp;
  12355             break;
  12356 
  12357         case bcmOAMEndpointTypeBHHMPLSVccv:
  12358             switch(endpoint_info->vccv_type) {
  12359 
  12360             case bcmOamBhhVccvChannelAch:
  12361                 msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_PW_VCCV_1;
  12362                 msg_sess.priority   = endpoint_info->mpls_exp;
  12363                 break;
  12364 
  12365             case bcmOamBhhVccvRouterAlert:
  12366                 msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_PW_VCCV_2;
  12367                 msg_sess.priority   = endpoint_info->mpls_exp;
  12368                 break;
  12369 
  12370             case bcmOamBhhVccvTtl:
  12371                 msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_PW_VCCV_3;
  12372                 msg_sess.priority   = endpoint_info->mpls_exp;
  12373                 break;
  12374 
  12375             case bcmOamBhhVccvGal13:
  12376                 msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_PW_VCCV_4;
  12377                 msg_sess.priority   = endpoint_info->mpls_exp;
  12378                 break;
  12379 
  12380             default:
  12381                 return BCM_E_PARAM;
  12382                 break;
  12383             }
  12384             break;
  12385 
  12386         case bcmOAMEndpointTypeBhhSection:
  12387             msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_PORT_SECTION;
  12388             msg_sess.priority   = 0;
  12389             break;
  12390         case bcmOAMEndpointTypeBhhSectionInnervlan:
  12391             msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_PORT_SECTION_INNERVLAN;
  12392             msg_sess.priority   = endpoint_info->inner_pkt_pri;
  12393             break;
  12394         case bcmOAMEndpointTypeBhhSectionOuterVlan:
  12395             msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_PORT_SECTION_OUTERVLAN;
  12396             msg_sess.priority   = endpoint_info->pkt_pri;
  12397             break;
  12398         case bcmOAMEndpointTypeBhhSectionOuterPlusInnerVlan:
  12399             msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_PORT_SECTION_OUTER_PLUS_INNERVLAN;
  12400             msg_sess.priority   = endpoint_info->pkt_pri;
  12401             break;
  12402 
  12403         default:
  12404             return BCM_E_PARAM;
  12405         }
  12406 
  12407         /* Pack control message data into DMA buffer */
  12408         buffer     = oc->dma_buffer;
  12409         buffer_ptr = bhh_sdk_msg_ctrl_sess_set_pack(buffer, &msg_sess);
  12410         buffer_len = buffer_ptr - buffer;
  12411 
  12412         /* Send BHH Session Update message to uC */
  12413         rv = _bcm_tr3_oam_bhh_msg_send_receive(unit,
  12414                 MOS_MSG_SUBCLASS_BHH_SESS_SET,
  12415                 buffer_len, 0,
  12416                 MOS_MSG_SUBCLASS_BHH_SESS_SET_REPLY,
  12417                 &reply_len, _BHH_UC_MSG_TIMEOUT_USECS);
  12418         if (BCM_FAILURE(rv) || (reply_len != 0)) {
  12419             /* Return ID back to free MEP ID pool.*/
  12420             BCM_IF_ERROR_RETURN(shr_idxres_list_free(oc->bhh_pool, bhh_pool_ep_idx));
  12421             LOG_ERROR(BSL_LS_BCM_OAM,
  12422                       (BSL_META_U(unit,
  12423                                   "BHH Error: Endpoint destroy (EP=%d) - %s.\n"),
  12424                        endpoint_info->id, bcm_errmsg(rv)));
  12425             return (rv);
  12426         }
  12427 
  12428         if (!is_replace) {
  12429             rv = _bcm_oam_group_ep_list_add(unit, endpoint_info->group,
  12430                     endpoint_info->id);
  12431         }
  12432 
  12433         if (BCM_FAILURE(rv)) {
  12434             /* Return ID back to free MEP ID pool.*/
  12435             BCM_IF_ERROR_RETURN(shr_idxres_list_free(oc->bhh_pool, bhh_pool_ep_idx));
  12436             LOG_ERROR(BSL_LS_BCM_OAM,
  12437                     (BSL_META_U(unit,
  12438                                 "OAM Error: Tx config failed for EP=%d %s.\n"),
  12439                      endpoint_info->id, bcm_errmsg(rv)));
  12440             return (rv);
  12441         }
  12442     }
  12443     hash_data->in_use = 1;
  12444 
  12445 #ifdef BCM_WARM_BOOT_SUPPORT
  12446     SOC_CONTROL_LOCK(unit);
  12447     SOC_CONTROL(unit)->scache_dirty = 1;
  12448     SOC_CONTROL_UNLOCK(unit);
  12449 #endif
  12450 
  12451     return (rv);
  12452 }
  12453 
  12454 /*
  12455  * Function:
  12456  *      _bcm_tr3_oam_bhh_fp_init
  12457  * Purpose:
  12458  *      Initialize the fp for BHH LM/DM packet processing.
  12459  *      Configure:
  12460  *      - Qualifiers QSET
  12461  *      - Create Groups
  12462  * Parameters:
  12463  *      unit - (IN) Unit number.
  12464  *      oc   - (IN) OAM control structure.
  12465  * Returns:
  12466  *      BCM_E_XXX
  12467  * Notes:
  12468  */
  12469 STATIC int
  12470 _bcm_tr3_oam_bhh_fp_init(int unit)
  12471 {
  12472     int                   rv = BCM_E_NONE;
  12473     _bcm_oam_control_t   *oc;
  12474 
  12475     /* Lock already taken by the calling routine. */
  12476     BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc));
  12477 
  12478     BCM_FIELD_QSET_INIT(oc->bhh_lmdm_qset);
  12479     BCM_FIELD_QSET_ADD(oc->bhh_lmdm_qset, bcmFieldQualifySrcPort);
  12480     BCM_FIELD_QSET_ADD(oc->bhh_lmdm_qset, bcmFieldQualifySrcTrunk);
  12481     BCM_FIELD_QSET_ADD(oc->bhh_lmdm_qset, bcmFieldQualifyDstPort);
  12482     BCM_FIELD_QSET_ADD(oc->bhh_lmdm_qset, bcmFieldQualifyDstTrunk);
  12483     BCM_FIELD_QSET_ADD(oc->bhh_lmdm_qset, bcmFieldQualifyOuterVlanId);
  12484     BCM_FIELD_QSET_ADD(oc->bhh_lmdm_qset, bcmFieldQualifyDstL3Egress);
  12485 
  12486 
  12487     if (oc->bhh_udf_mode) { /* Configure UDF using bcm_udf_xxx() APIs */
  12488         bcm_udf_alloc_hints_t      hints;
  12489         bcm_udf_t                  label;
  12490         bcm_udf_t                  ach;
  12491         bcm_udf_t                  opcode;
  12492         bcm_udf_pkt_format_info_t  pkt_fmt;
  12493 
  12494         bcm_udf_pkt_format_info_t_init(&pkt_fmt);
  12495         pkt_fmt.prio            = 0xffff; /* Highest priority */
  12496         pkt_fmt.l2              = BCM_PKT_FORMAT_L2_ANY;
  12497         pkt_fmt.vlan_tag        = BCM_PKT_FORMAT_VLAN_TAG_ANY;
  12498         pkt_fmt.tunnel          = BCM_PKT_FORMAT_TUNNEL_MPLS;
  12499         pkt_fmt.mpls            = BCM_PKT_FORMAT_MPLS_ANY;
  12500         BCM_IF_ERROR_RETURN(
  12501                  bcm_esw_udf_pkt_format_create(unit,
  12502                                                BCM_UDF_PKT_FORMAT_CREATE_O_NONE,
  12503                                                &pkt_fmt,
  12504                                                &(oc->bhh_udf_pkt_fmt_id)));
  12505 
  12506         bcm_udf_alloc_hints_t_init (&hints);
  12507         hints.flags = BCM_UDF_CREATE_O_FIELD_INGRESS;
  12508         hints.qset = oc->bhh_lmdm_qset;
  12509 
  12510         /* Match MPLS label */
  12511         bcm_udf_t_init(&label);
  12512         label.layer = bcmUdfLayerL3OuterHeader;
  12513         label.start = 0;
  12514         label.width = SHR_BHH_MPLS_LABEL_LENGTH * 8;  /* Convert to bits */
  12515 
  12516 
  12517         BCM_IF_ERROR_RETURN(bcm_esw_udf_create(unit,
  12518                                                &hints,
  12519                                                &label,
  12520                                                &(oc->bhh_label_udf_id)));
  12521 
  12522         BCM_IF_ERROR_RETURN(
  12523                     bcm_esw_udf_pkt_format_add(unit,
  12524                                                oc->bhh_label_udf_id,
  12525                                                oc->bhh_udf_pkt_fmt_id));
  12526         BCM_IF_ERROR_RETURN(
  12527                    bcm_esw_field_qset_id_multi_set(unit,
  12528                                                    bcmFieldQualifyUdf,
  12529                                                    1,
  12530                                                    &(oc->bhh_label_udf_id),
  12531                                                    &hints.qset));
  12532 
  12533         /* Match ACH channel type 0x8902 */
  12534         bcm_udf_t_init(&ach);
  12535         ach.layer = bcmUdfLayerL3OuterHeader;
  12536         ach.start = 10 * 8;     /* Convert to bits*/
  12537         ach.width = SHR_BHH_ACH_TYPE_LENGTH * 8;
  12538 
  12539         BCM_IF_ERROR_RETURN(bcm_esw_udf_create(unit,
  12540                                                &hints,
  12541                                                &ach,
  12542                                                &(oc->bhh_ach_udf_id)));
  12543 
  12544         BCM_IF_ERROR_RETURN(
  12545                     bcm_esw_udf_pkt_format_add(unit,
  12546                                                oc->bhh_ach_udf_id,
  12547                                                oc->bhh_udf_pkt_fmt_id));
  12548         BCM_IF_ERROR_RETURN(
  12549                    bcm_esw_field_qset_id_multi_set(unit,
  12550                                                    bcmFieldQualifyUdf,
  12551                                                    1,
  12552                                                    &(oc->bhh_ach_udf_id),
  12553                                                    &hints.qset));
  12554 
  12555 
  12556         /* Match opcode 45 or 46 or 47 */
  12557         bcm_udf_t_init(&opcode);
  12558         opcode.layer = bcmUdfLayerL3OuterHeader;
  12559         opcode.start = 13 * 8;  /* Convert to bits*/
  12560         opcode.width = SHR_BHH_OPCODE_LEN * 8;
  12561 
  12562         BCM_IF_ERROR_RETURN(bcm_esw_udf_create(unit,
  12563                                                &hints,
  12564                                                &opcode,
  12565                                                &(oc->bhh_opcode_udf_id)));
  12566 
  12567         BCM_IF_ERROR_RETURN(bcm_esw_udf_pkt_format_add(unit,
  12568                                                        oc->bhh_opcode_udf_id,
  12569                                                        oc->bhh_udf_pkt_fmt_id));
  12570         BCM_IF_ERROR_RETURN(
  12571                    bcm_esw_field_qset_id_multi_set(unit,
  12572                                                    bcmFieldQualifyUdf,
  12573                                                    1,
  12574                                                    &(oc->bhh_opcode_udf_id),
  12575                                                    &hints.qset));
  12576         oc->bhh_lmdm_qset = hints.qset;
  12577 
  12578     } else { /* Configure UDF using bcm_field_xxx() APIs */
  12579 
  12580         bcm_field_data_packet_format_t  pkt_fmt;
  12581         bcm_field_data_qualifier_t      label;
  12582         bcm_field_data_qualifier_t      ach;
  12583         bcm_field_data_qualifier_t      opcode;
  12584 
  12585         bcm_field_data_packet_format_t_init(&pkt_fmt);
  12586         pkt_fmt.relative_offset = 0;
  12587         pkt_fmt.l2              = BCM_FIELD_DATA_FORMAT_L2_ANY;
  12588         pkt_fmt.vlan_tag        = BCM_FIELD_DATA_FORMAT_VLAN_TAG_ANY;
  12589         pkt_fmt.tunnel          = BCM_FIELD_DATA_FORMAT_TUNNEL_MPLS;
  12590         pkt_fmt.mpls            = BCM_FIELD_DATA_FORMAT_MPLS_ANY;
  12591 
  12592         /* match mpls label */
  12593         bcm_field_data_qualifier_t_init(&label);
  12594         label.offset_base = bcmFieldDataOffsetBaseOuterL3Header;
  12595         label.offset      = 0;
  12596         label.length      = SHR_BHH_MPLS_LABEL_LENGTH;
  12597         BCM_IF_ERROR_RETURN(bcm_esw_field_data_qualifier_create(unit, &label));
  12598         BCM_IF_ERROR_RETURN(
  12599            bcm_esw_field_data_qualifier_packet_format_add(unit,
  12600                                                           label.qual_id,
  12601                                                           &pkt_fmt));
  12602         BCM_IF_ERROR_RETURN(
  12603                   bcm_esw_field_qset_data_qualifier_add(unit,
  12604                                                         &oc->bhh_lmdm_qset,
  12605                                                         label.qual_id));
  12606         oc->bhh_label_qual_id = label.qual_id;
  12607 
  12608 
  12609         /* match ACH channel type 0x8902 */
  12610         bcm_field_data_qualifier_t_init(&ach);
  12611         ach.offset_base = bcmFieldDataOffsetBaseOuterL3Header;
  12612         ach.offset      = 10;
  12613         ach.length      = SHR_BHH_ACH_TYPE_LENGTH;
  12614         BCM_IF_ERROR_RETURN(bcm_esw_field_data_qualifier_create(unit, &ach));
  12615         BCM_IF_ERROR_RETURN(
  12616            bcm_esw_field_data_qualifier_packet_format_add(unit,
  12617                                                           ach.qual_id,
  12618                                                           &pkt_fmt));
  12619         BCM_IF_ERROR_RETURN(
  12620                     bcm_esw_field_qset_data_qualifier_add(unit,
  12621                                                           &oc->bhh_lmdm_qset,
  12622                                                           ach.qual_id));
  12623         oc->bhh_ach_qual_id = ach.qual_id;
  12624 
  12625 
  12626         /* match opcode 45 or 46 or 47 */
  12627         bcm_field_data_qualifier_t_init(&opcode);
  12628         opcode.offset_base = bcmFieldDataOffsetBaseOuterL3Header;
  12629         opcode.offset      = 13;
  12630         opcode.length      = SHR_BHH_OPCODE_LEN;
  12631         BCM_IF_ERROR_RETURN(bcm_esw_field_data_qualifier_create(unit, &opcode));
  12632         BCM_IF_ERROR_RETURN(
  12633            bcm_esw_field_data_qualifier_packet_format_add(unit,
  12634                                                           opcode.qual_id,
  12635                                                           &pkt_fmt));
  12636         BCM_IF_ERROR_RETURN(
  12637                  bcm_esw_field_qset_data_qualifier_add(unit,
  12638                                                        &oc->bhh_lmdm_qset,
  12639                                                        opcode.qual_id));
  12640         oc->bhh_opcode_qual_id = opcode.qual_id;
  12641 
  12642         oc->bhh_field_pkt_fmt = pkt_fmt;
  12643 
  12644     }
  12645     return rv;
  12646 }
  12647 
  12648 /*
  12649  * Function:
  12650  *      _bcm_tr3_oam_bhh_hw_init
  12651  * Purpose:
  12652  *      Initialize the HW for BHH packet processing.
  12653  *      Configure:
  12654  *      - Copy to CPU BHH error packets
  12655  *      - CPU COS Queue for BHH packets
  12656  *      - RX DMA channel
  12657  * Parameters:
  12658  *      unit - (IN) Unit number.
  12659  * Returns:
  12660  *      BCM_E_XXX
  12661  * Notes:
  12662  */
  12663 STATIC int
  12664 _bcm_tr3_oam_bhh_hw_init(int unit)
  12665 {
  12666     int rv = BCM_E_NONE;
  12667     _bcm_oam_control_t   *oc;               /* OAM control structure.        */
  12668     uint32 val; 
  12669     int index;
  12670     int ach_error_index;
  12671     int cosq_map_size;
  12672     bcm_rx_reasons_t reasons, reasons_mask;
  12673     uint8 int_prio, int_prio_mask;
  12674     uint32 packet_type, packet_type_mask;
  12675     bcm_cos_queue_t cosq;
  12676     bcm_rx_chan_t chan_id;
  12677     int num_cosq = 0;
  12678     int min_cosq, max_cosq;
  12679     int i;
  12680 
  12681     /* Get OAM Control Structure. */
  12682     BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc));
  12683 
  12684     _BCM_OAM_LOCK(oc);
  12685 
  12686     /*
  12687      * Send BHH error packet to CPU
  12688      *
  12689      * Configure CPU_CONTROL_0 register
  12690      */
  12691     rv = READ_CPU_CONTROL_0r(unit, &val);
  12692     if(BCM_FAILURE(rv)) {
  12693         LOG_ERROR(BSL_LS_BCM_OAM,
  12694                   (BSL_META_U(unit,
  12695                               "BHH Error:hw init. Read CPU Control Reg %s.\n"),
  12696                    bcm_errmsg(rv)));
  12697         _BCM_OAM_UNLOCK(oc);
  12698         return (rv);
  12699     }
  12700 
  12701     soc_reg_field_set(unit, CPU_CONTROL_0r, &val,
  12702                       BFD_UNKNOWN_VERSION_TOCPUf, 1);
  12703     soc_reg_field_set(unit, CPU_CONTROL_0r, &val,
  12704                       BFD_YOUR_DISCRIMINATOR_NOT_FOUND_TOCPUf, 1);
  12705     soc_reg_field_set(unit, CPU_CONTROL_0r, &val,
  12706                       BFD_UNKNOWN_CONTROL_PACKET_TOCPUf, 1);
  12707 
  12708     rv = WRITE_CPU_CONTROL_0r(unit, val);
  12709     if(BCM_FAILURE(rv)) {
  12710         LOG_ERROR(BSL_LS_BCM_OAM,
  12711                   (BSL_META_U(unit,
  12712                               "BHH Error:hw init. Write CPU Control_0 Reg %s.\n"),
  12713                    bcm_errmsg(rv)));
  12714         _BCM_OAM_UNLOCK(oc);
  12715         return (rv);
  12716     }
  12717 
  12718     /*
  12719      * Configure CPU_CONTROL_M register
  12720      */
  12721 
  12722     rv = READ_CPU_CONTROL_Mr(unit, &val);
  12723     if(BCM_FAILURE(rv)) {
  12724         LOG_ERROR(BSL_LS_BCM_OAM,
  12725                   (BSL_META_U(unit,
  12726                               "BHH Error:hw init. Read CPU Control Reg %s.\n"),
  12727                    bcm_errmsg(rv)));
  12728         _BCM_OAM_UNLOCK(oc);
  12729         return (rv);
  12730     }
  12731     soc_reg_field_set(unit, CPU_CONTROL_Mr, &val, 
  12732                       MPLS_UNKNOWN_ACH_TYPE_TO_CPUf, 1); 
  12733     soc_reg_field_set(unit, CPU_CONTROL_Mr, &val, 
  12734                       MPLS_UNKNOWN_ACH_VERSION_TOCPUf, 1); 
  12735     rv = WRITE_CPU_CONTROL_Mr(unit, val);
  12736     if(BCM_FAILURE(rv)) {
  12737         LOG_ERROR(BSL_LS_BCM_OAM,
  12738                   (BSL_META_U(unit,
  12739                               "BHH Error:hw init. Write CPU Control_m Reg %s.\n"),
  12740                    bcm_errmsg(rv)));
  12741         _BCM_OAM_UNLOCK(oc);
  12742         return (rv);
  12743     }
  12744 
  12745     if(oc->ukernel_not_ready == 0){
  12746         /* 
  12747          * Get COSQ for BHH
  12748          */
  12749         min_cosq = 0;
  12750         for (i = 0; i < SOC_CMCS_NUM(unit); i++) {
  12751             num_cosq = NUM_CPU_ARM_COSQ(unit, i);
  12752             if (i == oc->uc_num + 1) {
  12753                 break;
  12754             }
  12755             min_cosq += num_cosq;
  12756         }
  12757         max_cosq = min_cosq + num_cosq - 1;
  12758 
  12759         if(max_cosq < min_cosq) {
  12760             LOG_ERROR(BSL_LS_BCM_OAM,
  12761                       (BSL_META_U(unit,
  12762                                   "BHH Error: No BHH COS Queue available from uC%d - %s\n"),
  12763                        oc->uc_num, bcm_errmsg(BCM_E_CONFIG)));
  12764             _BCM_OAM_UNLOCK(oc);
  12765             return (BCM_E_CONFIG);
  12766         }
  12767 
  12768         /* check user configured COSq */
  12769         if (oc->cpu_cosq != BHH_COSQ_INVALID) {
  12770             if ((oc->cpu_cosq < min_cosq) ||
  12771                 (oc->cpu_cosq > max_cosq)) {
  12772                 _BCM_OAM_UNLOCK(oc);
  12773                 return (BCM_E_CONFIG);
  12774             }
  12775             min_cosq = max_cosq = oc->cpu_cosq;
  12776         }
  12777 
  12778         /*
  12779          * Assign RX DMA channel to CPU COS Queue
  12780          * (This is the RX channel to listen on for BHH packets).
  12781          *
  12782          * DMA channels (12) are assigned 4 per processor:
  12783          * (see /src/bcm/common/rx.c)
  12784          *   channels 0..3  --> PCI host
  12785          *   channels 4..7  --> uController 0
  12786          *   chnanels 8..11 --> uController 1
  12787          *
  12788          * The uControllers designate the 4 local DMA channels as follows:
  12789          *   local channel  0     --> TX
  12790          *   local channel  1..3  --> RX
  12791          *
  12792          * Each uController application needs to use a different
  12793          * RX DMA channel to listen on.
  12794          */
  12795         chan_id = (BCM_RX_CHANNELS * (SOC_ARM_CMC(unit, oc->uc_num))) +
  12796             oc->rx_channel;
  12797 
  12798         for (i = max_cosq; i >= min_cosq; i--) {
  12799             rv = _bcm_common_rx_queue_channel_set(unit, i, chan_id);
  12800             if(BCM_SUCCESS(rv)) {
  12801                 oc->cpu_cosq = i;
  12802                 break;
  12803             }
  12804         }
  12805 
  12806         if (i < min_cosq) {
  12807             rv = BCM_E_RESOURCE;
  12808             LOG_ERROR(BSL_LS_BCM_OAM,
  12809                       (BSL_META_U(unit,
  12810                                   "BHH Error:hw init. queue channel set %s.\n"),
  12811                        bcm_errmsg(rv)));
  12812             _BCM_OAM_UNLOCK(oc);
  12813             return (rv);
  12814         }
  12815 
  12816         /*
  12817          * Direct BHH packets to designated CPU COS Queue...or more accurately
  12818          * BFD error packets.
  12819          *
  12820          * Reasons:
  12821          *   - bcmRxReasonBFD:               BFD error
  12822          *   - bcmRxReasonBfdUnknownVersion: BFD Unknown ACH
  12823          * NOTE:
  12824          *     The user input 'cpu_qid' (bcm_BHH_endpoint_t) could be
  12825          *     used to select different CPU COS queue. Currently,
  12826          *     all priorities are mapped into the same CPU COS Queue.
  12827          */
  12828 
  12829         /* Find available entries in CPU COS queue map table */
  12830         ach_error_index    = -1;   /* COSQ map index for error packets */
  12831         rv = bcm_esw_rx_cosq_mapping_size_get(unit, &cosq_map_size);
  12832         if(BCM_FAILURE(rv)) {
  12833             LOG_ERROR(BSL_LS_BCM_OAM,
  12834                       (BSL_META_U(unit,
  12835                                   "BHH Error:hw init. cosq maps size %s.\n"),
  12836                        bcm_errmsg(rv)));
  12837             _BCM_OAM_UNLOCK(oc);
  12838             return (rv);
  12839         }
  12840 
  12841         for (index = 0; index < cosq_map_size; index++) {
  12842             rv = bcm_esw_rx_cosq_mapping_get(unit, index,
  12843                                              &reasons, &reasons_mask,
  12844                                              &int_prio, &int_prio_mask,
  12845                                              &packet_type, &packet_type_mask,
  12846                                              &cosq);
  12847             if (rv == BCM_E_NOT_FOUND) {
  12848                 /* Assign first available index */
  12849                 rv = BCM_E_NONE;
  12850                 ach_error_index = index;
  12851                 break;
  12852             }
  12853             if (BCM_FAILURE(rv)) {
  12854                 LOG_ERROR(BSL_LS_BCM_OAM,
  12855                           (BSL_META_U(unit,
  12856                                       "BHH Error:hw init. cosq maps get %s.\n"),
  12857                            bcm_errmsg(rv)));
  12858                 _BCM_OAM_UNLOCK(oc);
  12859                 return (rv);
  12860             }
  12861         }
  12862 
  12863         if (ach_error_index == -1) {
  12864             LOG_ERROR(BSL_LS_BCM_OAM,
  12865                       (BSL_META_U(unit,
  12866                                   "BHH Error:hw init. ACH error %s.\n"),
  12867                        bcm_errmsg(rv)));
  12868             _BCM_OAM_UNLOCK(oc);
  12869             return (BCM_E_FULL);
  12870         }
  12871 
  12872         /* Set CPU COS Queue mapping */
  12873         BCM_RX_REASON_CLEAR_ALL(reasons);
  12874         BCM_RX_REASON_SET(reasons, bcmRxReasonMplsUnknownAch); /* Despite the name this reason */
  12875         /* code covers Unknown ACH */
  12876 
  12877         rv = bcm_esw_rx_cosq_mapping_set(unit, ach_error_index,
  12878                                          reasons, reasons,
  12879                                          0, 0, /* Any priority */
  12880                                          0, 0, /* Any packet type */
  12881                                          oc->cpu_cosq);
  12882         if(BCM_FAILURE(rv)) {
  12883             LOG_ERROR(BSL_LS_BCM_OAM,
  12884                       (BSL_META_U(unit,
  12885                                   "BHH Error:hw init. cosq map set %s.\n"),
  12886                        bcm_errmsg(rv)));
  12887             _BCM_OAM_UNLOCK(oc);
  12888             return (rv);
  12889         }
  12890         oc->cpu_cosq_ach_error_index = ach_error_index;
  12891 
  12892         if (oc->bhh_lm_dm_enable) {
  12893             rv = _bcm_tr3_oam_bhh_fp_init(unit);
  12894         }
  12895     }
  12896 
  12897     _BCM_OAM_UNLOCK(oc);
  12898     return (rv);
  12899 }
  12900 
  12901 /*
  12902  * Function:
  12903  *      _bcm_tr3_oam_bhh_find_l2_entry_1
  12904  */
  12905 STATIC int
  12906 _bcm_tr3_oam_bhh_find_l2_entry_1(int unit, uint32 key, int key_type, int ses_type,
  12907                    int *index, l2_entry_1_entry_t *l2_entry_1)
  12908 {
  12909     l2_entry_1_entry_t l2_key;
  12910 
  12911     sal_memset(&l2_key, 0, sizeof(l2_key));
  12912 
  12913     soc_mem_field32_set(unit, L2_ENTRY_1m, &l2_key, KEY_TYPEf, key_type);
  12914     soc_mem_field32_set(unit, L2_ENTRY_1m, &l2_key,
  12915                         BFD__SESSION_IDENTIFIER_TYPEf, ses_type);
  12916 
  12917     if (ses_type) {
  12918         soc_mem_field32_set(unit, L2_ENTRY_1m, &l2_key, BFD__LABELf, key);
  12919     } else {
  12920         soc_mem_field32_set(unit, L2_ENTRY_1m, &l2_key,
  12921                             BFD__YOUR_DISCRIMINATORf, key);
  12922     }
  12923 
  12924     return soc_mem_search(unit, L2_ENTRY_1m, MEM_BLOCK_ANY, index,
  12925                           &l2_key, l2_entry_1, 0);
  12926 
  12927 }
  12928 
  12929 /*
  12930  * Function:
  12931  *      _bcm_tr3_oam_bhh_fp_delete
  12932  * Purpose:
  12933  *      Sets BHH FP for LM/DM in HW device.
  12934  * Parameters:
  12935  *      unit            - (IN) Unit number.
  12936  *      module_id       - (IN) Module id.
  12937  *      port_id         - (IN) Port.
  12938  *      is_local        - (IN) Indicates if module id is local.
  12939  *      endpoint_config - (IN) Pointer to BHH endpoint structure.
  12940  * Returns:
  12941  *      BCM_E_XXX
  12942  * Notes:
  12943  */
  12944  STATIC int
  12945 _bcm_tr3_oam_bhh_fp_delete(int unit, _bcm_oam_hash_data_t *h_data_p)
  12946 {
  12947     int rv = BCM_E_NONE;
  12948     _bcm_oam_control_t *oc;
  12949 
  12950     /* Lock already taken by the calling routine. */
  12951     BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc));
  12952 
  12953     if(h_data_p->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT) {
  12954         if (h_data_p->bhh_entry_pkt_rx) {
  12955             (void)bcm_esw_field_entry_destroy(unit, h_data_p->bhh_entry_pkt_rx);
  12956             oc->bhh_lmdm_entry_count--;
  12957         }
  12958         if (h_data_p->bhh_entry_pkt_tx) {
  12959             (void)bcm_esw_field_entry_destroy(unit, h_data_p->bhh_entry_pkt_tx);
  12960             oc->bhh_lmdm_entry_count--;
  12961         }
  12962         if (h_data_p->bhh_lm_entry_rx) {
  12963             (void)bcm_esw_field_entry_destroy(unit, h_data_p->bhh_lm_entry_rx);
  12964             oc->bhh_lmdm_entry_count--;
  12965         }
  12966     }
  12967 
  12968     if(h_data_p->flags & BCM_OAM_ENDPOINT_DELAY_MEASUREMENT) {
  12969         if (h_data_p->bhh_dm_entry_rx) {
  12970             (void)bcm_esw_field_entry_destroy(unit, h_data_p->bhh_dm_entry_rx);
  12971             oc->bhh_lmdm_entry_count--;
  12972         }
  12973     }
  12974 
  12975     if (h_data_p->lm_counter_index != _BCM_OAM_LM_COUNTER_IDX_INVALID) {
  12976         /* Return ID back to free lm counter pool.*/
  12977         BCM_IF_ERROR_RETURN(shr_idxres_list_free(oc->lm_counter_pool, 
  12978                                                  h_data_p->lm_counter_index));
  12979         h_data_p->lm_counter_index = _BCM_OAM_LM_COUNTER_IDX_INVALID;
  12980         SOC_IF_ERROR_RETURN(soc_profile_mem_delete(unit, 
  12981                 &oc->ing_service_pri_map,
  12982                 (h_data_p->pri_map_index * BCM_OAM_INTPRI_MAX)));
  12983     }
  12984 
  12985     if(oc->bhh_lmdm_entry_count == 0) {
  12986         (void)bcm_esw_field_group_destroy(unit, oc->bhh_lmdm_group);
  12987         oc->bhh_lmdm_group = 0;
  12988     }
  12989 
  12990     h_data_p->bhh_entry_pkt_tx = 0;
  12991     h_data_p->bhh_entry_pkt_rx = 0;
  12992     h_data_p->bhh_lm_entry_rx = 0;
  12993     h_data_p->bhh_dm_entry_rx = 0;
  12994 
  12995     return rv;
  12996 }
  12997 
  12998 
  12999 /*
  13000  * Function:
  13001  *      _bcm_tr3_oam_bhh_session_hw_delete
  13002  * Purpose:
  13003  *      Delete BHH Session in HW device.
  13004  * Parameters:
  13005  *      unit       - (IN) Unit number.
  13006  *      h_data_p- (IN) Pointer to BHH endpoint structure.
  13007  * Returns:
  13008  *      BCM_E_XXX
  13009  * Notes:
  13010  */
  13011 STATIC int
  13012 _bcm_tr3_oam_bhh_session_hw_delete(int unit, _bcm_oam_hash_data_t *h_data_p)
  13013 {
  13014     int rv = BCM_E_NONE;
  13015     int l2_index = 0;
  13016     l2_entry_1_entry_t l2_entry_1;
  13017 #if defined(BCM_TRIUMPH_SUPPORT) && defined(BCM_MPLS_SUPPORT)
  13018     mpls_entry_1_entry_t mpls_entry;
  13019     mpls_entry_1_entry_t mpls_key;
  13020     int mpls_index = 0;
  13021 #endif /* BCM_TRIUMPH_SUPPORT &&  BCM_MPLS_SUPPORT */
  13022 
  13023 
  13024     switch(h_data_p->type) {
  13025     case bcmOAMEndpointTypeBHHMPLS:
  13026     case bcmOAMEndpointTypeBHHMPLSVccv:
  13027 #if defined(BCM_TRIUMPH_SUPPORT) && defined(BCM_MPLS_SUPPORT)
  13028         SOC_IF_ERROR_RETURN(bcm_tr_mpls_lock (unit));
  13029 
  13030         sal_memset(&mpls_key, 0, sizeof(mpls_key));
  13031         soc_MPLS_ENTRYm_field32_set(unit, &mpls_key,
  13032                                     MPLS__MPLS_LABELf, h_data_p->label);
  13033         soc_MPLS_ENTRYm_field32_set(unit, &mpls_key, KEY_TYPEf, 16);
  13034 
  13035         rv = soc_mem_search(unit, MPLS_ENTRYm, MEM_BLOCK_ANY, &mpls_index,
  13036                                            &mpls_key, &mpls_entry, 0);
  13037 
  13038         /* It can so happen that this function is called when the switch is
  13039            re-initailizing, then MPLS ENTRY will not be found, as MPLS init 
  13040            happens before OAM init and it would have cleared the MPLS Entry, as 
  13041            such its not an error scenario. Hence dont return failure from here.*/
  13042         if (BCM_SUCCESS(rv)) {
  13043             if ((soc_MPLS_ENTRYm_field32_get(unit, &mpls_entry, VALIDf) == 0x1)) 
  13044             {
  13045                 soc_MPLS_ENTRYm_field32_set(unit, &mpls_entry, 
  13046                                                         MPLS__BFD_ENABLEf, 0);
  13047                 rv = soc_mem_write(unit, MPLS_ENTRYm, MEM_BLOCK_ANY, 
  13048                         mpls_index, &mpls_entry);
  13049                 if (BCM_FAILURE(rv)) {
  13050                     LOG_ERROR(BSL_LS_BCM_OAM,
  13051                               (BSL_META_U(unit,
  13052                                           "OAM Error: MPLS_ENTRY write failed - "
  13053                                            "%s.\n"), bcm_errmsg(rv)));
  13054                     bcm_tr_mpls_unlock(unit);
  13055                     return (rv);
  13056                 }
  13057             }
  13058         }
  13059         bcm_tr_mpls_unlock (unit);
  13060 
  13061         if (BCM_SUCCESS(_bcm_tr3_oam_bhh_find_l2_entry_1(unit,
  13062                                h_data_p->label,
  13063                                12, 1,
  13064                                &l2_index, &l2_entry_1))) {
  13065             soc_mem_delete_index(unit, L2_ENTRY_1m, MEM_BLOCK_ANY, l2_index);
  13066 
  13067         }
  13068 #endif /* BCM_TRIUMPH_SUPPORT &&  BCM_MPLS_SUPPORT */
  13069         break;
  13070 
  13071     default:
  13072         break;
  13073     }
  13074 
  13075     if((h_data_p->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT) ||
  13076         (h_data_p->flags & BCM_OAM_ENDPOINT_DELAY_MEASUREMENT))
  13077     {
  13078         rv = _bcm_tr3_oam_bhh_fp_delete(unit, h_data_p);
  13079     }
  13080 
  13081     return (rv);
  13082 }
  13083 
  13084 /*
  13085  * Function:
  13086  *      _bcm_tr3_oam_bhh_msg_send_receive
  13087  * Purpose:
  13088  *      Sends given BHH control message to the uController.
  13089  *      Receives and verifies expected reply.
  13090  *      Performs DMA operation if required.
  13091  * Parameters:
  13092  *      unit        - (IN) Unit number.
  13093  *      s_subclass  - (IN) BHH message subclass.
  13094  *      s_len       - (IN) Value for 'len' field in message struct.
  13095  *                         Length of buffer to flush if DMA send is required.
  13096  *      s_data      - (IN) Value for 'data' field in message struct.
  13097  *                         Ignored if message requires a DMA send/receive
  13098  *                         operation.
  13099  *      r_subclass  - (IN) Expected reply message subclass.
  13100  *      r_len       - (OUT) Returns value in 'len' reply message field.
  13101  * Returns:
  13102  *      BCM_E_XXX
  13103  * Notes:
  13104  *     - The uc_msg 'len' and 'data' fields of mos_msg_data_t
  13105  *       can take any arbitrary data.
  13106  *
  13107  *     BHH Long Control message:
  13108  *     - BHH control messages that require send/receive of information
  13109  *       that cannot fit in the uc_msg 'len' and 'data' fields need to
  13110  *       use DMA operations to exchange information (long control message).
  13111  *
  13112  *     - BHH convention for long control messages for
  13113  *        'mos_msg_data_t' fields:
  13114  *          'len'    size of the DMA buffer to send to uController
  13115  *          'data'   physical DMA memory address to send or receive
  13116  *
  13117  *      DMA Operations:
  13118  *      - DMA read/write operation is performed when a long BHH control
  13119  *        message is involved.
  13120  *
  13121  *      - Messages that require DMA operation (long control message)
  13122  *        is indicated by MOS_MSG_DMA_MSG().
  13123  *
  13124  *      - Callers must 'pack' and 'unpack' corresponding information
  13125  *        into/from DMA buffer indicated by BHH_INFO(unit)->dma_buffer.
  13126  */
  13127 STATIC int
  13128 _bcm_tr3_oam_bhh_msg_send_receive(int unit, uint8 s_subclass,
  13129                                     uint16 s_len, uint32 s_data,
  13130                                     uint8 r_subclass, uint16 *r_len, sal_usecs_t timeout)
  13131 {
  13132     int rv;
  13133     _bcm_oam_control_t *oc;
  13134     mos_msg_data_t send, reply;
  13135     uint8 *dma_buffer;
  13136     int dma_buffer_len;
  13137     uint32 uc_rv;
  13138 
  13139     /* Lock already taken by the calling routine. */
  13140     BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc));
  13141 
  13142     sal_memset(&send, 0, sizeof(send));
  13143     sal_memset(&reply, 0, sizeof(reply));
  13144     send.s.mclass = MOS_MSG_CLASS_BHH;
  13145     send.s.subclass = s_subclass;
  13146     send.s.len = bcm_htons(s_len);
  13147 
  13148     /*
  13149      * Set 'data' to DMA buffer address if a DMA operation is
  13150      * required for send or receive.
  13151      */
  13152     dma_buffer = oc->dma_buffer;
  13153     dma_buffer_len = oc->dma_buffer_len;
  13154     if (MOS_MSG_DMA_MSG(s_subclass) ||
  13155         MOS_MSG_DMA_MSG(r_subclass)) {
  13156         send.s.data = bcm_htonl(soc_cm_l2p(unit, dma_buffer));
  13157     } else {
  13158         send.s.data = bcm_htonl(s_data);
  13159     }
  13160 
  13161     /* Flush DMA memory */
  13162     if (MOS_MSG_DMA_MSG(s_subclass)) {
  13163         soc_cm_sflush(unit, dma_buffer, s_len);
  13164     }
  13165 
  13166     /* Invalidate DMA memory to read */
  13167     if (MOS_MSG_DMA_MSG(r_subclass)) {
  13168         soc_cm_sinval(unit, dma_buffer, dma_buffer_len);
  13169     }
  13170 
  13171     rv = soc_cmic_uc_msg_send_receive(unit, oc->uc_num,
  13172                                       &send, &reply,
  13173                                       timeout);
  13174 
  13175     /* Check reply class, subclass */
  13176     if ((rv != SOC_E_NONE) ||
  13177         (reply.s.mclass != MOS_MSG_CLASS_BHH) ||
  13178         (reply.s.subclass != r_subclass)) {
  13179         return (BCM_E_INTERNAL);
  13180     }
  13181 
  13182     /* Convert BHH uController error code to BCM */
  13183     uc_rv = bcm_ntohl(reply.s.data);
  13184     switch(uc_rv) {
  13185     case SHR_BHH_UC_E_NONE:
  13186         rv = BCM_E_NONE;
  13187         break;
  13188     case SHR_BHH_UC_E_INTERNAL:
  13189         rv = BCM_E_INTERNAL;
  13190         break;
  13191     case SHR_BHH_UC_E_MEMORY:
  13192         rv = BCM_E_MEMORY;
  13193         break;
  13194     case SHR_BHH_UC_E_PARAM:
  13195         rv = BCM_E_PARAM;
  13196         break;
  13197     case SHR_BHH_UC_E_RESOURCE:
  13198         rv = BCM_E_RESOURCE;
  13199         break;
  13200     case SHR_BHH_UC_E_EXISTS:
  13201         rv = BCM_E_EXISTS;
  13202         break;
  13203     case SHR_BHH_UC_E_NOT_FOUND:
  13204         rv = BCM_E_NOT_FOUND;
  13205         break;
  13206     case SHR_BHH_UC_E_INIT:
  13207         rv = BCM_E_INIT;
  13208         break;
  13209     default:
  13210         rv = BCM_E_INTERNAL;
  13211         break;
  13212     }
  13213         
  13214     *r_len = bcm_ntohs(reply.s.len);
  13215 
  13216     return (rv);
  13217 }
  13218 
  13219 /*
  13220  * Function:
  13221  *      _bcm_tr3_oam_bhh_callback_thread
  13222  * Purpose:
  13223  *      Thread to listen for event messages from uController.
  13224  * Parameters:
  13225  *      param - Pointer to BFD info structure.
  13226  * Returns:
  13227  *      None
  13228  */
  13229 STATIC void
  13230 _bcm_tr3_oam_bhh_callback_thread(void *param)
  13231 {
  13232     int rv;
  13233     _bcm_oam_control_t *oc = (_bcm_oam_control_t *)param;
  13234     bcm_oam_event_types_t events;
  13235     bcm_oam_event_type_t event_type;
  13236     bhh_msg_event_t event_msg;
  13237     int sess_id;
  13238     uint32 event_mask, flags = 0;
  13239     _bcm_oam_event_handler_t *event_handler_p;
  13240     _bcm_oam_hash_data_t *h_data_p;
  13241     int ep_id = 0;
  13242     char thread_name[SAL_THREAD_NAME_MAX_LEN];
  13243 
  13244     thread_name[0] = 0x0;
  13245     sal_thread_name(oc->event_thread_id, thread_name, sizeof (thread_name));
  13246     LOG_VERBOSE(BSL_LS_SOC_COMMON,
  13247                 (BSL_META_U(oc->unit,
  13248                             "BHH callback thread starting\n")));
  13249 
  13250     while (1) {
  13251         /* Wait on notifications from uController */
  13252         rv = soc_cmic_uc_msg_receive(oc->unit, oc->uc_num,
  13253                                      MOS_MSG_CLASS_BHH_EVENT, &event_msg,
  13254                                      sal_sem_FOREVER);
  13255 
  13256         if (BCM_FAILURE(rv)) {
  13257             break;  /*  Thread exit */
  13258         }
  13259 
  13260         event_handler_p = oc->event_handler_list_p;
  13261         /* Get data from event message */
  13262         sess_id = (int)bcm_ntohs(event_msg.s.len);
  13263         ep_id = BCM_OAM_BHH_GET_SDK_EP(sess_id);
  13264 
  13265         if (sess_id < 0 ||
  13266             sess_id >= oc->ep_count) {
  13267             LOG_WARN(BSL_LS_BCM_OAM,
  13268                      (BSL_META_U(oc->unit,
  13269                                  "Invalid sess_id:%d\n"), sess_id));
  13270             continue;
  13271         }
  13272         /* Check endpoint status. */
  13273         rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id);
  13274         if ((BCM_E_EXISTS != rv)) {
  13275             /* Endpoint not in use. */
  13276             LOG_ERROR(BSL_LS_BCM_OAM,
  13277                       (BSL_META_U(oc->unit,
  13278                                   "OAM Error: Endpoint EP=%d %s.\n"),
  13279                        ep_id, bcm_errmsg(rv)));
  13280         }
  13281         h_data_p = &oc->oam_hash_data[ep_id];
  13282         event_mask = bcm_ntohl(event_msg.s.data);
  13283 
  13284    
  13285         /* Set events */
  13286         sal_memset(&events, 0, sizeof(events));
  13287 
  13288         if (event_mask & BHH_BTE_EVENT_LB_TIMEOUT) {
  13289             LOG_DEBUG(BSL_LS_BCM_OAM,
  13290                       (BSL_META_U(oc->unit,
  13291                                   "****** OAM BHH LB Timeout ******\n")));
  13292 
  13293             if (oc->event_handler_cnt[bcmOAMEventBHHLBTimeout] > 0)
  13294             SHR_BITSET(events.w, bcmOAMEventBHHLBTimeout);
  13295         }
  13296         if (event_mask & BHH_BTE_EVENT_LB_DISCOVERY_UPDATE) {
  13297             LOG_DEBUG(BSL_LS_BCM_OAM,
  13298                       (BSL_META_U(oc->unit,
  13299                                   "****** OAM BHH LB Discovery Update ******\n")));
  13300             if (oc->event_handler_cnt[bcmOAMEventBHHLBDiscoveryUpdate] > 0)
  13301             SHR_BITSET(events.w, bcmOAMEventBHHLBDiscoveryUpdate);
  13302         }
  13303         if (event_mask & BHH_BTE_EVENT_CCM_TIMEOUT) {
  13304             LOG_DEBUG(BSL_LS_BCM_OAM,
  13305                       (BSL_META_U(oc->unit,
  13306                                   "****** OAM BHH CCM Timeout ******\n")));
  13307             if (oc->event_handler_cnt[bcmOAMEventBHHCCMTimeout] > 0)
  13308             SHR_BITSET(events.w, bcmOAMEventBHHCCMTimeout);
  13309         }
  13310         if (event_mask & BHH_BTE_EVENT_CCM_TIMEOUT_CLEAR) {
  13311             LOG_DEBUG(BSL_LS_BCM_OAM,
  13312                       (BSL_META_U(oc->unit,
  13313                                   "****** OAM BHH CCM Timeout Clear ******\n")));
  13314             if (oc->event_handler_cnt[bcmOAMEventBHHCCMTimeoutClear] > 0)
  13315             SHR_BITSET(events.w, bcmOAMEventBHHCCMTimeoutClear);
  13316         }
  13317         if (event_mask & BHH_BTE_EVENT_STATE) {
  13318             LOG_DEBUG(BSL_LS_BCM_OAM,
  13319                       (BSL_META_U(oc->unit,
  13320                                   "****** OAM BHH State ******\n")));
  13321             if (oc->event_handler_cnt[bcmOAMEventBHHCCMState] > 0)
  13322             SHR_BITSET(events.w, bcmOAMEventBHHCCMState);
  13323         }
  13324    
  13325         if (event_mask & BHH_BTE_EVENT_CCM_RDI) {
  13326             LOG_DEBUG(BSL_LS_BCM_OAM,
  13327                       (BSL_META_U(oc->unit,
  13328                                   "****** OAM BHH CCM RDI ******\n")));
  13329             if (oc->event_handler_cnt[bcmOAMEventBHHCCMRdi] > 0)
  13330             SHR_BITSET(events.w, bcmOAMEventBHHCCMRdi);
  13331         }
  13332         if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_LEVEL) {
  13333             LOG_DEBUG(BSL_LS_BCM_OAM,
  13334                       (BSL_META_U(oc->unit,
  13335                                   "****** OAM BHH CCM Unknown MEG Level ******\n")));
  13336             if (oc->event_handler_cnt[bcmOAMEventBHHCCMUnknownMegLevel] > 0)
  13337             SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownMegLevel);
  13338         }
  13339         if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_ID) {
  13340             LOG_DEBUG(BSL_LS_BCM_OAM,
  13341                       (BSL_META_U(oc->unit,
  13342                                   "****** OAM BHH CCM Unknown MEG ID ******\n")));
  13343             if (oc->event_handler_cnt[bcmOAMEventBHHCCMUnknownMegId] > 0)
  13344             SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownMegId);
  13345         }
  13346         if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_MEP_ID) {
  13347             LOG_DEBUG(BSL_LS_BCM_OAM,
  13348                       (BSL_META_U(oc->unit,
  13349                                   "****** OAM BHH CCM Unknown MEP ID ******\n")));
  13350             if (oc->event_handler_cnt[bcmOAMEventBHHCCMUnknownMepId] > 0)
  13351             SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownMepId);
  13352         }
  13353         if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_PERIOD) {
  13354             if (oc->event_handler_cnt[bcmOAMEventBHHCCMUnknownPeriod] > 0)
  13355             SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownPeriod);
  13356         }
  13357         if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_PRIORITY) {
  13358             if (oc->event_handler_cnt[bcmOAMEventBHHCCMUnknownPriority] > 0)
  13359             SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownPriority);
  13360         }
  13361         if (event_mask & BHH_BTE_EVENT_CCM_RDI_CLEAR) {
  13362             if (oc->event_handler_cnt[bcmOAMEventBHHCCMRdiClear] > 0)
  13363             SHR_BITSET(events.w, bcmOAMEventBHHCCMRdiClear);
  13364         }
  13365         if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_LEVEL_CLEAR) {
  13366             if (oc->event_handler_cnt[bcmOAMEventBHHCCMUnknownMegLevelClear] > 0)
  13367             SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownMegLevelClear);
  13368         }
  13369         if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_ID_CLEAR) {
  13370             if (oc->event_handler_cnt[bcmOAMEventBHHCCMUnknownMegIdClear] > 0)
  13371             SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownMegIdClear);
  13372         }
  13373         if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_MEP_ID_CLEAR) {
  13374             if (oc->event_handler_cnt[bcmOAMEventBHHCCMUnknownMepIdClear] > 0)
  13375             SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownMepIdClear);
  13376         }
  13377         if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_PERIOD_CLEAR) {
  13378             if (oc->event_handler_cnt[bcmOAMEventBHHCCMUnknownPeriodClear] > 0)
  13379             SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownPeriodClear);
  13380         }
  13381         if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_PRIORITY_CLEAR) {
  13382             if (oc->event_handler_cnt[bcmOAMEventBHHCCMUnknownPriorityClear] > 0)
  13383             SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownPriorityClear);
  13384         }
  13385         if (event_mask & BHH_BTE_EVENT_CSF_LOS) {
  13386             if (oc->event_handler_cnt[bcmOAMEventCsfLos] > 0) {
  13387                 SHR_BITSET(events.w, bcmOAMEventCsfLos);
  13388             }
  13389         }
  13390         if (event_mask & BHH_BTE_EVENT_CSF_FDI) {
  13391             if (oc->event_handler_cnt[bcmOAMEventCsfFdi] > 0) {
  13392                 SHR_BITSET(events.w, bcmOAMEventCsfFdi);
  13393             }
  13394         }
  13395         if (event_mask & BHH_BTE_EVENT_CSF_RDI) {
  13396             if (oc->event_handler_cnt[bcmOAMEventCsfRdi] > 0) {
  13397                 SHR_BITSET(events.w, bcmOAMEventCsfRdi);
  13398             }
  13399         }
  13400         if (event_mask & BHH_BTE_EVENT_CSF_DCI) {
  13401             if (oc->event_handler_cnt[bcmOAMEventCsfDci] > 0) {
  13402                 SHR_BITSET(events.w, bcmOAMEventCsfDci);
  13403             }
  13404         }
  13405 
  13406         /* Loop over registered callbacks,
  13407          * If any match the events field, then invoke
  13408          */
  13409         for (event_handler_p = oc->event_handler_list_p;
  13410              event_handler_p != NULL;
  13411              event_handler_p = event_handler_p->next_p) {
  13412             for (event_type = bcmOAMEventBHHLBTimeout; event_type < bcmOAMEventCount; ++event_type) {
  13413                 if (SHR_BITGET(events.w, event_type)) {
  13414                     if (SHR_BITGET(event_handler_p->event_types.w,
  13415                                    event_type)) {
  13416                         event_handler_p->cb(oc->unit,
  13417                                         flags,
  13418                                         event_type,
  13419                                         h_data_p->group_index, /* Group index */
  13420                                         ep_id, /* Endpoint index */
  13421                                         event_handler_p->user_data);
  13422                     }
  13423                 }
  13424             }
  13425         }
  13426     }
  13427 
  13428     oc->event_thread_id   = NULL;
  13429 
  13430     LOG_VERBOSE(BSL_LS_SOC_COMMON,
  13431                 (BSL_META_U(oc->unit,
  13432                             "BHH callback thread stopped\n")));
  13433     sal_thread_exit(0);
  13434 }
  13435 
  13436 /* BHH Event Handler */
  13437 typedef struct _event_handler_s {
  13438     struct _event_handler_s *next;
  13439     bcm_oam_event_types_t event_types;
  13440     bcm_oam_event_cb cb;
  13441     void *user_data;
  13442 } _event_handler_t;
  13443 
  13444 /*
  13445  * Function:
  13446  *      _bcm_tr3_oam_bhh_event_mask_set
  13447  * Purpose:
  13448  *      Set the BHH Events mask.
  13449  *      Events are set per BHH module.
  13450  * Parameters:
  13451  *      unit        - (IN) Unit number.
  13452  * Returns:
  13453  *      BCM_E_NONE Operation completed successfully
  13454  *      BCM_E_XXX  Operation failed
  13455  * Notes:
  13456  */
  13457 STATIC int
  13458 _bcm_tr3_oam_bhh_event_mask_set(int unit)
  13459 {
  13460     _bcm_oam_control_t *oc;
  13461     _bcm_oam_event_handler_t *event_handler_p;
  13462     uint32 event_mask = 0;
  13463     uint16 reply_len;
  13464     int rv = BCM_E_NONE;
  13465 
  13466     /* Lock already taken by the calling routine. */
  13467     BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc));
  13468 
  13469     /* Get event mask from all callbacks */
  13470     for (event_handler_p = oc->event_handler_list_p;
  13471          event_handler_p != NULL;
  13472          event_handler_p = event_handler_p->next_p) {
  13473 
  13474         if (SHR_BITGET(event_handler_p->event_types.w,
  13475                        bcmOAMEventBHHLBTimeout)) {
  13476             event_mask |= BHH_BTE_EVENT_LB_TIMEOUT;
  13477         }
  13478         if (SHR_BITGET(event_handler_p->event_types.w,
  13479                        bcmOAMEventBHHLBDiscoveryUpdate)) {
  13480             event_mask |= BHH_BTE_EVENT_LB_DISCOVERY_UPDATE;
  13481         }
  13482         if (SHR_BITGET(event_handler_p->event_types.w,
  13483                        bcmOAMEventBHHCCMTimeout)) {
  13484             event_mask |= BHH_BTE_EVENT_CCM_TIMEOUT;
  13485         }
  13486         if (SHR_BITGET(event_handler_p->event_types.w,
  13487                        bcmOAMEventBHHCCMTimeoutClear)) {
  13488             event_mask |= BHH_BTE_EVENT_CCM_TIMEOUT_CLEAR;
  13489         }
  13490         if (SHR_BITGET(event_handler_p->event_types.w,
  13491                        bcmOAMEventBHHCCMState)) {
  13492             event_mask |= BHH_BTE_EVENT_STATE;
  13493         }
  13494         if (SHR_BITGET(event_handler_p->event_types.w,
  13495                        bcmOAMEventBHHCCMRdi)) {
  13496             event_mask |= BHH_BTE_EVENT_CCM_RDI;
  13497         }
  13498         if (SHR_BITGET(event_handler_p->event_types.w,
  13499                        bcmOAMEventBHHCCMUnknownMegLevel)) {
  13500             event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_MEG_LEVEL;
  13501         }
  13502         if (SHR_BITGET(event_handler_p->event_types.w,
  13503                        bcmOAMEventBHHCCMUnknownMegId)) {
  13504             event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_MEG_ID;
  13505         }
  13506         if (SHR_BITGET(event_handler_p->event_types.w,
  13507                        bcmOAMEventBHHCCMUnknownMepId)) {
  13508             event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_MEP_ID;
  13509         }
  13510         if (SHR_BITGET(event_handler_p->event_types.w,
  13511                        bcmOAMEventBHHCCMUnknownPeriod)) {
  13512             event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_PERIOD;
  13513         }
  13514         if (SHR_BITGET(event_handler_p->event_types.w,
  13515                        bcmOAMEventBHHCCMUnknownPriority)) {
  13516             event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_PRIORITY;
  13517         }
  13518         if (SHR_BITGET(event_handler_p->event_types.w,
  13519                        bcmOAMEventBHHCCMRdiClear)) {
  13520             event_mask |= BHH_BTE_EVENT_CCM_RDI_CLEAR;
  13521         }
  13522         if (SHR_BITGET(event_handler_p->event_types.w,
  13523                        bcmOAMEventBHHCCMUnknownMegLevelClear)) {
  13524             event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_MEG_LEVEL_CLEAR;
  13525         }
  13526         if (SHR_BITGET(event_handler_p->event_types.w,
  13527                        bcmOAMEventBHHCCMUnknownMegIdClear)) {
  13528             event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_MEG_ID_CLEAR;
  13529         }
  13530         if (SHR_BITGET(event_handler_p->event_types.w,
  13531                        bcmOAMEventBHHCCMUnknownMepIdClear)) {
  13532             event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_MEP_ID_CLEAR;
  13533         }
  13534         if (SHR_BITGET(event_handler_p->event_types.w,
  13535                        bcmOAMEventBHHCCMUnknownPeriodClear)) {
  13536             event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_PERIOD_CLEAR;
  13537         }
  13538         if (SHR_BITGET(event_handler_p->event_types.w,
  13539                        bcmOAMEventBHHCCMUnknownPriorityClear)) {
  13540             event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_PRIORITY_CLEAR;
  13541         }
  13542         if (SHR_BITGET(event_handler_p->event_types.w, bcmOAMEventCsfLos)) {
  13543             event_mask |= BHH_BTE_EVENT_CSF_LOS;
  13544         }
  13545         if (SHR_BITGET(event_handler_p->event_types.w, bcmOAMEventCsfFdi)) {
  13546             event_mask |= BHH_BTE_EVENT_CSF_FDI;
  13547         }
  13548         if (SHR_BITGET(event_handler_p->event_types.w, bcmOAMEventCsfRdi)) {
  13549             event_mask |= BHH_BTE_EVENT_CSF_RDI;
  13550         }
  13551         if (SHR_BITGET(event_handler_p->event_types.w, bcmOAMEventCsfDci)) {
  13552             event_mask |= BHH_BTE_EVENT_CSF_DCI;
  13553         }
  13554     }
  13555     /* Update BHH event mask in uKernel */
  13556     if (event_mask != oc->event_mask) {
  13557         /* Send BHH Event Mask message to uC */
  13558         rv = _bcm_tr3_oam_bhh_msg_send_receive
  13559                 (unit,
  13560                  MOS_MSG_SUBCLASS_BHH_EVENT_MASK_SET,
  13561                  0, event_mask,
  13562                  MOS_MSG_SUBCLASS_BHH_EVENT_MASK_SET_REPLY,
  13563                  &reply_len, _BHH_UC_MSG_TIMEOUT_USECS);
  13564 
  13565         if(BCM_SUCCESS(rv) && (reply_len != 0)) {
  13566             rv = BCM_E_INTERNAL;
  13567         }
  13568     }
  13569 
  13570     oc->event_mask = event_mask;
  13571 
  13572     return (rv);
  13573 }
  13574 
  13575 /*
  13576  * Function:
  13577  *     bcm_tr3_oam_loopback_add
  13578  * Purpose:
  13579  *     
  13580  * Parameters:
  13581  *     unit - Device unit number
  13582  * Returns:
  13583  *     None
  13584  */
  13585 int
  13586 bcm_tr3_oam_loopback_add(int unit, bcm_oam_loopback_t *loopback_p)
  13587 {
  13588     _bcm_oam_control_t *oc;
  13589     _bcm_oam_hash_data_t *h_data_p;
  13590     int rv = BCM_E_NONE;
  13591     bhh_sdk_msg_ctrl_loopback_add_t msg;
  13592     uint8 *buffer, *buffer_ptr;
  13593     uint16 buffer_len, reply_len;
  13594     uint32 flags = 0;
  13595     int sess_id = 0;
  13596 
  13597     /* Get OAM Control Structure. */
  13598     BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc));
  13599     _BCM_OAM_LOCK(oc);
  13600 
  13601     if (oc->ukernel_not_ready) {
  13602         _BCM_OAM_UNLOCK(oc);
  13603         return BCM_E_INIT;
  13604     }
  13605 
  13606 
  13607     BCM_OAM_BHH_VALIDATE_EP(loopback_p->id);
  13608 
  13609     sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(loopback_p->id);
  13610 
  13611     /* Check endpoint status. */
  13612     rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id);
  13613     if ((BCM_E_EXISTS != rv)) {
  13614         /* Endpoint not in use. */
  13615         LOG_ERROR(BSL_LS_BCM_OAM,
  13616                   (BSL_META_U(unit,
  13617                               "OAM Error: Endpoint EP=%d %s.\n"),
  13618                    loopback_p->id, bcm_errmsg(rv)));
  13619         _BCM_OAM_UNLOCK(oc);
  13620         return (rv);
  13621     }
  13622 
  13623     h_data_p = &oc->oam_hash_data[loopback_p->id];
  13624 
  13625     /*
  13626      * Only BHH is supported
  13627      */
  13628     if (h_data_p->type == bcmOAMEndpointTypeBHHMPLS ||
  13629         h_data_p->type == bcmOAMEndpointTypeBHHMPLSVccv) {
  13630 
  13631         /*
  13632          * Convert host space flags to uKernel space flags
  13633          */
  13634 
  13635         if (loopback_p->flags & BCM_OAM_LOOPBACK_TX_ENABLE) {
  13636             flags |= BCM_BHH_TX_ENABLE;
  13637         }
  13638 
  13639         if (loopback_p->flags & BCM_OAM_BHH_INC_REQUESTING_MEP_TLV) {
  13640             flags |= BCM_BHH_INC_REQUESTING_MEP_TLV;
  13641         }
  13642 
  13643         if (loopback_p->flags & BCM_OAM_BHH_LBM_INGRESS_DISCOVERY_MEP_TLV) {
  13644             flags |= BCM_BHH_LBM_INGRESS_DISCOVERY_MEP_TLV;
  13645         } else if (loopback_p->flags & BCM_OAM_BHH_LBM_EGRESS_DISCOVERY_MEP_TLV) {
  13646             flags |= BCM_BHH_LBM_EGRESS_DISCOVERY_MEP_TLV;
  13647         } else if (loopback_p->flags & BCM_OAM_BHH_LBM_ICC_MEP_TLV) {
  13648             flags |= BCM_BHH_LBM_ICC_MEP_TLV;
  13649         } else if (loopback_p->flags & BCM_OAM_BHH_LBM_ICC_MIP_TLV) {
  13650             flags |= BCM_BHH_LBM_ICC_MIP_TLV;
  13651         } else {
  13652             flags |= BCM_BHH_LBM_ICC_MEP_TLV; /* Default */
  13653         }
  13654 
  13655         if (loopback_p->flags & BCM_OAM_BHH_LBR_ICC_MEP_TLV) {
  13656             flags |= BCM_BHH_LBR_ICC_MEP_TLV;
  13657         } else if (loopback_p->flags & BCM_OAM_BHH_LBR_ICC_MIP_TLV) {
  13658             flags |= BCM_BHH_LBR_ICC_MIP_TLV;
  13659         }
  13660 
  13661         sal_memset(&msg, 0, sizeof(msg));
  13662         msg.flags   = flags;
  13663         msg.sess_id = sess_id;
  13664         msg.int_pri = loopback_p->int_pri;
  13665         msg.pkt_pri = loopback_p->pkt_pri;
  13666 
  13667         /*
  13668          * Set period
  13669          */
  13670         msg.period  = _tr3_ccm_intervals[
  13671                              _bcm_tr3_oam_ccm_msecs_to_hw_encode(
  13672                                                             loopback_p->period)];
  13673 
  13674         /*
  13675          * Check TTL
  13676          */
  13677         if (loopback_p->ttl == 0 || loopback_p->ttl > 255) {
  13678             _BCM_OAM_UNLOCK(oc);
  13679             return BCM_E_PARAM;
  13680         }
  13681 
  13682         if (h_data_p->type == bcmOAMEndpointTypeBHHMPLSVccv &&
  13683              h_data_p->vccv_type == bcmOamBhhVccvTtl) {
  13684 
  13685             msg.ttl = 1; /* Only TTL 1 is valid */
  13686         } else {
  13687             msg.ttl = loopback_p->ttl;
  13688         }
  13689 
  13690 
  13691 
  13692         /* Pack control message data into DMA buffer */
  13693         buffer     = oc->dma_buffer;
  13694         buffer_ptr = bhh_sdk_msg_ctrl_loopback_add_pack(buffer, &msg);
  13695         buffer_len = buffer_ptr - buffer;
  13696 
  13697         /* Send BHH Session Update message to uC */
  13698         rv = _bcm_tr3_oam_bhh_msg_send_receive(unit,
  13699                                          MOS_MSG_SUBCLASS_BHH_LOOPBACK_ADD,
  13700                                          buffer_len, 0,
  13701                                          MOS_MSG_SUBCLASS_BHH_LOOPBACK_ADD_REPLY,
  13702                                          &reply_len, _BHH_UC_MSG_TIMEOUT_USECS);
  13703 
  13704         if(BCM_SUCCESS(rv) && (reply_len != 0)) {
  13705             rv =  BCM_E_INTERNAL;
  13706         }
  13707     }
  13708     else {
  13709         rv = BCM_E_UNAVAIL;
  13710     }
  13711 
  13712     _BCM_OAM_UNLOCK(oc);
  13713     return (rv);
  13714 }
  13715 
  13716 /*
  13717  * Function:
  13718  *     bcm_tr3_oam_loopback_get
  13719  * Purpose:
  13720  *     
  13721  * Parameters:
  13722  *     unit - Device unit number
  13723  * Returns:
  13724  *     None
  13725  */
  13726 int
  13727 bcm_tr3_oam_loopback_get(int unit, bcm_oam_loopback_t *loopback_p)
  13728 {
  13729     _bcm_oam_control_t *oc;
  13730     int rv = BCM_E_NONE;
  13731     bhh_sdk_msg_ctrl_loopback_get_t msg;
  13732     _bcm_oam_hash_data_t *h_data_p;
  13733     uint8 *buffer, *buffer_ptr;
  13734     uint16 buffer_len, reply_len;
  13735     int sess_id = 0;
  13736 
  13737     /* Get OAM Control Structure. */
  13738     BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc));
  13739     _BCM_OAM_LOCK(oc);
  13740 
  13741     if (oc->ukernel_not_ready) {
  13742         _BCM_OAM_UNLOCK(oc);
  13743         return BCM_E_INIT;
  13744     }
  13745 
  13746     BCM_OAM_BHH_VALIDATE_EP(loopback_p->id);
  13747 
  13748     sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(loopback_p->id);
  13749 
  13750     /* Check endpoint status. */
  13751     rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id);
  13752     if ((BCM_E_EXISTS != rv)) {
  13753         /* Endpoint not in use. */
  13754         LOG_ERROR(BSL_LS_BCM_OAM,
  13755                   (BSL_META_U(unit,
  13756                               "OAM Error: Endpoint EP=%d %s.\n"),
  13757                    loopback_p->id, bcm_errmsg(rv)));
  13758         _BCM_OAM_UNLOCK(oc);
  13759         return (rv);
  13760     }
  13761 
  13762     h_data_p = &oc->oam_hash_data[loopback_p->id];
  13763 
  13764     /*
  13765      * Only BHH is supported
  13766      */
  13767     if (h_data_p->type == bcmOAMEndpointTypeBHHMPLS ||
  13768         h_data_p->type == bcmOAMEndpointTypeBHHMPLSVccv) {
  13769 
  13770         sal_memset(&msg, 0, sizeof(msg));
  13771         /* Send BHH Session Update message to uC */
  13772         rv = _bcm_tr3_oam_bhh_msg_send_receive(unit,
  13773                                          MOS_MSG_SUBCLASS_BHH_LOOPBACK_GET,
  13774                                          sess_id, 0,
  13775                                          MOS_MSG_SUBCLASS_BHH_LOOPBACK_GET_REPLY,
  13776                                          &reply_len, _BHH_UC_MSG_TIMEOUT_USECS);
  13777         if(BCM_FAILURE(rv)) {
  13778             LOG_ERROR(BSL_LS_BCM_OAM,
  13779                       (BSL_META_U(unit,
  13780                                   "OAM Error: Endpoint EP=%d %s.\n"),
  13781                        loopback_p->id, bcm_errmsg(rv)));
  13782             _BCM_OAM_UNLOCK(oc);
  13783             return (rv);
  13784         }
  13785 
  13786         /* Pack control message data into DMA buffer */
  13787         buffer     = oc->dma_buffer;
  13788         buffer_ptr = bhh_sdk_msg_ctrl_loopback_get_unpack(buffer, &msg);
  13789         buffer_len = buffer_ptr - buffer;
  13790 
  13791 
  13792         if (reply_len != buffer_len) {
  13793             rv =  BCM_E_INTERNAL;
  13794         } else {
  13795             /*
  13796              * Convert kernel space flags to host space flags
  13797              */
  13798             if (msg.flags & BCM_BHH_INC_REQUESTING_MEP_TLV) {
  13799                 loopback_p->flags |= BCM_OAM_BHH_INC_REQUESTING_MEP_TLV;
  13800             }
  13801 
  13802             if (msg.flags & BCM_BHH_LBM_INGRESS_DISCOVERY_MEP_TLV) {
  13803                 loopback_p->flags |= BCM_OAM_BHH_LBM_INGRESS_DISCOVERY_MEP_TLV;
  13804             } else if (msg.flags & BCM_BHH_LBM_EGRESS_DISCOVERY_MEP_TLV) {
  13805                 loopback_p->flags |= BCM_OAM_BHH_LBM_EGRESS_DISCOVERY_MEP_TLV;
  13806             } else if (msg.flags & BCM_BHH_LBM_ICC_MEP_TLV) {
  13807                 loopback_p->flags |= BCM_OAM_BHH_LBM_ICC_MEP_TLV;
  13808             } else if (msg.flags & BCM_BHH_LBM_ICC_MIP_TLV) {
  13809                 loopback_p->flags |= BCM_OAM_BHH_LBM_ICC_MIP_TLV;
  13810             }
  13811 
  13812             if (msg.flags & BCM_BHH_LBR_ICC_MEP_TLV) {
  13813                 loopback_p->flags |= BCM_OAM_BHH_LBR_ICC_MEP_TLV;
  13814             } else if (msg.flags & BCM_BHH_LBR_ICC_MIP_TLV) {
  13815                 loopback_p->flags |= BCM_OAM_BHH_LBR_ICC_MIP_TLV;
  13816             }
  13817 
  13818             if (msg.flags & BCM_BHH_TX_ENABLE) {
  13819                 loopback_p->flags |= BCM_OAM_LOOPBACK_TX_ENABLE;
  13820             }
  13821 
  13822             loopback_p->period                  = msg.period;
  13823             loopback_p->ttl                     = msg.ttl;
  13824             loopback_p->discovered_me.flags     = msg.discovery_flags;
  13825             loopback_p->discovered_me.name      = msg.discovery_id;
  13826             loopback_p->discovered_me.ttl       = msg.discovery_ttl;
  13827             loopback_p->rx_count                = msg.rx_count;
  13828             loopback_p->tx_count                = msg.tx_count;
  13829             loopback_p->drop_count              = msg.drop_count;
  13830             loopback_p->unexpected_response     = msg.unexpected_response;
  13831             loopback_p->out_of_sequence         = msg.out_of_sequence;
  13832             loopback_p->local_mipid_missmatch   = msg.local_mipid_missmatch;
  13833             loopback_p->remote_mipid_missmatch  = msg.remote_mipid_missmatch;
  13834             loopback_p->invalid_target_mep_tlv  = msg.invalid_target_mep_tlv;
  13835             loopback_p->invalid_mep_tlv_subtype = msg.invalid_mep_tlv_subtype;
  13836             loopback_p->invalid_tlv_offset      = msg.invalid_tlv_offset;
  13837             loopback_p->int_pri                 = msg.int_pri;
  13838             loopback_p->pkt_pri                 = msg.pkt_pri;
  13839 
  13840             rv = BCM_E_NONE;
  13841         }
  13842     }
  13843     else {
  13844         rv = BCM_E_UNAVAIL;
  13845     }
  13846 
  13847     _BCM_OAM_UNLOCK(oc);
  13848 
  13849     return (rv);
  13850 }
  13851 
  13852 /*
  13853  * Function:
  13854  *     bcm_tr3_oam_loopback_delete
  13855  * Purpose:
  13856  *     
  13857  * Parameters:
  13858  *     unit - Device unit number
  13859  * Returns:
  13860  *     None
  13861  */
  13862 int
  13863 bcm_tr3_oam_loopback_delete(int unit, bcm_oam_loopback_t *loopback_p)
  13864 {
  13865     _bcm_oam_control_t *oc;
  13866     int rv = BCM_E_NONE;
  13867     shr_bhh_msg_ctrl_loopback_delete_t msg;
  13868     uint8 *buffer, *buffer_ptr;
  13869     uint16 buffer_len, reply_len;
  13870     int sess_id = 0;
  13871     _bcm_oam_hash_data_t *h_data_p;
  13872 
  13873     /* Get OAM Control Structure. */
  13874     BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc));
  13875     _BCM_OAM_LOCK(oc);
  13876 
  13877     if (oc->ukernel_not_ready) {
  13878         _BCM_OAM_UNLOCK(oc);
  13879         return BCM_E_INIT;
  13880     }
  13881 
  13882 
  13883     BCM_OAM_BHH_VALIDATE_EP(loopback_p->id);
  13884 
  13885     sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(loopback_p->id);
  13886 
  13887     /* Check endpoint status. */
  13888     rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id);
  13889     if ((BCM_E_EXISTS != rv)) {
  13890         /* Endpoint not in use. */
  13891         LOG_ERROR(BSL_LS_BCM_OAM,
  13892                   (BSL_META_U(unit,
  13893                               "OAM Error: Endpoint EP=%d %s.\n"),
  13894                    loopback_p->id, bcm_errmsg(rv)));
  13895         _BCM_OAM_UNLOCK(oc);
  13896         return (rv);
  13897     }
  13898 
  13899     h_data_p = &oc->oam_hash_data[loopback_p->id];
  13900 
  13901     /*
  13902      * Only BHH is supported
  13903      */
  13904     if (h_data_p->type == bcmOAMEndpointTypeBHHMPLS ||
  13905         h_data_p->type == bcmOAMEndpointTypeBHHMPLSVccv) {
  13906 
  13907         msg.sess_id = sess_id;
  13908 
  13909         /* Pack control message data into DMA buffer */
  13910         buffer     = oc->dma_buffer;
  13911         buffer_ptr = shr_bhh_msg_ctrl_loopback_delete_pack(buffer, &msg);
  13912         buffer_len = buffer_ptr - buffer;
  13913 
  13914         /* Send BHH Session Update message to uC */
  13915         rv = _bcm_tr3_oam_bhh_msg_send_receive(unit,
  13916                       MOS_MSG_SUBCLASS_BHH_LOOPBACK_DELETE,
  13917                       buffer_len, 0,
  13918                       MOS_MSG_SUBCLASS_BHH_LOOPBACK_DELETE_REPLY,
  13919                       &reply_len, _BHH_UC_MSG_TIMEOUT_USECS);
  13920 
  13921         if(BCM_SUCCESS(rv) && (reply_len != 0))
  13922             rv =  BCM_E_INTERNAL;
  13923     }
  13924     else {
  13925         _BCM_OAM_UNLOCK(oc);
  13926         return BCM_E_UNAVAIL;
  13927     }
  13928 
  13929     _BCM_OAM_UNLOCK(oc);
  13930 
  13931     return (rv);
  13932 }
  13933 
  13934 /*
  13935  * Function:
  13936  *     bcm_tr3_oam_loss_add
  13937  * Purpose:
  13938  *        Loss Measurement add     
  13939  * Parameters:
  13940  *     unit - Device unit number
  13941  * Returns:
  13942  *     None
  13943  */
  13944 int
  13945 bcm_tr3_oam_loss_add(int unit, bcm_oam_loss_t *loss_p)
  13946 {
  13947     _bcm_oam_control_t *oc;
  13948     _bcm_oam_hash_data_t *h_data_p;
  13949     int rv = BCM_E_NONE;
  13950     bhh_sdk_msg_ctrl_loss_add_t msg;
  13951     uint8 *buffer, *buffer_ptr;
  13952     uint16 buffer_len, reply_len;
  13953     uint32 flags = 0;
  13954     int sess_id = 0;
  13955 
  13956     /* Get OAM Control Structure. */
  13957     BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc));
  13958     _BCM_OAM_LOCK(oc);
  13959 
  13960     if (oc->ukernel_not_ready) {
  13961         _BCM_OAM_UNLOCK(oc);
  13962         return BCM_E_INIT;
  13963     }
  13964 
  13965 
  13966     if (!oc->bhh_lm_dm_enable) {
  13967         LOG_ERROR(BSL_LS_BCM_OAM,
  13968                   (BSL_META_U(unit,
  13969                               "OAM Error: LM/DM not enabled\n")));
  13970         _BCM_OAM_UNLOCK(oc);
  13971         return BCM_E_DISABLED;
  13972     }
  13973 
  13974     BCM_OAM_BHH_VALIDATE_EP(loss_p->id);
  13975 
  13976     sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(loss_p->id);
  13977 
  13978     /* Check endpoint status. */
  13979     rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id);
  13980     if ((BCM_E_EXISTS != rv)) {
  13981         /* Endpoint not in use. */
  13982         LOG_ERROR(BSL_LS_BCM_OAM,
  13983                   (BSL_META_U(unit,
  13984                               "OAM Error: Endpoint EP=%d %s.\n"),
  13985                    loss_p->id, bcm_errmsg(rv)));
  13986         _BCM_OAM_UNLOCK(oc);
  13987         return (rv);
  13988     }
  13989 
  13990     h_data_p = &oc->oam_hash_data[loss_p->id];
  13991 
  13992     /*
  13993      * Only BHH is supported
  13994      */
  13995     if (h_data_p->type == bcmOAMEndpointTypeBHHMPLS ||
  13996         h_data_p->type == bcmOAMEndpointTypeBHHMPLSVccv) {
  13997 
  13998 	/*
  13999 	 * Convert host space flags to uKernel space flags
  14000 	 */
  14001 	if (loss_p->flags & BCM_OAM_LOSS_SINGLE_ENDED)
  14002 	    flags |= BCM_BHH_LM_SINGLE_ENDED;
  14003 
  14004 	if (loss_p->flags & BCM_OAM_LOSS_TX_ENABLE)
  14005 	    flags |= BCM_BHH_LM_TX_ENABLE;
  14006 
  14007         sal_memset(&msg, 0, sizeof(msg));
  14008 	msg.flags   = flags;
  14009 	msg.sess_id = sess_id;
  14010 
  14011 	/*
  14012 	 * Set period
  14013 	 */
  14014 	msg.period  = _tr3_ccm_intervals[_bcm_tr3_oam_ccm_msecs_to_hw_encode(loss_p->period)];
  14015     msg.int_pri = loss_p->int_pri;
  14016     msg.pkt_pri = loss_p->pkt_pri;
  14017 
  14018     /* Pack control message data into DMA buffer */
  14019     buffer     = oc->dma_buffer;
  14020     buffer_ptr = bhh_sdk_msg_ctrl_loss_add_pack(buffer, &msg);
  14021     buffer_len = buffer_ptr - buffer;
  14022 
  14023     /* Send BHH Session Update message to uC */
  14024     rv = _bcm_tr3_oam_bhh_msg_send_receive(unit,
  14025                       MOS_MSG_SUBCLASS_BHH_LOSS_MEASUREMENT_ADD,
  14026                       buffer_len, 0,
  14027                       MOS_MSG_SUBCLASS_BHH_LOSS_MEASUREMENT_ADD_REPLY,
  14028                       &reply_len, _BHH_UC_MSG_TIMEOUT_USECS);
  14029 
  14030     if(BCM_SUCCESS(rv) && (reply_len != 0)) 
  14031         rv =  BCM_E_INTERNAL;
  14032     }
  14033     else {
  14034         _BCM_OAM_UNLOCK(oc);
  14035         return BCM_E_UNAVAIL;
  14036     }
  14037 
  14038     _BCM_OAM_UNLOCK(oc);
  14039     return (rv);
  14040 }
  14041 
  14042 int
  14043 bcm_oam_bhh_convert_ep_to_time_spec(bcm_time_spec_t* bts, int sec, int ns)
  14044 {
  14045     int rv = BCM_E_NONE;
  14046 
  14047     if (bts != NULL) {
  14048         /* if both seconds and nanoseconds are negative or both positive,
  14049          * then the ucode's subtraction is ok.
  14050          * if seconds and nanoseconds have different signs, then "borrow"
  14051          * 1000000000 nanoseconds from seconds.
  14052          */
  14053         if ((sec < 0) && (ns > 0)) {
  14054             ns -= 1000000000;
  14055             sec += 1;
  14056         } else if ((sec > 0) && (ns < 0)) {
  14057             ns += 1000000000;
  14058             sec -= 1;
  14059         }
  14060 
  14061         if (ns < 0) {
  14062             /* if still negative, then something else is wrong.
  14063              * the nanoseconds field is the difference between two
  14064              * (non-negative) time-stamps.
  14065              */
  14066             rv = BCM_E_INTERNAL;
  14067         }
  14068 
  14069         /* if seconds is negative then set the bts is-negative flag,
  14070          * and use the absolute value of seconds & nanoseconds.
  14071          */
  14072         bts->isnegative  = (sec < 0 ? 1 : 0);
  14073         bts->seconds     = BCM_OAM_BHH_ABS(sec);
  14074         bts->nanoseconds = BCM_OAM_BHH_ABS(ns);
  14075     } else {
  14076         rv = BCM_E_INTERNAL;
  14077     }
  14078 
  14079     return rv;
  14080 }
  14081 
  14082 #if 0
  14083 /* d (difference) = m (minuend) - s (subtrahend) */
  14084 int
  14085 bcm_oam_bhh_time_spec_subtract(bcm_time_spec_t* d, bcm_time_spec_t* m, bcm_time_spec_t* s)
  14086 {
  14087     int rv = BCM_E_NONE;
  14088     int32 d_ns = 0;
  14089     int32 d_s = 0;
  14090 
  14091     if ((d != NULL) && (m != NULL) && (s != NULL)) {
  14092         /* subtract the nanoseconds first, then borrow is necessary. */
  14093         d_ns = m->nanoseconds - s->nanoseconds;
  14094         if (d_ns < 0) {
  14095             m->seconds = m->seconds - 1;
  14096             d_ns = 1000000000 + d_ns;
  14097         }
  14098         if (d_ns < 0) {
  14099             /* if still negative, then error */
  14100             rv = BCM_E_INTERNAL;
  14101             d_ns = abs(d_ns);
  14102         }
  14103         d->nanoseconds = d_ns;
  14104 
  14105         /* subtract the seconds next, check for negative. */
  14106         d_s = m->seconds - s->seconds;
  14107         if (d_s < 0) {
  14108             d->isnegative = TRUE;
  14109             d_s = abs(d_s);
  14110         } else {
  14111             d->isnegative = FALSE;
  14112         }
  14113         d->seconds = d_s;
  14114 
  14115     } else {
  14116         rv = BCM_E_INTERNAL;
  14117     }
  14118 
  14119     return rv;
  14120 }
  14121 #endif
  14122 
  14123 /*
  14124  * Function:
  14125  *     bcm_tr3_oam_loss_get
  14126  * Purpose:
  14127  *     Loss Measurement get
  14128  * Parameters:
  14129  *     unit - Device unit number
  14130  * Returns:
  14131  *     None
  14132  */
  14133 int
  14134 bcm_tr3_oam_loss_get(int unit, bcm_oam_loss_t *loss_p)
  14135 {
  14136     _bcm_oam_control_t *oc;
  14137     int rv = BCM_E_NONE;
  14138     bhh_sdk_msg_ctrl_loss_get_t msg;
  14139     _bcm_oam_hash_data_t *h_data_p;
  14140     uint8 *buffer, *buffer_ptr;
  14141     uint16 buffer_len, reply_len;
  14142     int sess_id = 0;
  14143 
  14144     /* Get OAM Control Structure. */
  14145     BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc));
  14146     _BCM_OAM_LOCK(oc);
  14147 
  14148     if (oc->ukernel_not_ready) {
  14149         _BCM_OAM_UNLOCK(oc);
  14150         return BCM_E_INIT;
  14151     }
  14152 
  14153 
  14154     BCM_OAM_BHH_VALIDATE_EP(loss_p->id);
  14155 
  14156     sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(loss_p->id);
  14157 
  14158     /* Check endpoint status. */
  14159     rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id);
  14160     if ((BCM_E_EXISTS != rv)) {
  14161         /* Endpoint not in use. */
  14162         LOG_ERROR(BSL_LS_BCM_OAM,
  14163                   (BSL_META_U(unit,
  14164                               "OAM Error: Endpoint EP=%d %s.\n"),
  14165                    loss_p->id, bcm_errmsg(rv)));
  14166         _BCM_OAM_UNLOCK(oc);
  14167         return (rv);
  14168     }
  14169 
  14170     h_data_p = &oc->oam_hash_data[loss_p->id];
  14171 
  14172     /*
  14173      * Only BHH is supported
  14174      */
  14175     if (h_data_p->type == bcmOAMEndpointTypeBHHMPLS ||
  14176         h_data_p->type == bcmOAMEndpointTypeBHHMPLSVccv) {
  14177 
  14178     sal_memset(&msg, 0, sizeof(msg));
  14179     /* Send BHH Session Update message to uC */
  14180     rv = _bcm_tr3_oam_bhh_msg_send_receive(unit,
  14181                       MOS_MSG_SUBCLASS_BHH_LOSS_MEASUREMENT_GET,
  14182                       sess_id, 0,
  14183                       MOS_MSG_SUBCLASS_BHH_LOSS_MEASUREMENT_GET_REPLY,
  14184                       &reply_len, _BHH_UC_MSG_TIMEOUT_USECS);
  14185     if(BCM_FAILURE(rv)) {
  14186         LOG_ERROR(BSL_LS_BCM_OAM,
  14187                   (BSL_META_U(unit,
  14188                               "OAM Error: Endpoint EP=%d %s.\n"),
  14189                    loss_p->id, bcm_errmsg(rv)));
  14190         _BCM_OAM_UNLOCK(oc);
  14191         return (rv);
  14192     }
  14193 
  14194     /* Pack control message data into DMA buffer */
  14195     buffer     = oc->dma_buffer;
  14196     buffer_ptr = bhh_sdk_msg_ctrl_loss_get_unpack(buffer, &msg);
  14197     buffer_len = buffer_ptr - buffer;
  14198 
  14199     if (reply_len != buffer_len) {
  14200         rv =  BCM_E_INTERNAL;
  14201     } else {
  14202         /*
  14203          * Convert kernel space flags to host space flags
  14204          */
  14205         if (msg.flags & BCM_BHH_LM_SINGLE_ENDED) {
  14206             loss_p->flags |= BCM_OAM_LOSS_SINGLE_ENDED;
  14207         }
  14208 
  14209         if (msg.flags & BCM_BHH_LM_TX_ENABLE) {
  14210             loss_p->flags |= BCM_OAM_LOSS_TX_ENABLE;
  14211         }
  14212 
  14213         if (msg.flags & BCM_BHH_LM_SLM) {
  14214             loss_p->flags |= BCM_OAM_LOSS_SLM;
  14215         }
  14216 
  14217         loss_p->period = msg.period;
  14218         loss_p->loss_threshold = msg.loss_threshold;             
  14219         loss_p->loss_nearend = msg.loss_nearend;               
  14220         loss_p->loss_farend = msg.loss_farend;    
  14221         loss_p->tx_nearend = msg.tx_nearend;            
  14222         loss_p->rx_nearend = msg.rx_nearend;              
  14223         loss_p->tx_farend = msg.tx_farend;               
  14224         loss_p->rx_farend = msg.rx_farend;               
  14225         loss_p->rx_oam_packets = msg.rx_oam_packets;          
  14226         loss_p->tx_oam_packets = msg.tx_oam_packets;          
  14227         loss_p->int_pri = msg.int_pri;
  14228         loss_p->pkt_pri = msg.pkt_pri;         
  14229 
  14230         rv = BCM_E_NONE;
  14231     }
  14232     }
  14233     else {
  14234         _BCM_OAM_UNLOCK(oc);
  14235         return BCM_E_UNAVAIL;
  14236     }
  14237 
  14238     _BCM_OAM_UNLOCK(oc);
  14239 
  14240     return (rv);
  14241 }
  14242 
  14243 /*
  14244  * Function:
  14245  *     bcm_tr3_oam_loss_delete
  14246  * Purpose:
  14247  *    Loss Measurement Delete 
  14248  * Parameters:
  14249  *     unit - Device unit number
  14250  * Returns:
  14251  *     None
  14252  */
  14253 int
  14254 bcm_tr3_oam_loss_delete(int unit, bcm_oam_loss_t *loss_p)
  14255 {
  14256     _bcm_oam_control_t *oc;
  14257     int rv = BCM_E_NONE;
  14258     shr_bhh_msg_ctrl_loss_delete_t msg;
  14259     uint8 *buffer, *buffer_ptr;
  14260     uint16 buffer_len, reply_len;
  14261     int sess_id = 0;
  14262     _bcm_oam_hash_data_t *h_data_p;
  14263 
  14264     /* Get OAM Control Structure. */
  14265     BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc));
  14266     _BCM_OAM_LOCK(oc);
  14267 
  14268     if (oc->ukernel_not_ready) {
  14269         _BCM_OAM_UNLOCK(oc);
  14270         return BCM_E_INIT;
  14271     }
  14272 
  14273 
  14274     BCM_OAM_BHH_VALIDATE_EP(loss_p->id);
  14275 
  14276     sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(loss_p->id);
  14277 
  14278     /* Check endpoint status. */
  14279     rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id);
  14280     if ((BCM_E_EXISTS != rv)) {
  14281         /* Endpoint not in use. */
  14282         LOG_ERROR(BSL_LS_BCM_OAM,
  14283                   (BSL_META_U(unit,
  14284                               "OAM Error: Endpoint EP=%d %s.\n"),
  14285                    loss_p->id, bcm_errmsg(rv)));
  14286         _BCM_OAM_UNLOCK(oc);
  14287         return (rv);
  14288     }
  14289 
  14290     h_data_p = &oc->oam_hash_data[loss_p->id];
  14291 
  14292     /*
  14293      * Only BHH is supported
  14294      */
  14295     if (h_data_p->type == bcmOAMEndpointTypeBHHMPLS ||
  14296         h_data_p->type == bcmOAMEndpointTypeBHHMPLSVccv) {
  14297 
  14298         msg.sess_id = sess_id;
  14299 
  14300         /* Pack control message data into DMA buffer */
  14301         buffer     = oc->dma_buffer;
  14302         buffer_ptr = shr_bhh_msg_ctrl_loss_delete_pack(buffer, &msg);
  14303         buffer_len = buffer_ptr - buffer;
  14304 
  14305         /* Send BHH Session Update message to uC */
  14306         rv = _bcm_tr3_oam_bhh_msg_send_receive(unit,
  14307                       MOS_MSG_SUBCLASS_BHH_LOSS_MEASUREMENT_DELETE,
  14308                       buffer_len, 0,
  14309                       MOS_MSG_SUBCLASS_BHH_LOSS_MEASUREMENT_DELETE_REPLY,
  14310                       &reply_len, _BHH_UC_MSG_TIMEOUT_USECS);
  14311 
  14312         if(BCM_SUCCESS(rv) && (reply_len != 0))
  14313             rv =  BCM_E_INTERNAL;
  14314     }
  14315     else {
  14316         _BCM_OAM_UNLOCK(oc);
  14317         return BCM_E_UNAVAIL;
  14318     }
  14319 
  14320     _BCM_OAM_UNLOCK(oc);
  14321 
  14322     return (rv);
  14323 }
  14324 
  14325 /*
  14326  * Function:
  14327  *     bcm_tr3_oam_delay_add
  14328  * Purpose:
  14329  *     Delay Measurement add     
  14330  * Parameters:
  14331  *     unit - Device unit number
  14332  * Returns:
  14333  *     None
  14334  */
  14335 int
  14336 bcm_tr3_oam_delay_add(int unit, bcm_oam_delay_t *delay_p)
  14337 {
  14338     _bcm_oam_control_t *oc;
  14339     _bcm_oam_hash_data_t *h_data_p;
  14340     int rv = BCM_E_NONE;
  14341     bhh_sdk_msg_ctrl_delay_add_t msg;
  14342     uint8 *buffer, *buffer_ptr;
  14343     uint16 buffer_len, reply_len;
  14344     uint32 flags = 0;
  14345     int sess_id = 0;
  14346 
  14347     /* Get OAM Control Structure. */
  14348     BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc));
  14349     _BCM_OAM_LOCK(oc);
  14350 
  14351     if (oc->ukernel_not_ready) {
  14352         _BCM_OAM_UNLOCK(oc);
  14353         return BCM_E_INIT;
  14354     }
  14355 
  14356 
  14357     if (!oc->bhh_lm_dm_enable) {
  14358         LOG_ERROR(BSL_LS_BCM_OAM,
  14359                   (BSL_META_U(unit,
  14360                               "OAM Error: LM/DM not enabled\n")));
  14361         _BCM_OAM_UNLOCK(oc);
  14362         return BCM_E_DISABLED;
  14363     }
  14364 
  14365 
  14366     BCM_OAM_BHH_VALIDATE_EP(delay_p->id);
  14367 
  14368     sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(delay_p->id);
  14369 
  14370     /* Check endpoint status. */
  14371     rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id);
  14372     if ((BCM_E_EXISTS != rv)) {
  14373         /* Endpoint not in use. */
  14374         LOG_ERROR(BSL_LS_BCM_OAM,
  14375                   (BSL_META_U(unit,
  14376                               "OAM Error: Endpoint EP=%d %s.\n"),
  14377                    delay_p->id, bcm_errmsg(rv)));
  14378         _BCM_OAM_UNLOCK(oc);
  14379         return (rv);
  14380     }
  14381 
  14382     h_data_p = &oc->oam_hash_data[delay_p->id];
  14383 
  14384     /*
  14385      * Only BHH is supported
  14386      */
  14387     if (h_data_p->type == bcmOAMEndpointTypeBHHMPLS ||
  14388         h_data_p->type == bcmOAMEndpointTypeBHHMPLSVccv) {
  14389     /*
  14390      * Convert host space flags to uKernel space flags
  14391      */
  14392     if (delay_p->flags & BCM_OAM_DELAY_ONE_WAY)
  14393         flags |= BCM_BHH_DM_ONE_WAY;
  14394 
  14395     if (delay_p->flags & BCM_OAM_DELAY_TX_ENABLE)
  14396         flags |= BCM_BHH_DM_TX_ENABLE;
  14397 
  14398     sal_memset(&msg, 0, sizeof(msg));
  14399     msg.flags   = flags;
  14400     msg.sess_id = sess_id;
  14401     msg.int_pri = delay_p->int_pri;
  14402     msg.pkt_pri = delay_p->pkt_pri;
  14403 
  14404     h_data_p->ts_format = delay_p->timestamp_format;
  14405 
  14406     if(delay_p->timestamp_format == bcmOAMTimestampFormatIEEE1588v1)
  14407         msg.dm_format = BCM_BHH_DM_TYPE_PTP;
  14408     else
  14409         msg.dm_format = BCM_BHH_DM_TYPE_NTP;
  14410 
  14411     /*
  14412      * Set period
  14413      */
  14414     msg.period  = _tr3_ccm_intervals[_bcm_tr3_oam_ccm_msecs_to_hw_encode(delay_p->period)];
  14415 
  14416     /* Pack control message data into DMA buffer */
  14417     buffer     = oc->dma_buffer;
  14418     buffer_ptr = bhh_sdk_msg_ctrl_delay_add_pack(buffer, &msg);
  14419     buffer_len = buffer_ptr - buffer;
  14420 
  14421     /* Send BHH Session Update message to uC */
  14422     rv = _bcm_tr3_oam_bhh_msg_send_receive(unit,
  14423                       MOS_MSG_SUBCLASS_BHH_DELAY_MEASUREMENT_ADD,
  14424                       buffer_len, 0,
  14425                       MOS_MSG_SUBCLASS_BHH_DELAY_MEASUREMENT_ADD_REPLY,
  14426                       &reply_len, _BHH_UC_MSG_TIMEOUT_USECS);
  14427 
  14428     if(BCM_SUCCESS(rv) && (reply_len != 0)) 
  14429         rv =  BCM_E_INTERNAL;
  14430     }
  14431     else {
  14432         _BCM_OAM_UNLOCK(oc);
  14433         return BCM_E_UNAVAIL;
  14434     }
  14435 
  14436     _BCM_OAM_UNLOCK(oc);
  14437     return (rv);
  14438 }
  14439 
  14440 /*
  14441  * Function:
  14442  *     bcm_tr3_oam_delay_get
  14443  * Purpose:
  14444  *     Delay Measurements get 
  14445  * Parameters:
  14446  *     unit - Device unit number
  14447  * Returns:
  14448  *     None
  14449  */
  14450 int
  14451 bcm_tr3_oam_delay_get(int unit, bcm_oam_delay_t *delay_p)
  14452 {
  14453     _bcm_oam_control_t *oc;
  14454     int rv = BCM_E_NONE;
  14455     bhh_sdk_msg_ctrl_delay_get_t msg;
  14456     _bcm_oam_hash_data_t *h_data_p;
  14457     uint8 *buffer, *buffer_ptr;
  14458     uint16 buffer_len, reply_len;
  14459     int sess_id = 0;
  14460 
  14461     /* Get OAM Control Structure. */
  14462     BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc));
  14463     _BCM_OAM_LOCK(oc);
  14464 
  14465     if (oc->ukernel_not_ready) {
  14466         _BCM_OAM_UNLOCK(oc);
  14467         return BCM_E_INIT;
  14468     }
  14469 
  14470 
  14471     BCM_OAM_BHH_VALIDATE_EP(delay_p->id);
  14472 
  14473     sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(delay_p->id);
  14474 
  14475     /* Check endpoint status. */
  14476     rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id);
  14477     if ((BCM_E_EXISTS != rv)) {
  14478         /* Endpoint not in use. */
  14479         LOG_ERROR(BSL_LS_BCM_OAM,
  14480                   (BSL_META_U(unit,
  14481                               "OAM Error: Endpoint EP=%d %s.\n"),
  14482                    delay_p->id, bcm_errmsg(rv)));
  14483         _BCM_OAM_UNLOCK(oc);
  14484         return (rv);
  14485     }
  14486 
  14487     h_data_p = &oc->oam_hash_data[delay_p->id];
  14488 
  14489     /*
  14490      * Only BHH is supported
  14491      */
  14492     if (h_data_p->type == bcmOAMEndpointTypeBHHMPLS ||
  14493         h_data_p->type == bcmOAMEndpointTypeBHHMPLSVccv) {
  14494 
  14495     sal_memset(&msg, 0, sizeof(msg));
  14496     /* Send BHH Session Update message to uC */
  14497     rv = _bcm_tr3_oam_bhh_msg_send_receive(unit,
  14498                       MOS_MSG_SUBCLASS_BHH_DELAY_MEASUREMENT_GET,
  14499                       sess_id, 0,
  14500                       MOS_MSG_SUBCLASS_BHH_DELAY_MEASUREMENT_GET_REPLY,
  14501                       &reply_len, _BHH_UC_MSG_TIMEOUT_USECS);
  14502     if(BCM_FAILURE(rv)) {
  14503         LOG_ERROR(BSL_LS_BCM_OAM,
  14504                   (BSL_META_U(unit,
  14505                               "OAM Error: Endpoint EP=%d %s.\n"),
  14506                    delay_p->id, bcm_errmsg(rv)));
  14507         _BCM_OAM_UNLOCK(oc);
  14508         return (rv);
  14509     }
  14510 
  14511     /* Pack control message data into DMA buffer */
  14512     buffer     = oc->dma_buffer;
  14513     buffer_ptr = bhh_sdk_msg_ctrl_delay_get_unpack(buffer, &msg);
  14514     buffer_len = buffer_ptr - buffer;
  14515 
  14516 
  14517     if (reply_len != buffer_len) {
  14518         rv =  BCM_E_INTERNAL;
  14519     } else {
  14520         /*
  14521          * Convert kernel space flags to host space flags
  14522          */
  14523         if (msg.flags & BCM_BHH_DM_ONE_WAY)
  14524             delay_p->flags |= BCM_OAM_DELAY_ONE_WAY;
  14525 
  14526         if (msg.flags & BCM_BHH_DM_TX_ENABLE)
  14527             delay_p->flags |= BCM_OAM_DELAY_TX_ENABLE;
  14528 
  14529         delay_p->period = msg.period;
  14530 
  14531         if(msg.dm_format == BCM_BHH_DM_TYPE_PTP)
  14532             delay_p->timestamp_format = bcmOAMTimestampFormatIEEE1588v1;
  14533         else
  14534             delay_p->timestamp_format = bcmOAMTimestampFormatNTP;
  14535 
  14536         rv = bcm_oam_bhh_convert_ep_to_time_spec(&(delay_p->delay), 
  14537                                        msg.delay_seconds, msg.delay_nanoseconds);
  14538         if(BCM_SUCCESS(rv)) {
  14539             rv = bcm_oam_bhh_convert_ep_to_time_spec(&(delay_p->txf), 
  14540                                        msg.txf_seconds, msg.txf_nanoseconds);
  14541         }
  14542         if(BCM_SUCCESS(rv)) {
  14543             rv = bcm_oam_bhh_convert_ep_to_time_spec(&(delay_p->rxf), 
  14544                                        msg.rxf_seconds, msg.rxf_nanoseconds);
  14545         }
  14546         if(BCM_SUCCESS(rv)) {
  14547             rv = bcm_oam_bhh_convert_ep_to_time_spec(&(delay_p->txb), 
  14548                                        msg.txb_seconds, msg.txb_nanoseconds);
  14549         }
  14550         if(BCM_SUCCESS(rv)) {
  14551             rv = bcm_oam_bhh_convert_ep_to_time_spec(&(delay_p->rxb), 
  14552                                        msg.rxb_seconds, msg.rxb_nanoseconds);
  14553         }
  14554         delay_p->rx_oam_packets = msg.rx_oam_packets;
  14555         delay_p->tx_oam_packets = msg.tx_oam_packets;
  14556         delay_p->int_pri = msg.int_pri;
  14557         delay_p->pkt_pri = msg.pkt_pri;
  14558 
  14559         rv = BCM_E_NONE;
  14560     }
  14561     }
  14562     else {
  14563         _BCM_OAM_UNLOCK(oc);
  14564         return BCM_E_UNAVAIL;
  14565     }
  14566 
  14567     _BCM_OAM_UNLOCK(oc);
  14568 
  14569     return (rv);
  14570 }
  14571 
  14572 /*
  14573  * Function:
  14574  *     bcm_tr3_oam_delay_delete
  14575  * Purpose:
  14576  *     Delay Measurement Delete 
  14577  * Parameters:
  14578  *     unit - Device unit number
  14579  * Returns:
  14580  *     None
  14581  */
  14582 int
  14583 bcm_tr3_oam_delay_delete(int unit, bcm_oam_delay_t *delay_p)
  14584 {
  14585     _bcm_oam_control_t *oc;
  14586     int rv = BCM_E_NONE;
  14587     shr_bhh_msg_ctrl_delay_delete_t msg;
  14588     uint8 *buffer, *buffer_ptr;
  14589     uint16 buffer_len, reply_len;
  14590     int sess_id = 0;
  14591     _bcm_oam_hash_data_t *h_data_p;
  14592 
  14593     /* Get OAM Control Structure. */
  14594     BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc));
  14595     _BCM_OAM_LOCK(oc);
  14596 
  14597     if (oc->ukernel_not_ready) {
  14598         _BCM_OAM_UNLOCK(oc);
  14599         return BCM_E_INIT;
  14600     }
  14601 
  14602 
  14603     BCM_OAM_BHH_VALIDATE_EP(delay_p->id);
  14604 
  14605     sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(delay_p->id);
  14606 
  14607     /* Check endpoint status. */
  14608     rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id);
  14609     if ((BCM_E_EXISTS != rv)) {
  14610         /* Endpoint not in use. */
  14611         LOG_ERROR(BSL_LS_BCM_OAM,
  14612                   (BSL_META_U(unit,
  14613                               "OAM Error: Endpoint EP=%d %s.\n"),
  14614                    delay_p->id, bcm_errmsg(rv)));
  14615         _BCM_OAM_UNLOCK(oc);
  14616         return (rv);
  14617     }
  14618 
  14619     h_data_p = &oc->oam_hash_data[delay_p->id];
  14620 
  14621     /*
  14622      * Only BHH is supported
  14623      */
  14624     if (h_data_p->type == bcmOAMEndpointTypeBHHMPLS ||
  14625         h_data_p->type == bcmOAMEndpointTypeBHHMPLSVccv) {
  14626 
  14627         msg.sess_id = sess_id;
  14628 
  14629         /* Pack control message data into DMA buffer */
  14630         buffer     = oc->dma_buffer;
  14631         buffer_ptr = shr_bhh_msg_ctrl_delay_delete_pack(buffer, &msg);
  14632         buffer_len = buffer_ptr - buffer;
  14633 
  14634         /* Send BHH Session Update message to uC */
  14635         rv = _bcm_tr3_oam_bhh_msg_send_receive(unit,
  14636                       MOS_MSG_SUBCLASS_BHH_DELAY_MEASUREMENT_DELETE,
  14637                       buffer_len, 0,
  14638                       MOS_MSG_SUBCLASS_BHH_DELAY_MEASUREMENT_DELETE_REPLY,
  14639                       &reply_len, _BHH_UC_MSG_TIMEOUT_USECS);
  14640 
  14641         if(BCM_SUCCESS(rv) && (reply_len != 0))
  14642             rv =  BCM_E_INTERNAL;
  14643     }
  14644     else {
  14645         rv = BCM_E_UNAVAIL;
  14646     }
  14647 
  14648     _BCM_OAM_UNLOCK(oc);
  14649 
  14650     return (rv);
  14651 }
  14652 
  14653 /*
  14654  * Function:
  14655  *      bcm_tr3_oam_csf_add
  14656  * Purpose:
  14657  *      Start CSF PDU transmission
  14658  * Parameters:
  14659  *      unit    - (IN)    Unit number.
  14660  *      csf_ptr - (INOUT) CSF object
  14661  * Returns:
  14662  *      BCM_E_XXX
  14663  * Notes:
  14664  */
  14665 int bcm_tr3_oam_csf_add(int unit, bcm_oam_csf_t *csf_p)
  14666 {
  14667     _bcm_oam_control_t         *oc;
  14668     _bcm_oam_hash_data_t       *h_data_p;
  14669     bhh_sdk_msg_ctrl_csf_add_t  msg;
  14670     uint8                      *buffer, *buffer_ptr;
  14671     uint16                      buffer_len, reply_len;
  14672     int                         sess_id = 0;
  14673     int                         rv = BCM_E_NONE;
  14674 
  14675     /* Get OAM Control Structure. */
  14676     BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc));
  14677     _BCM_OAM_LOCK(oc);
  14678 
  14679     if (oc->ukernel_not_ready) {
  14680         _BCM_OAM_UNLOCK(oc);
  14681         return BCM_E_INIT;
  14682     }
  14683 
  14684     BCM_OAM_BHH_VALIDATE_EP(csf_p->id);
  14685     sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(csf_p->id);
  14686 
  14687     /* Check endpoint status. */
  14688     rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id);
  14689     if ((BCM_E_EXISTS != rv)) {
  14690         /* Endpoint not in use. */
  14691         LOG_ERROR(BSL_LS_BCM_OAM,
  14692                   (BSL_META_U(unit,
  14693                               "OAM(unit %d) Error: Endpoint EP=%d %s.\n"),
  14694                    unit, csf_p->id, bcm_errmsg(rv)));
  14695         _BCM_OAM_UNLOCK(oc);
  14696         return (rv);
  14697     }
  14698 
  14699     if ((csf_p->period != BCM_OAM_ENDPOINT_CCM_PERIOD_1S) &&
  14700         (csf_p->period != BCM_OAM_ENDPOINT_CCM_PERIOD_1M)) {
  14701         /* Only 1S and 1M are supported */
  14702         _BCM_OAM_UNLOCK(oc);
  14703         return BCM_E_PARAM;
  14704     }
  14705 
  14706     h_data_p = &oc->oam_hash_data[csf_p->id];
  14707     /*
  14708      * Only BHH is supported
  14709      */
  14710     if (h_data_p->type != bcmOAMEndpointTypeBHHMPLS &&
  14711         h_data_p->type != bcmOAMEndpointTypeBHHMPLSVccv) {
  14712         _BCM_OAM_UNLOCK(oc);
  14713         return BCM_E_UNAVAIL;
  14714     }
  14715 
  14716     sal_memset(&msg, 0, sizeof(msg));
  14717     msg.sess_id = sess_id;
  14718     msg.int_pri = csf_p->int_pri;
  14719     msg.pkt_pri = csf_p->pkt_pri;
  14720 
  14721     switch(csf_p->type) {
  14722         case BCM_OAM_CSF_LOS:
  14723             msg.type = SHR_CSF_TYPE_LOS;
  14724             break;
  14725 
  14726         case BCM_OAM_CSF_FDI:
  14727             msg.type = SHR_CSF_TYPE_FDI;
  14728             break;
  14729 
  14730         case BCM_OAM_CSF_RDI:
  14731             msg.type = SHR_CSF_TYPE_RDI;
  14732             break;
  14733 
  14734         case BCM_OAM_CSF_DCI:
  14735             msg.type = SHR_CSF_TYPE_DCI;
  14736             break;
  14737 
  14738         default:
  14739             _BCM_OAM_UNLOCK(oc);
  14740             return BCM_E_PARAM;
  14741     }
  14742 
  14743     /*
  14744      * Set period
  14745      */
  14746     msg.period  = csf_p->period;
  14747 
  14748     /* Pack control message data into DMA buffer */
  14749     buffer     = oc->dma_buffer;
  14750     buffer_ptr = bhh_sdk_msg_ctrl_csf_add_pack(buffer, &msg);
  14751     buffer_len = buffer_ptr - buffer;
  14752 
  14753     /* Send BHH Session Update message to uC */
  14754     rv = _bcm_tr3_oam_bhh_msg_send_receive(unit,
  14755                                            MOS_MSG_SUBCLASS_BHH_CSF_ADD,
  14756                                            buffer_len, 0,
  14757                                            MOS_MSG_SUBCLASS_BHH_CSF_ADD_REPLY,
  14758                                            &reply_len,
  14759                                            _BHH_UC_MSG_TIMEOUT_USECS);
  14760 
  14761     if(BCM_SUCCESS(rv) && (reply_len != 0)) {
  14762         rv =  BCM_E_INTERNAL;
  14763     }
  14764 
  14765     _BCM_OAM_UNLOCK(oc);
  14766     return rv;
  14767 }
  14768 
  14769 /*
  14770  * Function:
  14771  *      bcm_tr3_oam_csf_get
  14772  * Purpose:
  14773  *      Get CSF info
  14774  * Parameters:
  14775  *      unit    - (IN)  Unit number.
  14776  *      csf_ptr - (OUT) CSF object
  14777  * Returns:
  14778  *      BCM_E_XXX
  14779  * Notes:
  14780  */
  14781 int bcm_tr3_oam_csf_get(int unit, bcm_oam_csf_t *csf_p)
  14782 {
  14783     _bcm_oam_control_t          *oc;
  14784     bhh_sdk_msg_ctrl_csf_get_t   msg;
  14785     _bcm_oam_hash_data_t        *h_data_p;
  14786     uint8                       *buffer, *buffer_ptr;
  14787     uint16                       buffer_len, reply_len;
  14788     int                          sess_id = 0;
  14789     int                          rv = BCM_E_NONE;
  14790 
  14791     /* Get OAM Control Structure. */
  14792     BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc));
  14793     _BCM_OAM_LOCK(oc);
  14794 
  14795     if (oc->ukernel_not_ready) {
  14796         _BCM_OAM_UNLOCK(oc);
  14797         return BCM_E_INIT;
  14798     }
  14799 
  14800     BCM_OAM_BHH_VALIDATE_EP(csf_p->id);
  14801     sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(csf_p->id);
  14802 
  14803     /* Check endpoint status. */
  14804     rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id);
  14805     if ((BCM_E_EXISTS != rv)) {
  14806         /* Endpoint not in use. */
  14807         LOG_ERROR(BSL_LS_BCM_OAM,
  14808                   (BSL_META_U(unit,
  14809                               "OAM(unit %d) Error: Endpoint EP=%d %s.\n"),
  14810                    unit, csf_p->id, bcm_errmsg(rv)));
  14811         _BCM_OAM_UNLOCK(oc);
  14812         return (rv);
  14813     }
  14814 
  14815     h_data_p = &oc->oam_hash_data[csf_p->id];
  14816 
  14817     if (h_data_p->type != bcmOAMEndpointTypeBHHMPLS &&
  14818         h_data_p->type != bcmOAMEndpointTypeBHHMPLSVccv) {
  14819         _BCM_OAM_UNLOCK(oc);
  14820         return BCM_E_UNAVAIL;
  14821     }
  14822 
  14823 
  14824     sal_memset(&msg, 0, sizeof(msg));
  14825 
  14826     /* Send BHH Session Update message to uC */
  14827     rv = _bcm_tr3_oam_bhh_msg_send_receive(unit,
  14828                                            MOS_MSG_SUBCLASS_BHH_CSF_GET,
  14829                                            sess_id, 0,
  14830                                            MOS_MSG_SUBCLASS_BHH_CSF_GET_REPLY,
  14831                                            &reply_len,
  14832                                            _BHH_UC_MSG_TIMEOUT_USECS);
  14833     if(BCM_FAILURE(rv)) {
  14834         LOG_ERROR(BSL_LS_BCM_OAM,
  14835                   (BSL_META_U(unit,
  14836                               "OAM(unit %d) Error: Endpoint EP=%d %s.\n"),
  14837                    unit, csf_p->id, bcm_errmsg(rv)));
  14838         _BCM_OAM_UNLOCK(oc);
  14839         return (rv);
  14840     }
  14841 
  14842     /* Pack control message data into DMA buffer */
  14843     buffer     = oc->dma_buffer;
  14844     buffer_ptr = bhh_sdk_msg_ctrl_csf_get_unpack(buffer, &msg);
  14845     buffer_len = buffer_ptr - buffer;
  14846 
  14847 
  14848     if (reply_len != buffer_len) {
  14849         _BCM_OAM_UNLOCK(oc);
  14850         return BCM_E_INTERNAL;
  14851     }
  14852 
  14853     switch(msg.type) {
  14854         case SHR_CSF_TYPE_LOS:
  14855             csf_p->type = BCM_OAM_CSF_LOS;
  14856             break;
  14857 
  14858         case SHR_CSF_TYPE_FDI:
  14859             csf_p->type = BCM_OAM_CSF_FDI;
  14860             break;
  14861 
  14862         case SHR_CSF_TYPE_RDI:
  14863             csf_p->type = BCM_OAM_CSF_RDI;
  14864             break;
  14865 
  14866         case SHR_CSF_TYPE_DCI:
  14867             csf_p->type = BCM_OAM_CSF_DCI;
  14868             break;
  14869 
  14870         default:
  14871             _BCM_OAM_UNLOCK(oc);
  14872             return BCM_E_INTERNAL;
  14873     }
  14874 
  14875     csf_p->period  = msg.period;
  14876     csf_p->flags   = msg.flags;
  14877     csf_p->pkt_pri = msg.pkt_pri;
  14878     csf_p->int_pri = msg.int_pri;
  14879 
  14880 
  14881     _BCM_OAM_UNLOCK(oc);
  14882     return BCM_E_NONE;
  14883 
  14884 }
  14885 
  14886 /*
  14887  * Function:
  14888  *      bcm_tr3_oam_csf_delete
  14889  * Purpose:
  14890  *      Stop CSF PDU transmission
  14891  * Parameters:
  14892  *      unit    - (IN  Unit number.
  14893  *      csf_ptr - (IN) CSF object
  14894  * Returns:
  14895  *      BCM_E_XXX
  14896  * Notes:
  14897  */
  14898 int bcm_tr3_oam_csf_delete(int unit, bcm_oam_csf_t *csf_p)
  14899 {
  14900     _bcm_oam_control_t   *oc;
  14901     _bcm_oam_hash_data_t *h_data_p;
  14902     uint16                reply_len;
  14903     int                   sess_id;
  14904     int                   rv = BCM_E_NONE;
  14905 
  14906     /* Get OAM Control Structure. */
  14907     BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc));
  14908     _BCM_OAM_LOCK(oc);
  14909 
  14910     if (oc->ukernel_not_ready) {
  14911         _BCM_OAM_UNLOCK(oc);
  14912         return BCM_E_INIT;
  14913     }
  14914 
  14915     BCM_OAM_BHH_VALIDATE_EP(csf_p->id);
  14916     sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(csf_p->id);
  14917 
  14918     /* Check endpoint status. */
  14919     rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id);
  14920     if ((BCM_E_EXISTS != rv)) {
  14921         /* Endpoint not in use. */
  14922         LOG_ERROR(BSL_LS_BCM_OAM,
  14923                   (BSL_META_U(unit,
  14924                               "OAM(unit %d) Error: Endpoint EP=%d %s.\n"),
  14925                    unit, csf_p->id, bcm_errmsg(rv)));
  14926         _BCM_OAM_UNLOCK(oc);
  14927         return (rv);
  14928     }
  14929 
  14930     h_data_p = &oc->oam_hash_data[csf_p->id];
  14931 
  14932     if (h_data_p->type != bcmOAMEndpointTypeBHHMPLS &&
  14933         h_data_p->type != bcmOAMEndpointTypeBHHMPLSVccv) {
  14934         _BCM_OAM_UNLOCK(oc);
  14935         return BCM_E_UNAVAIL;
  14936     }
  14937 
  14938     /* Send BHH Session Update message to uC */
  14939     rv = _bcm_tr3_oam_bhh_msg_send_receive(unit,
  14940                                            MOS_MSG_SUBCLASS_BHH_CSF_DELETE,
  14941                                            sess_id, 0,
  14942                                            MOS_MSG_SUBCLASS_BHH_CSF_DELETE_REPLY,
  14943                                            &reply_len,
  14944                                            _BHH_UC_MSG_TIMEOUT_USECS);
  14945     _BCM_OAM_UNLOCK(oc);
  14946     return (rv);
  14947 }
  14948 #endif /* defined(INCLUDE_BHH) */
  14949 
  14950 /*
  14951  * Function:
  14952  *      _bcm_tr3_bhh_endpoint_faults_multi_get
  14953  * Purpose:
  14954  *      Function to get faults for multiple BHH endpoints
  14955  *      in a single call.
  14956  * Parameters:
  14957  *      unit                (IN) BCM device number
  14958  *      flags               (IN) Flags is kept unused as of now.
  14959  *                                This is for any future enhancement
  14960  *      max_endpoints       (IN) Number of max endpoint for the protocol
  14961  *      faults              (OUT) Pointer to faults for all endpoints
  14962  *      endpoint_count      (OUT) Pointer to Number of valid endpoints with faults,
  14963  *                                filled by get API.
  14964  *
  14965  * Returns:
  14966  *      BCM_E_NONE          No error
  14967  *      BCM_E_XXXX          Error
  14968  */
  14969 #if defined (INCLUDE_BHH)
  14970 int _bcm_tr3_bhh_endpoint_faults_multi_get(
  14971         int unit,
  14972         uint32 flags,
  14973         uint32 max_endpoints,
  14974         bcm_oam_endpoint_fault_t *faults,
  14975         uint32 *endpoint_count)
  14976 {
  14977     int rv = BCM_E_NONE;
  14978     _bcm_oam_control_t *oc = NULL;
  14979     bcm_oam_endpoint_fault_t *faults_temp = faults;
  14980     uint8 *buffer;
  14981     uint16 reply_len;
  14982     uint32 sess_count;
  14983     uint32 ep_id;
  14984     uint32 ep_count = 0;
  14985     uint32 faults_bitmap;
  14986     _bcm_oam_hash_data_t *h_data_p;      /* Pointer to endpoint hash data.    */
  14987 
  14988      /* Get OAM control structure. */
  14989     BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc));
  14990 
  14991     _BCM_OAM_LOCK(oc);
  14992 
  14993     if(max_endpoints != oc->bhh_endpoint_count) {
  14994         rv = BCM_E_PARAM;
  14995         _BCM_OAM_UNLOCK(oc);
  14996         return (rv);
  14997     }
  14998 
  14999     sal_memset(faults, 0, ((sizeof(bcm_oam_endpoint_fault_t))*max_endpoints));
  15000 
  15001     rv = _bcm_tr3_oam_bhh_msg_send_receive(unit,
  15002              MOS_MSG_SUBCLASS_BHH_FAULTS_MULTI_GET,
  15003              0, 0,
  15004              MOS_MSG_SUBCLASS_BHH_FAULTS_MULTI_GET_REPLY,
  15005              &reply_len, _BHH_UC_MSG_TIMEOUT_USECS);
  15006 
  15007 
  15008     if (BCM_FAILURE(rv)) {
  15009         LOG_ERROR(BSL_LS_BCM_OAM,
  15010                 (BSL_META_U(unit,
  15011                             "OAM(unit %d) Error: BHH uKernel msg failed for"
  15012                             "faults multi get %s.\n"), unit,
  15013                  bcm_errmsg(rv)));
  15014         _BCM_OAM_UNLOCK(oc);
  15015         return (rv);
  15016     }
  15017 
  15018     if(reply_len != (oc->bhh_endpoint_count * sizeof(uint32))) {
  15019         rv = BCM_E_INTERNAL;
  15020         _BCM_OAM_UNLOCK(oc);
  15021         return (rv);
  15022     }
  15023     /* Unpack control message data into DMA buffer */
  15024     buffer = oc->dma_buffer;
  15025     for(sess_count = 0;sess_count < oc->bhh_endpoint_count;sess_count++)
  15026     {
  15027         ep_id = BCM_OAM_BHH_GET_SDK_EP(sess_count);
  15028 
  15029         /* Validate endpoint index value. */
  15030         BCM_OAM_BHH_VALIDATE_EP(ep_id);
  15031 
  15032         h_data_p =  &oc->oam_hash_data[ep_id];
  15033 
  15034         /* If endpoint not in use, ignore and continue for next session_id).
  15035          * If session is running in hostCPU, skip and Go to ep_id.*/
  15036         if(!(h_data_p->in_use) || (h_data_p->flags2 & BCM_OAM_ENDPOINT_FLAGS2_REDIRECT_TO_CPU)) {
  15037            continue;
  15038         }
  15039 
  15040          _SHR_UNPACK_U32(buffer, faults_bitmap);
  15041 
  15042         faults_temp->endpoint_id = BCM_OAM_BHH_GET_SDK_EP(sess_count);
  15043 
  15044         if(faults_bitmap & BHH_BTE_EVENT_CCM_TIMEOUT){
  15045             faults_temp->faults |= BCM_OAM_BHH_FAULT_CCM_TIMEOUT;
  15046         }
  15047         if(faults_bitmap & BHH_BTE_EVENT_CCM_RDI){
  15048             faults_temp->faults |= BCM_OAM_BHH_FAULT_CCM_RDI;
  15049         }
  15050         if(faults_bitmap & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_LEVEL){
  15051             faults_temp->faults |=
  15052                 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEG_LEVEL;
  15053         }
  15054          if(faults_bitmap & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_ID){
  15055             faults_temp->faults |=
  15056                 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEG_ID;
  15057         }
  15058         if(faults_bitmap & BHH_BTE_EVENT_CCM_UNKNOWN_MEP_ID){
  15059             faults_temp->faults |=
  15060                 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEP_ID;
  15061         }
  15062         if(faults_bitmap & BHH_BTE_EVENT_CCM_UNKNOWN_PERIOD){
  15063             faults_temp->faults |=
  15064                 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_PERIOD;
  15065         }
  15066         if(faults_bitmap & BHH_BTE_EVENT_CCM_UNKNOWN_PRIORITY){
  15067             faults_temp->faults |=
  15068                 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_PRIORITY;
  15069         }
  15070 
  15071         ep_count++;
  15072         faults_temp++;
  15073 
  15074     }
  15075 
  15076     *endpoint_count = ep_count;
  15077     _BCM_OAM_UNLOCK(oc);
  15078     return (rv);
  15079 
  15080 }
  15081 #endif
  15082 
  15083 /* Function:
  15084  *      bcm_tr3_oam_endpoint_faults_multi_get
  15085  * Purpose:
  15086  *      Function to get faults for multiple endpoints per protocl
  15087  *      in a single call.
  15088  * Parameters:
  15089  *      unit                (IN) BCM device number
  15090  *      flags               (IN) Flags is kept unused as of now.
  15091  *                               This is for any future enhancement
  15092  *      endpoint_protocol   (IN) Protocol type of the endpoints to retrieve faults
  15093  *      max_endpoints       (IN) Number of max endpoint for the protocol
  15094  *      faults              (OUT) Pointer to faults for all endpoints
  15095  *      endpoint_count      (OUT) Pointer to Number of valid endpoints with faults,
  15096  *                                by get API.
  15097  *
  15098  * Returns:
  15099  *      BCM_E_NONE          No error
  15100  *      BCM_E_XXXX          Error
  15101  */
  15102 
  15103 int bcm_tr3_oam_endpoint_faults_multi_get(
  15104         int unit,
  15105         uint32 flags,
  15106         bcm_oam_protocol_type_t endpoint_protocol,
  15107         uint32 max_endpoints,
  15108         bcm_oam_endpoint_fault_t *faults,
  15109         uint32 *endpoint_count)
  15110 
  15111 {
  15112     int rv = BCM_E_NONE;
  15113 
  15114     if(!faults) {
  15115         rv = BCM_E_PARAM;
  15116         return (rv);
  15117     }
  15118 
  15119     switch(endpoint_protocol) {
  15120 
  15121 #if defined(INCLUDE_BHH)
  15122         case bcmOamProtocolBhh:
  15123             *endpoint_count = 0;
  15124             rv = _bcm_tr3_bhh_endpoint_faults_multi_get(
  15125                     unit,
  15126                     flags,
  15127                     max_endpoints,
  15128                     faults,
  15129                     endpoint_count);
  15130         break;
  15131 #endif
  15132         default:
  15133             rv = BCM_E_UNAVAIL;
  15134             break;
  15135     }
  15136 
  15137     return rv;
  15138 
  15139 }
  15140 
  15141 #if defined(INCLUDE_BHH)
  15142 /*
  15143  * Function:
  15144  *     _bcm_tr3_oam_trunk_ports_update
  15145  * Purpose:
  15146  *     Associate or Dissociate ports from trunk in mapping table
  15147  *     maintained by BTE
  15148  * Parameters:
  15149  *     unit        - Device unit number
  15150  *     trunk_gport - Trunk Gport
  15151  *     max_ports   - Num ports being added/deleted
  15152  *     port_arr    - Array of physical port gports being added/deleted
  15153  *     add         - add == 1 indicates ports are being added
  15154  * Returns:
  15155  *     BCM_E_XXX
  15156  */
  15157 STATIC int
  15158 _bcm_tr3_oam_trunk_ports_update(int unit, bcm_gport_t trunk_gport, int max_ports,
  15159                                 bcm_gport_t *port_arr, uint8 add)
  15160 {
  15161     bcm_trunk_t                          trunk_id = BCM_TRUNK_INVALID;
  15162     _bcm_oam_control_t                  *oc = NULL;
  15163     bhh_sdk_msg_ctrl_trunk_map_update_t  msg;
  15164     uint8                               *buffer, *buffer_ptr;
  15165     uint16                               buffer_len, reply_len;
  15166     int                                  rv = BCM_E_NONE;
  15167     int                                  i;
  15168 
  15169     BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc));
  15170     _BCM_OAM_LOCK(oc);
  15171 
  15172     if (oc->ukernel_not_ready) {
  15173         _BCM_OAM_UNLOCK(oc);
  15174         return BCM_E_INIT;
  15175     }
  15176 
  15177     if (!BCM_GPORT_IS_TRUNK(trunk_gport)) {
  15178         _BCM_OAM_UNLOCK(oc);
  15179         return BCM_E_PARAM;
  15180     }
  15181 
  15182     if (max_ports >= SHR_BHH_MAX_PORTS) {
  15183         _BCM_OAM_UNLOCK(oc);
  15184         return BCM_E_PARAM;
  15185     }
  15186 
  15187     if (!port_arr) {
  15188         _BCM_OAM_UNLOCK(oc);
  15189         return BCM_E_PARAM;
  15190     }
  15191 
  15192     trunk_id = BCM_GPORT_TRUNK_GET(trunk_gport);
  15193     if (trunk_id == BCM_TRUNK_INVALID) {
  15194         _BCM_OAM_UNLOCK(oc);
  15195         return BCM_E_PARAM;
  15196     }
  15197 
  15198     if (add) {
  15199         msg.trunk_id = trunk_id;
  15200     } else {
  15201         msg.trunk_id = (uint16) SHR_BHH_INVALID_TRUNK_ID;
  15202     }
  15203     msg.num_ports = max_ports;
  15204     for (i = 0; i < max_ports; i++) {
  15205         if (BCM_GPORT_IS_LOCAL(port_arr[i])) {
  15206             msg.port_list[i] = BCM_GPORT_LOCAL_GET(port_arr[i]);
  15207         } else if (BCM_GPORT_IS_MODPORT(port_arr[i])) {
  15208             msg.port_list[i] = BCM_GPORT_MODPORT_PORT_GET(port_arr[i]);
  15209         } else {
  15210             _BCM_OAM_UNLOCK(oc);
  15211             return BCM_E_PARAM;
  15212         }
  15213     }
  15214 
  15215     /* Pack control message data into DMA buffer */
  15216     buffer     = oc->dma_buffer;
  15217     buffer_ptr = bhh_sdk_msg_ctrl_trunk_map_update_pack(buffer, &msg);
  15218     buffer_len = buffer_ptr - buffer;
  15219 
  15220     rv = _bcm_tr3_oam_bhh_msg_send_receive(
  15221                                    unit,
  15222                                    MOS_MSG_SUBCLASS_BHH_PORT_TRUNK_UPDATE,
  15223                                    buffer_len, 0,
  15224                                    MOS_MSG_SUBCLASS_BHH_PORT_TRUNK_UPDATE_REPLY,
  15225                                    &reply_len, _BHH_UC_MSG_TIMEOUT_USECS);
  15226 
  15227 
  15228     if (BCM_FAILURE(rv)) {
  15229         _BCM_OAM_UNLOCK(oc);
  15230         return rv;
  15231     }
  15232 
  15233     return BCM_E_NONE;
  15234 }
  15235 
  15236 /*
  15237  * Function:
  15238  *     bcm_tr3_oam_trunk_ports_add
  15239  * Purpose:
  15240  *     Associate  ports from trunk in mapping table maintained by BTE
  15241  * Parameters:
  15242  *     unit        - Device unit number
  15243  *     trunk_gport - Trunk Gport
  15244  *     max_ports   - Num ports being added
  15245  *     port_arr    - Array of physical port gports being added
  15246  * Returns:
  15247  *     BCM_E_XXX
  15248  */
  15249 int bcm_tr3_oam_trunk_ports_add(int unit, bcm_gport_t trunk_gport,
  15250                                 int max_ports, bcm_gport_t *port_arr)
  15251 {
  15252     return _bcm_tr3_oam_trunk_ports_update(unit, trunk_gport, max_ports,
  15253                                            port_arr, 1);
  15254 }
  15255 
  15256 /*
  15257  * Function:
  15258  *     bcm_tr3_oam_trunk_ports_delete
  15259  * Purpose:
  15260  *     Dissociate ports from trunk in mapping table maintained by BTE
  15261  * Parameters:
  15262  *     unit        - Device unit number
  15263  *     trunk_gport - Trunk Gport
  15264  *     max_ports   - Num ports being deleted
  15265  *     port_arr    - Array of physical port gports being deleted
  15266  * Returns:
  15267  *     BCM_E_XXX
  15268  */
  15269 int bcm_tr3_oam_trunk_ports_delete(int unit, bcm_gport_t trunk_gport,
  15270                                    int max_ports, bcm_gport_t *port_arr)
  15271 {
  15272     return _bcm_tr3_oam_trunk_ports_update(unit, trunk_gport, max_ports,
  15273                                            port_arr, 0);
  15274 }
  15275 
  15276 /*
  15277  * Function:
  15278  *     _bcm_fp_oam_port_trunk_map_get
  15279  * Purpose:
  15280  *     Get port to trunk mapping from UKERNEL
  15281  * Parameters:
  15282  *     unit          - (IN) BCM device number
  15283  *     trunk_gport   - (IN) Trunk gport
  15284  *     max_ports     - (IN) Max ports the port_arr can accomodate
  15285  *     port_arr      - (OUT) Ports in the trunk
  15286  *     port_count    - (OUT) Valid number of ports in the port_arr
  15287  *
  15288  * Returns:
  15289  *      BCM_E_XXX
  15290  */
  15291 int
  15292 bcm_tr3_oam_trunk_ports_get(int unit, bcm_gport_t trunk_gport, int max_ports,
  15293                             bcm_gport_t *port_arr, int *port_count)
  15294 {
  15295     bhh_sdk_msg_ctrl_trunk_map_get_t     msg;
  15296     uint8                               *buffer, *buffer_ptr;
  15297     uint16                               buffer_len, reply_len;
  15298     bcm_trunk_t                          trunk_id;
  15299     _bcm_oam_control_t                  *oc = NULL;
  15300     int                                  rv = BCM_E_NONE;
  15301     int                                  i;
  15302 
  15303     if (!BCM_GPORT_IS_TRUNK(trunk_gport)) {
  15304         return BCM_E_PARAM;
  15305     }
  15306 
  15307     trunk_id = BCM_GPORT_TRUNK_GET(trunk_gport);
  15308     if (trunk_id == BCM_TRUNK_INVALID) {
  15309         return BCM_E_PARAM;
  15310     }
  15311 
  15312     /* Get OAM Control Structure. */
  15313     BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc));
  15314     _BCM_OAM_LOCK(oc);
  15315 
  15316     /* Send trunk_id in the send length variable */
  15317     rv = _bcm_tr3_oam_bhh_msg_send_receive(
  15318                                    unit,
  15319                                    MOS_MSG_SUBCLASS_BHH_PORT_TRUNK_GET,
  15320                                    trunk_id, 0,
  15321                                    MOS_MSG_SUBCLASS_BHH_PORT_TRUNK_GET_REPLY,
  15322                                    &reply_len, _BHH_UC_MSG_TIMEOUT_USECS);
  15323     if (BCM_FAILURE(rv)) {
  15324         _BCM_OAM_UNLOCK(oc);
  15325         return rv;
  15326     }
  15327 
  15328     sal_memset(&msg, 0, sizeof(msg));
  15329     buffer     = oc->dma_buffer;
  15330     buffer_ptr = bhh_sdk_msg_ctrl_trunk_map_get_unpack(buffer, &msg);
  15331     buffer_len = buffer_ptr - buffer;
  15332 
  15333     if (reply_len != buffer_len) {
  15334         _BCM_OAM_UNLOCK(oc);
  15335         return BCM_E_INTERNAL;
  15336     }
  15337 
  15338     *port_count = msg.num_ports;
  15339     for (i = 0; (i < *port_count) && (i < max_ports); i++) {
  15340         port_arr[i] = msg.port_list[i];
  15341     }
  15342 
  15343     _BCM_OAM_UNLOCK(oc);
  15344     return BCM_E_NONE;;
  15345 }
  15346 #endif /* INCLUDE_BHH */
  15347 #endif