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


      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 
      9 #include <shared/bsl.h>
     10 
     11 #include <sal/core/libc.h>
     12 #include <soc/defs.h>
     13 #include <soc/drv.h>
     14 #include <soc/scache.h>
     15 #include <soc/profile_mem.h>
     16 #include <soc/hash.h>
     17 #include <soc/l3x.h>
     18 #include <soc/enduro.h>
     19 #if defined(BCM_KATANA_SUPPORT)
     20 #include <soc/katana.h>
     21 #endif /* BCM_KATANA_SUPPORT */
     22 
     23 #include <bcm/l3.h>
     24 #include <bcm/oam.h>
     25 
     26 #if defined(BCM_KATANA_SUPPORT)  && defined(INCLUDE_BHH)
     27 #include <bcm_int/esw/bhh.h>
     28 #include <bcm_int/esw/bhh_sdk_pack.h>
     29 #include <soc/uc.h>
     30 #endif /* BCM_KATANA_SUPPORT */
     31 
     32 #include <bcm_int/esw/oam.h>
     33 #include <bcm_int/esw/port.h>
     34 #include <bcm_int/esw/l3.h>
     35 #include <bcm_int/esw/switch.h>
     36 #include <bcm_int/esw/enduro.h>
     37 #include <bcm_int/esw/virtual.h>
     38 #include <bcm_int/esw_dispatch.h>
     39 
     40 #if defined(BCM_ENDURO_SUPPORT)
     41 
     42 #define BCM_OAM_LM_COUNTER_INDEX_INVALID  (-1)
     43 #define BCM_OAM_LM_COUNTER_OFFSET         (8)
     44 #define LEVEL_BIT_COUNT (3)
     45 #define LEVEL_COUNT (1 << (LEVEL_BIT_COUNT))
     46 #define MAX_ENDPOINT_LEVEL (LEVEL_COUNT - 1)
     47 #define MANGLED_GROUP_NAME_LENGTH (BCM_OAM_GROUP_NAME_LENGTH)
     48 
     49 #define UNSUPPORTED_ENDPOINT_FLAGS \
     50     (BCM_OAM_ENDPOINT_CCM_COPYTOCPU | \
     51      BCM_OAM_ENDPOINT_CCM_DROP | \
     52      BCM_OAM_ENDPOINT_DM_COPYTOCPU | \
     53      BCM_OAM_ENDPOINT_DM_DROP | \
     54      BCM_OAM_ENDPOINT_LB_COPYTOCPU | \
     55      BCM_OAM_ENDPOINT_LB_DROP | \
     56      BCM_OAM_ENDPOINT_LT_COPYTOCPU | \
     57      BCM_OAM_ENDPOINT_LT_DROP | \
     58      BCM_OAM_ENDPOINT_USE_QOS_MAP | \
     59      BCM_OAM_ENDPOINT_MATCH_INNER_VLAN | \
     60      BCM_OAM_ENDPOINT_REMOTE_DEFECT_TX | \
     61      BCM_OAM_ENDPOINT_CCM_COPYFIRSTTOCPU | \
     62      BCM_OAM_ENDPOINT_PRI_TAG)   
     63 
     64 #define CHECK_INIT \
     65     if (!oam_info_p->initialized) \
     66     { \
     67         return BCM_E_INIT; \
     68     }
     69 
     70 #define SET_OAM_INFO oam_info_p = &en_oam_info[unit];
     71 
     72 #define SET_GROUP(_group_index_) group_p = \
     73     oam_info_p->groups + _group_index_;
     74 
     75 #define SET_ENDPOINT(_endpoint_index_) endpoint_p = \
     76     oam_info_p->endpoints + _endpoint_index_;
     77 
     78 #define VALIDATE_GROUP_INDEX(_group_index_) \
     79     if ((_group_index_) < 0 || (_group_index_) >= oam_info_p->group_count) \
     80     { \
     81         return BCM_E_PARAM; \
     82     } \
     83 
     84 #define VALIDATE_ENDPOINT_INDEX(_endpoint_index_) \
     85     if ((_endpoint_index_) < 0 || \
     86         (_endpoint_index_) >= oam_info_p->endpoint_count) \
     87     { \
     88         return BCM_E_PARAM; \
     89     } \
     90 
     91 #define SET_LMEP_FIELD(unit, field, flag, mask) \
     92     if (soc_mem_field_valid(unit, L3_ENTRY_IPV4_UNICASTm, field)) { \
     93         soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, &l3_entry, field, \
     94             (flag & mask) ? 1 : 0); \
     95     } \
     96 
     97 #define GET_LMEP_FIELD(unit, field, flag) \
     98     if (soc_mem_field_valid(unit, L3_ENTRY_IPV4_UNICASTm, field)) { \
     99         if (soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, &l3_entry, field)) { \
    100             endpoint_info->flags |= flag; \
    101         } \
    102     }
    103 
    104 #if defined(BCM_KATANA_SUPPORT)  && defined(INCLUDE_BHH)
    105 
    106 #define BCM_OAM_BHH_VALIDATE_END_POINT(oam_p, ep) \
    107     if(((ep) < (oam_info_p->remote_endpoint_count + \
    108                 oam_info_p->local_tx_endpoint_count + \
    109                 oam_info_p->local_rx_endpoint_count)) || \
    110         ((ep) >= oam_info_p->endpoint_count)) \
    111     { \
    112         return BCM_E_PARAM; \
    113     }
    114 
    115 #define BCM_OAM_BHH_GET_UKERNEL_EP(oam_p, ep) \
    116         (ep  -  \
    117             (oam_p->remote_endpoint_count + \
    118             oam_p->local_tx_endpoint_count + \
    119             oam_p->local_rx_endpoint_count))
    120 
    121 #define BCM_OAM_BHH_GET_SDK_EP(oam_p, ep) \
    122 	    ((ep) + \
    123             (oam_p->remote_endpoint_count + \
    124             oam_p->local_tx_endpoint_count + \
    125             oam_p->local_rx_endpoint_count))
    126 /*
    127  * Protos
    128  */
    129 STATIC int _bcm_en_oam_bhh_hw_init(int unit);
    130 STATIC int _bcm_en_oam_bhh_msg_send_receive(int unit, uint8 s_subclass,
    131                              uint16 s_len, uint32 s_data,
    132 				 uint8 r_subclass, uint16 *r_len);
    133 STATIC void _bcm_en_oam_bhh_callback_thread(void *param);
    134 static int en_oam_mpls_tp_ach_channel_type = SHR_BHH_ACH_CHANNEL_TYPE;
    135 
    136 #endif
    137 
    138 /* Cache of ING_SERVICE_PRI_MAP Profile Table */
    139 static soc_profile_mem_t *ing_pri_map_profile[BCM_MAX_NUM_UNITS] = {NULL};
    140 #define ING_SERVICE_PRI_MAP_PROFILE_DEFAULT  0
    141 
    142 #if defined(BCM_KATANA_SUPPORT)
    143 /* Cache of OAM Opcode Profile Table */
    144 static soc_profile_mem_t *oam_opcode_profile[BCM_MAX_NUM_UNITS] = {NULL};
    145 #define OAM_OPCODE_PROFILE_DEFAULT  0
    146 #endif /* BCM_KATANA_SUPPORT */
    147 
    148 #define SOC_MODID_BIT_POS(unit)   _shr_popcount((unsigned int)SOC_PORT_ADDR_MAX(unit))
    149 #define SOC_MODID_MASK(unit)  (SOC_INFO(unit).modid_max << SOC_MODID_BIT_POS(unit))
    150 
    151 static _bcm_oam_info_t en_oam_info[BCM_MAX_NUM_UNITS];
    152 static int _bcm_en_oam_quantize_ccm_period(int period);
    153 
    154 static _bcm_oam_fault_t en_group_faults[] =
    155 {
    156     {CURRENT_XCON_CCM_DEFECTf, STICKY_XCON_CCM_DEFECTf,
    157         BCM_OAM_GROUP_FAULT_CCM_XCON, 0x08},
    158 
    159     {CURRENT_ERROR_CCM_DEFECTf, STICKY_ERROR_CCM_DEFECTf,
    160         BCM_OAM_GROUP_FAULT_CCM_ERROR, 0x04},
    161 
    162     {CURRENT_SOME_RMEP_CCM_DEFECTf, STICKY_SOME_RMEP_CCM_DEFECTf,
    163         BCM_OAM_GROUP_FAULT_CCM_TIMEOUT, 0x02},
    164 
    165     {CURRENT_SOME_RDI_DEFECTf, STICKY_SOME_RDI_DEFECTf,
    166         BCM_OAM_GROUP_FAULT_REMOTE, 0x01},
    167 
    168     {0, 0, 0, 0}
    169 };
    170 
    171 static _bcm_oam_fault_t en_endpoint_faults[] =
    172 {
    173     {CURRENT_RMEP_PORT_STATUS_DEFECTf, STICKY_RMEP_PORT_STATUS_DEFECTf,
    174         BCM_OAM_ENDPOINT_FAULT_PORT_DOWN, 0x08},
    175 
    176     {CURRENT_RMEP_INTERFACE_STATUS_DEFECTf,
    177         STICKY_RMEP_INTERFACE_STATUS_DEFECTf,
    178         BCM_OAM_ENDPOINT_FAULT_INTERFACE_DOWN, 0x04},
    179 
    180     {CURRENT_RMEP_CCM_DEFECTf, STICKY_RMEP_CCM_DEFECTf,
    181         BCM_OAM_ENDPOINT_FAULT_CCM_TIMEOUT, 0x20},
    182 
    183     {CURRENT_RMEP_LAST_RDIf, STICKY_RMEP_LAST_RDIf,
    184         BCM_OAM_ENDPOINT_FAULT_REMOTE, 0x10},
    185 
    186     {0, 0, 0, 0}
    187 };
    188 
    189 typedef struct en_interrupt_enable_fields_s {
    190     soc_field_t field;
    191     uint32      value;
    192 } en_interrupt_enable_fields_t;
    193 
    194 #ifndef BCM_KATANA_SUPPORT
    195 static _bcm_oam_interrupt_t en_interrupts[] =
    196 {
    197     {ANY_RMEP_TLV_PORT_DOWN_STATUSr, FIRST_RMEP_INDEXf, INVALIDf,
    198         ANY_RMEP_TLV_PORT_DOWN_INTRf, bcmOAMEventEndpointPortDown},
    199 
    200     {ANY_RMEP_TLV_PORT_UP_STATUSr, FIRST_RMEP_INDEXf, INVALIDf,
    201         ANY_RMEP_TLV_PORT_UP_INTRf, bcmOAMEventEndpointPortUp},
    202 
    203     {ANY_RMEP_TLV_INTERFACE_DOWN_STATUSr, FIRST_RMEP_INDEXf, INVALIDf,
    204         ANY_RMEP_TLV_INTERFACE_DOWN_INTRf, bcmOAMEventEndpointInterfaceDown},
    205 
    206     {ANY_RMEP_TLV_INTERFACE_UP_STATUSr, FIRST_RMEP_INDEXf, INVALIDf,
    207         ANY_RMEP_TLV_INTERFACE_UP_INTRf, bcmOAMEventEndpointInterfaceUp},
    208 
    209     {XCON_CCM_DEFECT_STATUSr, INVALIDf, FIRST_MA_INDEXf,
    210         ERROR_CCM_DEFECT_INTRf, bcmOAMEventGroupCCMxcon},
    211 
    212     {ERROR_CCM_DEFECT_STATUSr, INVALIDf, FIRST_MA_INDEXf,
    213         ERROR_CCM_DEFECT_INTRf, bcmOAMEventGroupCCMError},
    214 
    215     {SOME_RDI_DEFECT_STATUSr, FIRST_RMEP_INDEXf, FIRST_MA_INDEXf,
    216         SOME_RDI_DEFECT_INTRf, bcmOAMEventGroupRemote},
    217 
    218     {SOME_RMEP_CCM_DEFECT_STATUSr, FIRST_RMEP_INDEXf, FIRST_MA_INDEXf,
    219         SOME_RMEP_CCM_DEFECT_INTRf, bcmOAMEventGroupCCMTimeout},
    220 
    221     {INVALIDr, INVALIDf, 0}
    222 };
    223 
    224 static en_interrupt_enable_fields_t en_interrupt_enable_fields[bcmOAMEventCount] =
    225 {
    226     /* This must be in the same order as the bcm_oam_event_type_t enum */
    227     { ANY_RMEP_TLV_PORT_DOWN_INT_ENABLEf, 1}, 
    228     { ANY_RMEP_TLV_PORT_UP_INT_ENABLEf, 1},
    229     { ANY_RMEP_TLV_INTERFACE_DOWN_INT_ENABLEf, 1},
    230     { ANY_RMEP_TLV_INTERFACE_UP_INT_ENABLEf, 1},
    231     { INVALIDf, 0},
    232     { INVALIDf, 0},
    233     { INVALIDf, 0},
    234     { INVALIDf, 0},
    235     { INVALIDf, 0},
    236     { INVALIDf, 0},
    237     { INVALIDf, 0},
    238     { INVALIDf, 0},
    239     { INVALIDf, 0},
    240     { INVALIDf, 0},
    241     { XCON_CCM_DEFECT_INT_ENABLEf, 1},
    242     { ERROR_CCM_DEFECT_INT_ENABLEf, 1},
    243     { SOME_RDI_DEFECT_INT_ENABLEf, 1},
    244     { SOME_RMEP_CCM_DEFECT_INT_ENABLEf, 1},
    245     { INVALIDf, 0}
    246 };
    247 #else
    248 
    249 static _bcm_oam_interrupt_t en_interrupts[] =
    250 {
    251     {ANY_RMEP_TLV_PORT_DOWN_STATUSr, FIRST_RMEP_INDEXf, INVALIDf,
    252         ANY_RMEP_TLV_PORT_DOWN_INT_ENABLEf, 
    253         bcmOAMEventEndpointPortDown},
    254 
    255     {ANY_RMEP_TLV_PORT_UP_STATUSr, FIRST_RMEP_INDEXf, INVALIDf,
    256         ANY_RMEP_TLV_PORT_UP_INT_ENABLEf, 
    257         bcmOAMEventEndpointPortUp},
    258 
    259     {ANY_RMEP_TLV_INTERFACE_DOWN_STATUSr, FIRST_RMEP_INDEXf, INVALIDf,
    260         ANY_RMEP_TLV_INTERFACE_UP_TO_DOWN_TRANSITION_INT_ENABLEf, 
    261         bcmOAMEventEndpointInterfaceDown},
    262 
    263     {ANY_RMEP_TLV_INTERFACE_UP_STATUSr, FIRST_RMEP_INDEXf, INVALIDf,
    264         ANY_RMEP_TLV_INTERFACE_DOWN_TO_UP_TRANSITION_INT_ENABLEf, 
    265         bcmOAMEventEndpointInterfaceUp},
    266 
    267     {ANY_RMEP_TLV_INTERFACE_UP_STATUSr, FIRST_RMEP_INDEXf, INVALIDf,
    268         ANY_RMEP_TLV_INTERFACE_TESTING_TO_UP_TRANSITION_INT_ENABLEf, 
    269         bcmOAMEventEndpointInterfaceTestingToUp},        
    270 
    271     {ANY_RMEP_TLV_INTERFACE_UP_STATUSr, FIRST_RMEP_INDEXf, INVALIDf,
    272         ANY_RMEP_TLV_INTERFACE_UNKNOWN_TO_UP_TRANSITION_INT_ENABLEf, 
    273         bcmOAMEventEndpointInterfaceUnknownToUp},   
    274 
    275     {ANY_RMEP_TLV_INTERFACE_UP_STATUSr, FIRST_RMEP_INDEXf, INVALIDf,
    276         ANY_RMEP_TLV_INTERFACE_DORMANT_TO_UP_TRANSITION_INT_ENABLEf, 
    277         bcmOAMEventEndpointInterfaceDormantToUp},  
    278 
    279     {ANY_RMEP_TLV_INTERFACE_UP_STATUSr, FIRST_RMEP_INDEXf, INVALIDf,
    280         ANY_RMEP_TLV_INTERFACE_NOTPRESENT_TO_UP_TRANSITION_INT_ENABLEf, 
    281         bcmOAMEventEndpointInterfaceNotPresentToUp}, 
    282 
    283     {ANY_RMEP_TLV_INTERFACE_UP_STATUSr, FIRST_RMEP_INDEXf, INVALIDf,
    284         ANY_RMEP_TLV_INTERFACE_LLDOWN_TO_UP_TRANSITION_INT_ENABLEf, 
    285         bcmOAMEventEndpointInterfaceLLDownToUp}, 
    286 
    287     {ANY_RMEP_TLV_INTERFACE_DOWN_STATUSr, FIRST_RMEP_INDEXf, INVALIDf,
    288         ANY_RMEP_TLV_INTERFACE_UP_TO_TESTING_TRANSITION_INT_ENABLEf, 
    289         bcmOAMEventEndpointInterfaceTesting}, 
    290 
    291     {ANY_RMEP_TLV_INTERFACE_DOWN_STATUSr, FIRST_RMEP_INDEXf, INVALIDf,
    292         ANY_RMEP_TLV_INTERFACE_UP_TO_UNKNOWN_TRANSITION_INT_ENABLEf, 
    293         bcmOAMEventEndpointInterfaceUnkonwn}, 
    294 
    295     {ANY_RMEP_TLV_INTERFACE_DOWN_STATUSr, FIRST_RMEP_INDEXf, INVALIDf,
    296         ANY_RMEP_TLV_INTERFACE_UP_TO_DORMANT_TRANSITION_INT_ENABLEf, 
    297         bcmOAMEventEndpointInterfaceDormant}, 
    298 
    299     {ANY_RMEP_TLV_INTERFACE_DOWN_STATUSr, FIRST_RMEP_INDEXf, INVALIDf,
    300         ANY_RMEP_TLV_INTERFACE_UP_TO_NOTPRESENT_TRANSITION_INT_ENABLEf, 
    301         bcmOAMEventEndpointInterfaceNotPresent}, 	
    302 
    303     {ANY_RMEP_TLV_INTERFACE_DOWN_STATUSr, FIRST_RMEP_INDEXf, INVALIDf,
    304         ANY_RMEP_TLV_INTERFACE_UP_TO_LLDOWN_TRANSITION_INT_ENABLEf, 
    305         bcmOAMEventEndpointInterfaceLLDown}, 
    306 
    307     {XCON_CCM_DEFECT_STATUSr, INVALIDf, FIRST_MA_INDEXf,
    308         XCON_CCM_DEFECT_INT_ENABLEf,
    309         bcmOAMEventGroupCCMxcon},
    310 
    311     {ERROR_CCM_DEFECT_STATUSr, INVALIDf, FIRST_MA_INDEXf,
    312         ERROR_CCM_DEFECT_INT_ENABLEf, 
    313         bcmOAMEventGroupCCMError},
    314 
    315     {SOME_RDI_DEFECT_STATUSr, FIRST_RMEP_INDEXf, FIRST_MA_INDEXf,
    316         SOME_RDI_DEFECT_INT_ENABLEf, 
    317         bcmOAMEventGroupRemote},
    318 
    319     {SOME_RMEP_CCM_DEFECT_STATUSr, FIRST_RMEP_INDEXf, FIRST_MA_INDEXf,
    320         SOME_RMEP_CCM_DEFECT_INT_ENABLEf, 
    321         bcmOAMEventGroupCCMTimeout},
    322 
    323     {INVALIDr, INVALIDf, 0}
    324 };
    325 
    326 
    327 static en_interrupt_enable_fields_t en_interrupt_enable_fields[bcmOAMEventCount] =
    328 {
    329     /* This must be in the same order as the bcm_oam_event_type_t enum */
    330     { ANY_RMEP_TLV_PORT_DOWN_INT_ENABLEf, 1}, 
    331     { ANY_RMEP_TLV_PORT_UP_INT_ENABLEf, 1},
    332     { ANY_RMEP_TLV_INTERFACE_UP_TO_DOWN_TRANSITION_INT_ENABLEf, 1},
    333     { ANY_RMEP_TLV_INTERFACE_DOWN_TO_UP_TRANSITION_INT_ENABLEf, 1},
    334     { ANY_RMEP_TLV_INTERFACE_TESTING_TO_UP_TRANSITION_INT_ENABLEf, 1},
    335     { ANY_RMEP_TLV_INTERFACE_UNKNOWN_TO_UP_TRANSITION_INT_ENABLEf, 1},
    336     { ANY_RMEP_TLV_INTERFACE_DORMANT_TO_UP_TRANSITION_INT_ENABLEf, 1},
    337     { ANY_RMEP_TLV_INTERFACE_NOTPRESENT_TO_UP_TRANSITION_INT_ENABLEf, 1},
    338     { ANY_RMEP_TLV_INTERFACE_LLDOWN_TO_UP_TRANSITION_INT_ENABLEf, 1},
    339     { ANY_RMEP_TLV_INTERFACE_UP_TO_TESTING_TRANSITION_INT_ENABLEf, 1},
    340     { ANY_RMEP_TLV_INTERFACE_UP_TO_UNKNOWN_TRANSITION_INT_ENABLEf, 1},
    341     { ANY_RMEP_TLV_INTERFACE_UP_TO_DORMANT_TRANSITION_INT_ENABLEf, 1},
    342     { ANY_RMEP_TLV_INTERFACE_UP_TO_NOTPRESENT_TRANSITION_INT_ENABLEf, 1},
    343     { ANY_RMEP_TLV_INTERFACE_UP_TO_LLDOWN_TRANSITION_INT_ENABLEf, 1},
    344     { XCON_CCM_DEFECT_INT_ENABLEf, 1},
    345     { ERROR_CCM_DEFECT_INT_ENABLEf, 1},
    346     { SOME_RDI_DEFECT_INT_ENABLEf, 1},
    347     { SOME_RMEP_CCM_DEFECT_INT_ENABLEf, 1},
    348     { INVALIDf, 0}
    349 };
    350 
    351 #endif
    352 
    353 static uint32 en_ccm_periods[] =
    354 {
    355     BCM_OAM_ENDPOINT_CCM_PERIOD_DISABLED,
    356     BCM_OAM_ENDPOINT_CCM_PERIOD_3MS,
    357     BCM_OAM_ENDPOINT_CCM_PERIOD_10MS,
    358     BCM_OAM_ENDPOINT_CCM_PERIOD_100MS,
    359     BCM_OAM_ENDPOINT_CCM_PERIOD_1S,
    360     BCM_OAM_ENDPOINT_CCM_PERIOD_10S,
    361     BCM_OAM_ENDPOINT_CCM_PERIOD_1M,
    362     BCM_OAM_ENDPOINT_CCM_PERIOD_10M,
    363     _BCM_OAM_ENDPOINT_CCM_PERIOD_UNDEFINED
    364 };
    365 
    366 static void *_bcm_en_oam_alloc_clear(unsigned int size, char *description)
    367 {
    368     void *block_p;
    369 
    370     block_p = sal_alloc(size, description);
    371 
    372     if (block_p != NULL)
    373     {
    374         sal_memset(block_p, 0, size);
    375     }
    376 
    377     return block_p;
    378 }
    379 
    380 static int _bcm_en_oam_handle_interrupt(int unit, soc_field_t fault_field)
    381 {
    382     _bcm_oam_info_t *oam_info_p;
    383     _bcm_oam_interrupt_t *interrupt_p;
    384     uint32 interrupt_status;
    385     bcm_oam_group_t group_index;
    386     bcm_oam_endpoint_t endpoint_index;
    387     _bcm_oam_event_handler_t *event_handler_p;
    388     uint32 flags = 0;
    389 
    390     SET_OAM_INFO;
    391 
    392     CHECK_INIT;
    393 
    394     BCM_IF_ERROR_RETURN(bcm_esw_oam_lock(unit));
    395 
    396     for (interrupt_p = en_interrupts;
    397         interrupt_p->status_register != INVALIDr;
    398         ++interrupt_p)
    399     {
    400         if (BCM_FAILURE(soc_reg32_get(unit, interrupt_p->status_register,
    401                         REG_PORT_ANY, 0, &interrupt_status))) {
    402             continue;
    403         }
    404 
    405         if (!soc_reg_field_get(unit, interrupt_p->status_register,
    406                                      interrupt_status, VALIDf))
    407         {
    408             continue;
    409         }
    410         if (soc_reg_field_get(unit, interrupt_p->status_register,
    411             interrupt_status, VALIDf) &&
    412             oam_info_p->event_handler_count[interrupt_p->event_type] > 0)
    413         {
    414             /* Reset callback flag for each interrupt */
    415             flags = 0;
    416             group_index = (interrupt_p->group_index_field != INVALIDf) ?
    417                 (int)soc_reg_field_get(unit, interrupt_p->status_register,
    418                     interrupt_status, interrupt_p->group_index_field) :
    419                 BCM_OAM_GROUP_INVALID;
    420 
    421             endpoint_index = (interrupt_p->endpoint_index_field != INVALIDf) ?
    422                 (int)soc_reg_field_get(unit, interrupt_p->status_register,
    423                     interrupt_status, interrupt_p->endpoint_index_field) :
    424                 BCM_OAM_ENDPOINT_INVALID;
    425 
    426             if (endpoint_index != BCM_OAM_ENDPOINT_INVALID)
    427             {
    428                 /* Find the logical endpoint for this RMEP */
    429 
    430                 endpoint_index = oam_info_p->remote_endpoints[endpoint_index];
    431             }
    432 
    433             flags |= soc_reg_field_get(unit, interrupt_p->status_register,
    434                 interrupt_status, MULTIf) ? BCM_OAM_EVENT_FLAGS_MULTIPLE : 0;
    435 
    436             for (event_handler_p = oam_info_p->event_handler_list_p;
    437                 event_handler_p != NULL;
    438                 event_handler_p = event_handler_p->next_p)
    439             {
    440                 if (SHR_BITGET(event_handler_p->event_types.w,
    441                     interrupt_p->event_type))
    442                 {
    443                     event_handler_p->cb(unit, flags, interrupt_p->event_type,
    444                         group_index, endpoint_index,
    445                         event_handler_p->user_data);
    446                 }
    447             }
    448         }
    449 
    450         /* Clear interrupt */
    451         if (BCM_FAILURE(soc_reg32_set(unit, interrupt_p->status_register,
    452                         REG_PORT_ANY, 0, 0))) {
    453             continue;
    454         }
    455     }
    456 
    457     return bcm_esw_oam_unlock(unit);
    458 }
    459 
    460 #ifdef BCM_WARM_BOOT_SUPPORT
    461 
    462 #define BCM_WB_VERSION_1_0                SOC_SCACHE_VERSION(1,0)
    463 #define BCM_WB_VERSION_1_1                SOC_SCACHE_VERSION(1,1)
    464 #define BCM_WB_DEFAULT_VERSION            BCM_WB_VERSION_1_1
    465 
    466 #define BCM_OAM_WB_SCACHE_V1_REMOTE_EP_ID_OFFSET(_scache_, _remote_index_)     \
    467     ((_scache_) + (_remote_index_) * sizeof(bcm_oam_endpoint_t))
    468 
    469 #define BCM_OAM_WB_SCACHE_V1_TX_EP_ID_OFFSET(_scache_, _tx_index_)      \
    470     ((_scache_) +                                                       \
    471     ((oam_info_p->remote_endpoint_count + (_tx_index_)) *               \
    472                                                sizeof(bcm_oam_endpoint_t)))
    473 
    474 #define BCM_OAM_WB_SCACHE_V1_RX_EP_ID_OFFSET(_scache_, _rx_index_) \
    475          ((_scache_)                           +                \
    476          ((oam_info_p->remote_endpoint_count   +                \
    477            oam_info_p->local_tx_endpoint_count +                \
    478           (_rx_index_)) * sizeof(bcm_oam_endpoint_t)))
    479 
    480 /*
    481  * Function:
    482  *      bcm_en_oam_scache_alloc
    483  * Purpose:
    484  *      Allocate memory for OAM module in scache
    485  * Parameters:
    486  *      unit - (IN) Unit number.
    487  * Returns:
    488  *      BCM_E_XXX
    489  * Notes:
    490  */
    491 STATIC int
    492 bcm_en_oam_scache_alloc(int unit)
    493 {
    494     _bcm_oam_info_t *oam_info_p;
    495     soc_scache_handle_t scache_handle;
    496     uint8 *oam_scache;
    497     int alloc_sz = 0;
    498 
    499     SET_OAM_INFO;
    500     alloc_sz = BCM_OAM_GROUP_NAME_LENGTH * (oam_info_p->group_count);
    501 
    502     /* Number of oam groups */
    503     alloc_sz += sizeof(int);
    504 
    505     /* VFP group, IFP VP group, IFP GLP group */
    506     alloc_sz += 3 * sizeof(bcm_field_group_t);
    507 
    508     /* Endpoint id */
    509     alloc_sz += (oam_info_p->endpoint_count * sizeof(bcm_oam_endpoint_t));
    510 
    511     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_OAM, 0);
    512     BCM_IF_ERROR_RETURN(_bcm_esw_scache_ptr_get(unit, scache_handle, 1,
    513                         alloc_sz, &oam_scache, BCM_WB_DEFAULT_VERSION, NULL));
    514     return BCM_E_NONE;
    515 }
    516 
    517 static int _bcm_en_oam_warm_boot(int unit)
    518 {
    519     _bcm_oam_info_t *oam_info_p;
    520     _bcm_oam_group_t *group_p;
    521     int group_index;
    522     maid_reduction_entry_t maid_reduction_entry;
    523     ma_state_entry_t ma_state_entry;
    524     int maid_reduction_valid;
    525     int ma_state_valid;
    526     _bcm_oam_endpoint_t *endpoint_p;
    527     int l3_entry_count;
    528     int l3_entry_index;
    529     l3_entry_ipv4_unicast_entry_t l3_entry;
    530     uint32 level_bitmap;
    531     int level;
    532     int lmep_index;
    533     int stable_size;
    534     int glp;
    535     int port;
    536     int epidx;
    537     int group_count;
    538     bcm_vlan_t vlan;
    539     lmep_entry_t lmep_entry;
    540     rmep_entry_t rmep_entry;
    541     ma_index_entry_t ma_index_entry;
    542     uint8 *oam_scache, *ptr;
    543     soc_scache_handle_t scache_handle;
    544     uint16 scache_version = 0;
    545     int remote_index, local_rx_index;
    546     int realloc_size = 0;
    547     int rv = BCM_E_NONE;
    548 
    549     SET_OAM_INFO;
    550 
    551     /* Get groups */
    552 
    553     SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size));
    554     if (!SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit) && (stable_size > 0)) {
    555 
    556         SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_OAM, 0);
    557         rv = _bcm_esw_scache_ptr_get(unit, scache_handle, 0, 0,
    558                                      &oam_scache, BCM_WB_DEFAULT_VERSION,
    559                                      &scache_version);
    560         if (BCM_E_NOT_FOUND == rv) {
    561             /* Upgrading from SDK release that does not have warmboot state */
    562             bcm_en_oam_scache_alloc(unit);
    563             return BCM_E_NONE;
    564         } else if (BCM_FAILURE(rv)) {
    565             return rv;
    566         }
    567 
    568         /* Recover the FP groups */
    569         sal_memcpy(&oam_info_p->vfp_group, oam_scache, sizeof(bcm_field_group_t));
    570         oam_scache += sizeof(bcm_field_group_t);
    571         sal_memcpy(&oam_info_p->fp_vp_group, oam_scache, sizeof(bcm_field_group_t));
    572         oam_scache += sizeof(bcm_field_group_t);
    573         sal_memcpy(&oam_info_p->fp_glp_group, oam_scache, sizeof(bcm_field_group_t));
    574         oam_scache += sizeof(bcm_field_group_t);
    575 
    576         /* Recover the OAM groups */
    577         sal_memcpy(&group_count, oam_scache, sizeof(int));
    578         oam_scache += sizeof(int);
    579     } else {
    580         return BCM_E_NONE;
    581     }
    582 
    583     for (group_index = 0; group_index < oam_info_p->group_count;
    584         ++group_index)
    585     {
    586         SOC_IF_ERROR_RETURN(READ_MAID_REDUCTIONm(unit,
    587             MEM_BLOCK_ANY, group_index, &maid_reduction_entry));
    588 
    589         SOC_IF_ERROR_RETURN(READ_MA_STATEm(unit, MEM_BLOCK_ANY, group_index,
    590             &ma_state_entry));
    591 
    592         maid_reduction_valid = soc_MAID_REDUCTIONm_field32_get(unit,
    593             &maid_reduction_entry, VALIDf);
    594 
    595         ma_state_valid = soc_MA_STATEm_field32_get(unit,
    596             &ma_state_entry, VALIDf);
    597 
    598         if (maid_reduction_valid || ma_state_valid)
    599         {
    600             if (!maid_reduction_valid || !ma_state_valid)
    601             {
    602                 return BCM_E_INTERNAL;
    603             }
    604 
    605             SET_GROUP(group_index);
    606 
    607             if (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit) || (stable_size == 0)) {
    608                 /* Return zeros as the name */
    609                 sal_memset(group_p->name, 0, BCM_OAM_GROUP_NAME_LENGTH);
    610             } else {
    611                 /* Use stored values */
    612                 /*
    613                  * COVERITY
    614                  * oam_scache has been initilized in _bcm_esw_scache_ptr_get
    615                  */
    616                  /* coverity[uninit_use_in_call : FALSE] */
    617                 memcpy(group_p->name, oam_scache, BCM_OAM_GROUP_NAME_LENGTH);
    618                 oam_scache += BCM_OAM_GROUP_NAME_LENGTH;
    619             }
    620             group_p->in_use = 1;
    621         }
    622     }
    623 
    624     /* Get endpoints */
    625     epidx = -1;
    626     l3_entry_count = soc_mem_index_count(unit, L3_ENTRY_IPV4_UNICASTm);
    627 
    628     for (l3_entry_index = 0; l3_entry_index < l3_entry_count; ++l3_entry_index)
    629     {
    630         SOC_IF_ERROR_RETURN(READ_L3_ENTRY_IPV4_UNICASTm(unit, MEM_BLOCK_ANY,
    631             l3_entry_index, &l3_entry));
    632 
    633         if (soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, &l3_entry, VALIDf))
    634         {
    635             switch (soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, &l3_entry, KEY_TYPEf))
    636             {
    637                 case TR_L3_HASH_KEY_TYPE_RMEP:
    638                     remote_index =
    639                         soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, &l3_entry,
    640                                                                RMEP__RMEP_PTRf);
    641 
    642                     if (scache_version >= BCM_WB_VERSION_1_1) {
    643                         ptr = BCM_OAM_WB_SCACHE_V1_REMOTE_EP_ID_OFFSET(
    644                                                                    oam_scache,
    645                                                                    remote_index);
    646                         sal_memcpy(&epidx, ptr, sizeof(bcm_oam_endpoint_t));
    647                     } else {
    648                         epidx++;
    649                     }
    650                     SET_ENDPOINT(epidx);
    651 
    652                     endpoint_p->remote_index = remote_index;
    653                     SOC_IF_ERROR_RETURN(READ_RMEPm(unit, MEM_BLOCK_ANY,
    654                         endpoint_p->remote_index, &rmep_entry));
    655 
    656                     if (!soc_RMEPm_field32_get(unit, &rmep_entry, VALIDf))
    657                     {
    658                         return BCM_E_INTERNAL;
    659                     }
    660 
    661                     endpoint_p->in_use = 1;
    662                     endpoint_p->is_remote = 1;
    663 
    664                     endpoint_p->group_index = soc_RMEPm_field32_get(unit,
    665                         &rmep_entry, MAID_INDEXf);
    666 
    667                     endpoint_p->name = soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit,
    668                         &l3_entry, RMEP__MEPIDf);
    669 
    670                     endpoint_p->level = soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit,
    671                         &l3_entry, RMEP__MDLf);
    672 
    673                     endpoint_p->vlan = soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit,
    674                         &l3_entry, RMEP__VIDf);
    675 
    676                     if (endpoint_p->vlan == 0) {
    677                         port = soc_L3_ENTRY_IPV4_UNICASTm_field32_get
    678                                               (unit, &l3_entry, RMEP__SGLPf);
    679 #if defined(INCLUDE_L3)
    680                         if (_bcm_vp_used_get(unit, port, _bcmVpTypeMim)) {
    681                             /* Associated with MIM VP */
    682                             endpoint_p->vp = port;
    683                         } else
    684 #endif /* INCLUDE_L3 */
    685                         {
    686                             /* Associated with physical port */
    687                             endpoint_p->glp = port;
    688                         }
    689                     } else {
    690                         endpoint_p->glp = soc_L3_ENTRY_IPV4_UNICASTm_field32_get
    691                                               (unit, &l3_entry, RMEP__SGLPf);
    692                     }
    693 
    694                     SHR_BITSET(oam_info_p->remote_endpoints_in_use,
    695                         endpoint_p->remote_index);
    696                     oam_info_p->remote_endpoints[endpoint_p->remote_index] =
    697                         epidx;
    698 
    699                     break;
    700 
    701                 case TR_L3_HASH_KEY_TYPE_LMEP:
    702                     level_bitmap = soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit,
    703                         &l3_entry, LMEP__MDL_BITMAPf);
    704 
    705                     for (level = 0; level < LEVEL_COUNT; ++level)
    706                     {
    707                         if (level_bitmap & (1 << level))
    708                         {
    709                             /* There's an endpoint here at this level */
    710                             local_rx_index =
    711                                 soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit,
    712                                     &l3_entry, LMEP__MA_BASE_PTRf) <<
    713                                         LEVEL_BIT_COUNT | level;
    714 
    715                             if (scache_version >= BCM_WB_VERSION_1_1) {
    716                                 ptr =
    717                                     BCM_OAM_WB_SCACHE_V1_RX_EP_ID_OFFSET(
    718                                                                    oam_scache,
    719                                                                    local_rx_index);
    720                                 sal_memcpy(&epidx, ptr,
    721                                            sizeof(bcm_oam_endpoint_t));
    722                             } else {
    723                                 epidx++;
    724                             }
    725                             SET_ENDPOINT(epidx);
    726 
    727                             endpoint_p->local_rx_index = local_rx_index;
    728                             SOC_IF_ERROR_RETURN(READ_MA_INDEXm(unit,
    729                                 MEM_BLOCK_ANY, endpoint_p->local_rx_index,
    730                                 &ma_index_entry));
    731 
    732                             endpoint_p->in_use = 1;
    733                             endpoint_p->is_remote = 0;
    734                             endpoint_p->local_rx_enabled = 1;
    735 
    736                             endpoint_p->group_index =
    737                                 soc_MA_INDEXm_field32_get(unit,
    738                                     &ma_index_entry, MA_PTRf);
    739 #if defined(BCM_KATANA_SUPPORT)
    740                             if (SOC_IS_KATANAX(unit)) {
    741                                 endpoint_p->opcode_profile_index =
    742                                     soc_MA_INDEXm_field32_get(unit,
    743                                             &ma_index_entry,
    744                                             OAM_OPCODE_CONTROL_PROFILE_PTRf);
    745 
    746                                 /* Increment the reference count for the opcode_profile_count */
    747                                 rv = soc_profile_mem_reference(unit, oam_opcode_profile[unit],
    748                                         endpoint_p->opcode_profile_index, 1);
    749                                 if (BCM_FAILURE(rv)) {
    750                                     LOG_ERROR(BSL_LS_BCM_OAM,
    751                                             (BSL_META_U(unit,
    752                                                         "OAM Error: Opcode Profile entry recover failed "
    753                                                         "(EP=%d) - %s.\n"), epidx, bcm_errmsg(rv)));
    754                                     return rv;
    755                                 }     
    756                             }
    757 #endif /* BCM_KATANA_SUPPORT */
    758                             /* Name is not used for receive-only endpoints */
    759                             endpoint_p->name = 0xffff;
    760 
    761                             endpoint_p->level = level;
    762 
    763                             endpoint_p->vlan =
    764                                 soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit,
    765                                     &l3_entry, LMEP__VIDf);
    766 
    767                             if (endpoint_p->vlan == 0) {
    768                                 endpoint_p->vp = 
    769                                     soc_L3_ENTRY_IPV4_UNICASTm_field32_get
    770                                                (unit, &l3_entry, LMEP__SGLPf);
    771                             } else {
    772                                 endpoint_p->glp = 
    773                                     soc_L3_ENTRY_IPV4_UNICASTm_field32_get
    774                                                (unit, &l3_entry, LMEP__SGLPf);
    775                             }
    776 
    777                             SHR_BITSET(oam_info_p->local_rx_endpoints_in_use,
    778                                 endpoint_p->local_rx_index);
    779 
    780                         }
    781                     }
    782 
    783                     break;
    784 
    785                 default:
    786                     continue;
    787             }
    788         }
    789     }
    790 
    791     SET_ENDPOINT(0); /* To avoid [-Werror=maybe-uninitialized] */
    792     for (lmep_index = 0; lmep_index < oam_info_p->local_tx_endpoint_count;
    793         ++lmep_index)
    794     {
    795         SOC_IF_ERROR_RETURN(READ_LMEPm(unit, MEM_BLOCK_ANY, lmep_index,
    796             &lmep_entry));
    797 
    798         group_index = soc_LMEPm_field32_get(unit,
    799             &lmep_entry, MAID_INDEXf);
    800 
    801         SOC_IF_ERROR_RETURN(READ_MAID_REDUCTIONm(unit,
    802             MEM_BLOCK_ANY, group_index, &maid_reduction_entry));
    803 
    804         if (soc_MAID_REDUCTIONm_field32_get(unit, &maid_reduction_entry, 
    805                                             VALIDf))
    806         {
    807             glp = soc_LMEPm_field32_get(unit, &lmep_entry, DESTf);
    808             vlan = soc_LMEPm_field32_get(unit, &lmep_entry, VLAN_IDf);
    809 
    810             /* Check if a receive entry exists for this LMEP */
    811             if (scache_version >= BCM_WB_VERSION_1_1) {
    812                 ptr = BCM_OAM_WB_SCACHE_V1_TX_EP_ID_OFFSET(oam_scache,
    813                                                            lmep_index);
    814                 sal_memcpy(&epidx, ptr, sizeof(bcm_oam_endpoint_t));
    815                 SET_ENDPOINT(epidx);
    816             } else {
    817                 for (epidx = 0; epidx < oam_info_p->endpoint_count; epidx++) {
    818                     SET_ENDPOINT(epidx);
    819                     if (!endpoint_p->in_use) {
    820                         continue;
    821                     }
    822                     if ((endpoint_p->vlan == vlan) && (endpoint_p->glp == glp) &&
    823                         (endpoint_p->name == 0xffff)) {
    824                         break;
    825                     }
    826                 }
    827                 if (epidx == oam_info_p->endpoint_count) {
    828                     /* Receive entry not found - local TX only */
    829                     /* Allocate a new ID */
    830                     for (epidx = 0; epidx < oam_info_p->endpoint_count; epidx++) {
    831                         SET_ENDPOINT(epidx);
    832                         if (!endpoint_p->in_use) {
    833                             break;
    834                         }
    835                     }
    836                 }
    837             }
    838 
    839             endpoint_p->glp = glp;
    840             endpoint_p->vlan = vlan;
    841             endpoint_p->in_use = 1;
    842             endpoint_p->is_remote = 0;
    843             endpoint_p->local_tx_enabled = 1;
    844             endpoint_p->local_tx_index = lmep_index;
    845             endpoint_p->name = soc_LMEPm_field32_get(unit, &lmep_entry,
    846                                                      MEPIDf);
    847             endpoint_p->level = soc_LMEPm_field32_get(unit, &lmep_entry,
    848                 MDLf);
    849             endpoint_p->group_index = group_index;
    850 
    851             SHR_BITSET(oam_info_p->local_tx_endpoints_in_use, lmep_index);
    852         }
    853     }
    854 
    855     if (scache_version >= BCM_WB_VERSION_1_1) {
    856         oam_scache += (oam_info_p->endpoint_count * sizeof(bcm_oam_endpoint_t));
    857     }
    858 
    859     if (!SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit) && (stable_size > 0)) {
    860         /* In BCM_WB_VERSION_1_1 onwards we allocate memory for storing EP
    861          * indexes
    862          */
    863         if (scache_version < BCM_WB_VERSION_1_1) {
    864             realloc_size += (oam_info_p->endpoint_count *
    865                                               sizeof(bcm_oam_endpoint_t));
    866         }
    867 
    868         SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_OAM, 0);
    869         rv = soc_scache_realloc(unit, scache_handle, realloc_size);
    870         if (SOC_FAILURE(rv)) {
    871             LOG_ERROR(BSL_LS_BCM_OAM,
    872                     (BSL_META_U(unit,"OAM Error: scache alloc failed  - %s.\n"),
    873                      bcm_errmsg(rv)));
    874             return rv;
    875         }
    876     }
    877 
    878     return BCM_E_NONE;
    879 }
    880 
    881 static int _bcm_en_oam_field_group_process(int unit, bcm_field_group_t group,
    882                                            void *user_data)
    883 {
    884     _bcm_oam_info_t *oam_info_p;
    885     _bcm_oam_endpoint_t *endpoint_p;
    886     bcm_field_qset_t group_qset;
    887     int glp, local_id, i, j, q, match, entry_size, entry_count, rv = BCM_E_NONE;
    888     bcm_field_entry_t *entry_arr = NULL;
    889     uint32 param0, param1;
    890     bcm_gport_t gport_id;
    891     bcm_module_t module_id, mod_mask;
    892     bcm_port_t port_id, port_mask;
    893     bcm_trunk_t trunk_id;
    894 
    895     SET_OAM_INFO;
    896 
    897     /* Get this group's QSET */
    898     BCM_IF_ERROR_RETURN(bcm_esw_field_group_get(unit, group, &group_qset));
    899 
    900     /* Check for the VFP QSET for a match */
    901     match = 1;
    902     _FIELD_QSET_ITER(oam_info_p->vfp_qs, q) {
    903         if (!BCM_FIELD_QSET_TEST(group_qset, bcmFieldQualifyStageLookup) ||
    904             !BCM_FIELD_QSET_TEST(group_qset, q)) {
    905             match = 0;
    906             break;
    907         }
    908     }
    909     if (match && (oam_info_p->vfp_group == -1)) {
    910         /* Get number of entries */
    911         rv = bcm_esw_field_entry_multi_get(unit, group, 0, NULL, &entry_count);
    912         if (BCM_FAILURE(rv)) {
    913             goto cleanup;
    914         }
    915         /* Get the actual entries - each entry belongs to an endpoint */
    916         entry_size = entry_count;
    917         entry_arr = sal_alloc(entry_size * sizeof(bcm_field_entry_t), 
    918                               "Entry array");
    919         if (entry_arr == NULL) {
    920             rv = BCM_E_MEMORY;
    921             goto cleanup;
    922         } 
    923         rv = bcm_esw_field_entry_multi_get(unit, group, entry_size, entry_arr, 
    924                                            &entry_count);
    925         if (BCM_FAILURE(rv)) {
    926             goto cleanup;
    927         }
    928         for (i = 0; i < entry_count; i++) {
    929             /* Check for bcmFieldActionIncomingMplsPortSet to find endpoint */
    930             rv = bcm_esw_field_action_get(unit, entry_arr[i], 
    931                                           bcmFieldActionIncomingMplsPortSet, 
    932                                           &param0, &param1);
    933             if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) {
    934                 goto cleanup;
    935             }
    936             if (BCM_SUCCESS(rv)) {
    937                 /* Find endpoint that matches this VP */
    938                 for (j = 0; j < oam_info_p->endpoint_count; j++) {
    939                     endpoint_p = oam_info_p->endpoints + j;
    940                     if (!endpoint_p->in_use) {
    941                         continue;
    942                     }
    943                     if (endpoint_p->vp == param0) {
    944                         endpoint_p->vfp_entry = entry_arr[i];
    945                         if (oam_info_p->vfp_group == -1) {
    946                             oam_info_p->vfp_group = group;
    947                             oam_info_p->vfp_entry_count = entry_count;
    948                         }
    949                         break;
    950                     }
    951                 }
    952             }
    953             if (rv == BCM_E_NOT_FOUND) {
    954                 /* The FP entry was not for an OAM endpoint */
    955                 rv = BCM_E_NONE;
    956             }
    957         }
    958         sal_free(entry_arr);
    959         entry_arr = NULL;
    960     }
    961 
    962     /* Check for the IFP VP QSET for a match */
    963     match = 1;
    964     _FIELD_QSET_ITER(oam_info_p->fp_vp_qs, q) {
    965         if (!BCM_FIELD_QSET_TEST(group_qset, bcmFieldQualifyStageIngress) ||
    966             !BCM_FIELD_QSET_TEST(group_qset, q)) {
    967             match = 0;
    968             break;
    969         }
    970     }
    971     if (match && (oam_info_p->fp_vp_group == -1)) {
    972         /* Get number of entries */
    973         rv = bcm_esw_field_entry_multi_get(unit, group, 0, NULL, &entry_count);
    974         if (BCM_FAILURE(rv)) {
    975             goto cleanup;
    976         }
    977         /* Get the actual entries - each entry belongs to an endpoint */
    978         entry_size = entry_count;
    979         entry_arr = sal_alloc(entry_size * sizeof(bcm_field_entry_t), 
    980                               "Entry array");
    981         if (entry_arr == NULL) {
    982             rv = BCM_E_MEMORY;
    983             goto cleanup;
    984         } 
    985         rv = bcm_esw_field_entry_multi_get(unit, group, entry_size, entry_arr, 
    986                                            &entry_count);
    987         if (BCM_FAILURE(rv)) {
    988             goto cleanup;
    989         }
    990         for (i = 0; i < entry_count; i++) {
    991             /* Check for SrcMimGport to find endpoint */
    992             rv = bcm_esw_field_qualify_SrcMimGport_get(unit, entry_arr[i], 
    993                                                        &gport_id);
    994             if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) {
    995                 goto cleanup;
    996             }
    997             if (BCM_SUCCESS(rv)) {
    998                 /* Find endpoint that matches this VP with possible actions */
    999                 for (j = 0; j < oam_info_p->endpoint_count; j++) {
   1000                     endpoint_p = oam_info_p->endpoints + j;
   1001                     if (!endpoint_p->in_use) {
   1002                         continue;
   1003                     }
   1004                     if (endpoint_p->vp == BCM_GPORT_MIM_PORT_ID_GET(gport_id)) {
   1005                         if (oam_info_p->fp_vp_group == -1) {
   1006                             oam_info_p->fp_vp_group = group;
   1007                             oam_info_p->fp_vp_entry_count = entry_count;
   1008                         }
   1009                         endpoint_p->fp_entry_tx = entry_arr[i];
   1010                         rv = bcm_esw_field_action_get(unit, entry_arr[i], 
   1011                                                      bcmFieldActionOamLmBasePtr, 
   1012                                                      &param0, &param1);
   1013                         if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) {
   1014                             goto cleanup;
   1015                         } 
   1016                         if (rv != BCM_E_NOT_FOUND) { 
   1017                             endpoint_p->lm_counter_index = param0;
   1018                             SHR_BITSET(oam_info_p->lm_counter_in_use, 
   1019                                 endpoint_p->lm_counter_index);
   1020                         }
   1021                         rv = bcm_esw_field_action_get(unit, entry_arr[i], 
   1022                                           bcmFieldActionOamServicePriMappingPtr,
   1023                                           &param0, &param1);
   1024                         if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) {
   1025                             goto cleanup;
   1026                         } 
   1027                         if (rv != BCM_E_NOT_FOUND) {
   1028                             endpoint_p->pri_map_index = param0;
   1029                             endpoint_p->flags |= BCM_OAM_ENDPOINT_LOSS_MEASUREMENT;
   1030                         }
   1031                         rv = bcm_esw_field_action_get(unit, entry_arr[i],
   1032                                           bcmFieldActionOamDmEnable,
   1033                                           &param0, &param1);
   1034                         if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) {
   1035                             goto cleanup;
   1036                         } 
   1037                         if (rv != BCM_E_NOT_FOUND) {
   1038                             if (param0 != 0) {
   1039                                 endpoint_p->flags |= BCM_OAM_ENDPOINT_DELAY_MEASUREMENT;
   1040                             }
   1041                         }
   1042                         rv = bcm_esw_field_action_get(unit, entry_arr[i],
   1043                                           bcmFieldActionOamUpMep,
   1044                                           &param0, &param1);
   1045                         if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) {
   1046                             goto cleanup;
   1047                         } 
   1048                         if (rv != BCM_E_NOT_FOUND) {
   1049                             if (param0 != 0) {
   1050                                 endpoint_p->flags |= BCM_OAM_ENDPOINT_UP_FACING;
   1051                             }
   1052                         }
   1053                         break;
   1054                     }
   1055                 }
   1056             } 
   1057             /* Check for DstMimGport to find endpoint */
   1058             rv = bcm_esw_field_qualify_DstMimGport_get(unit, entry_arr[i], 
   1059                                                        &gport_id);
   1060             if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) {
   1061                 goto cleanup;
   1062             }
   1063             if (BCM_SUCCESS(rv)) {
   1064                 /* Find endpoint that matches this VP */
   1065                 for (j = 0; j < oam_info_p->endpoint_count; j++) {
   1066                     endpoint_p = oam_info_p->endpoints + j;
   1067                     if (!endpoint_p->in_use) {
   1068                         continue;
   1069                     }
   1070                     if (endpoint_p->vp == BCM_GPORT_MIM_PORT_ID_GET(gport_id)) {
   1071                         if (oam_info_p->fp_vp_group == -1) {
   1072                             oam_info_p->fp_vp_group = group;
   1073                             oam_info_p->fp_vp_entry_count = entry_count;
   1074                         }
   1075                         endpoint_p->fp_entry_rx = entry_arr[i];
   1076                         rv = bcm_esw_field_action_get(unit, entry_arr[i], 
   1077                                                      bcmFieldActionOamLmBasePtr, 
   1078                                                      &param0, &param1);
   1079                         if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) {
   1080                             goto cleanup;
   1081                         } 
   1082                         if (rv != BCM_E_NOT_FOUND) { 
   1083                             endpoint_p->lm_counter_index = param0;
   1084                             SHR_BITSET(oam_info_p->lm_counter_in_use, 
   1085                                 endpoint_p->lm_counter_index);
   1086                         }
   1087                         rv = bcm_esw_field_action_get(unit, entry_arr[i], 
   1088                                           bcmFieldActionOamServicePriMappingPtr,
   1089                                           &param0, &param1);
   1090                         if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) {
   1091                             goto cleanup;
   1092                         } 
   1093                         if (rv != BCM_E_NOT_FOUND) {
   1094                             endpoint_p->pri_map_index = param0;
   1095                         }
   1096                         break;
   1097                     }
   1098                 }
   1099             }
   1100             if (rv == BCM_E_NOT_FOUND) {
   1101                 /* The FP entry was not for an OAM endpoint */
   1102                 rv = BCM_E_NONE;
   1103             }
   1104         }
   1105         sal_free(entry_arr);
   1106         entry_arr = NULL;
   1107     }
   1108 
   1109     /* Check for the IFP GLP QSET for a match */
   1110     match = 1;
   1111     _FIELD_QSET_ITER(oam_info_p->fp_glp_qs, q) {
   1112         if (!BCM_FIELD_QSET_TEST(group_qset, bcmFieldQualifyStageIngress) ||
   1113             !BCM_FIELD_QSET_TEST(group_qset, q)) {
   1114             match = 0;
   1115             break;
   1116         }
   1117     }
   1118     if (match && (oam_info_p->fp_glp_group == -1)) {
   1119         /* Get number of entries */
   1120         rv = bcm_esw_field_entry_multi_get(unit, group, 0, NULL, &entry_count);
   1121         if (BCM_FAILURE(rv)) {
   1122             goto cleanup;
   1123         }
   1124         /* Get the actual entries - each entry belongs to an endpoint */
   1125         entry_size = entry_count;
   1126         entry_arr = sal_alloc(entry_size * sizeof(bcm_field_entry_t), 
   1127                               "Entry array");
   1128         if (entry_arr == NULL) {
   1129             rv = BCM_E_MEMORY;
   1130             goto cleanup;
   1131         } 
   1132         rv = bcm_esw_field_entry_multi_get(unit, group, entry_size, entry_arr, 
   1133                                            &entry_count);
   1134         if (BCM_FAILURE(rv)) {
   1135             goto cleanup;
   1136         }
   1137         for (i = 0; i < entry_count; i++) {
   1138             /* Check for SrcPort to find endpoint */
   1139             rv = bcm_esw_field_qualify_SrcPort_get(unit, entry_arr[i], 
   1140                                                    &module_id, &mod_mask,
   1141                                                    &port_id, &port_mask);
   1142             if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) {
   1143                 goto cleanup;
   1144             }
   1145             if (BCM_SUCCESS(rv)) {
   1146                 if (BCM_GPORT_IS_SET(port_id)) {
   1147                     rv = _bcm_esw_gport_resolve(unit, port_id,
   1148                         &module_id, &port_id, &trunk_id, &local_id);
   1149                     if (BCM_FAILURE(rv)) {
   1150                         goto cleanup;
   1151                     }
   1152                 }
   1153                 glp = (module_id << SOC_MODID_BIT_POS(unit)) | port_id;
   1154                 /* Find endpoint that matches this GLP with possible actions */
   1155                 for (j = 0; j < oam_info_p->endpoint_count; j++) {
   1156                     endpoint_p = oam_info_p->endpoints + j;
   1157                     if (!endpoint_p->in_use) {
   1158                         continue;
   1159                     }
   1160                     if (endpoint_p->glp == glp) {
   1161                         if (oam_info_p->fp_glp_group == -1) {
   1162                             oam_info_p->fp_glp_group = group;
   1163                             oam_info_p->fp_glp_entry_count = entry_count;
   1164                         }
   1165                         endpoint_p->fp_entry_tx = entry_arr[i];
   1166                         rv = bcm_esw_field_action_get(unit, entry_arr[i], 
   1167                                                      bcmFieldActionOamLmBasePtr, 
   1168                                                      &param0, &param1);
   1169                         if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) {
   1170                             goto cleanup;
   1171                         }
   1172                         if (rv != BCM_E_NOT_FOUND) { 
   1173                             endpoint_p->lm_counter_index = param0;
   1174                             SHR_BITSET(oam_info_p->lm_counter_in_use, 
   1175                                 endpoint_p->lm_counter_index);
   1176                         }
   1177                         rv = bcm_esw_field_action_get(unit, entry_arr[i], 
   1178                                           bcmFieldActionOamServicePriMappingPtr,
   1179                                           &param0, &param1);
   1180                         if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) {
   1181                             goto cleanup;
   1182                         } 
   1183                         if (rv != BCM_E_NOT_FOUND) {
   1184                             endpoint_p->pri_map_index = param0;
   1185                             endpoint_p->flags |= BCM_OAM_ENDPOINT_LOSS_MEASUREMENT;
   1186                         }
   1187                         rv = bcm_esw_field_action_get(unit, entry_arr[i],
   1188                                           bcmFieldActionOamDmEnable,
   1189                                           &param0, &param1);
   1190                         if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) {
   1191                             goto cleanup;
   1192                         } 
   1193                         if (rv != BCM_E_NOT_FOUND) {
   1194                             if (param0 != 0) {
   1195                                 endpoint_p->flags |= BCM_OAM_ENDPOINT_DELAY_MEASUREMENT;
   1196                             }
   1197                         }
   1198                         rv = bcm_esw_field_action_get(unit, entry_arr[i],
   1199                                           bcmFieldActionOamUpMep,
   1200                                           &param0, &param1);
   1201                         if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) {
   1202                             goto cleanup;
   1203                         } 
   1204                         if (rv != BCM_E_NOT_FOUND) {
   1205                             if (param0 != 0) {
   1206                                 endpoint_p->flags |= BCM_OAM_ENDPOINT_UP_FACING;
   1207                             }
   1208                         }
   1209                         break;
   1210                     }
   1211                 }
   1212             } 
   1213             /* Check for DstPort to find endpoint */
   1214             rv = bcm_esw_field_qualify_DstPort_get(unit, entry_arr[i], 
   1215                                                    &module_id, &mod_mask,
   1216                                                    &port_id, &port_mask);
   1217             if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) {
   1218                 goto cleanup;
   1219             }
   1220             if (BCM_SUCCESS(rv)) {
   1221                 if (BCM_GPORT_IS_SET(port_id)) {
   1222                     rv = _bcm_esw_gport_resolve(unit, port_id,
   1223                         &module_id, &port_id, &trunk_id, &local_id);
   1224                     if (BCM_FAILURE(rv)) {
   1225                         goto cleanup;
   1226                     }
   1227                 }
   1228                 glp = (module_id << SOC_MODID_BIT_POS(unit)) | port_id;
   1229                 /* Find endpoint that matches this GLP */
   1230                 for (j = 0; j < oam_info_p->endpoint_count; j++) {
   1231                     endpoint_p = oam_info_p->endpoints + j;
   1232                     if (!endpoint_p->in_use) {
   1233                         continue;
   1234                     }
   1235                     if (endpoint_p->glp == glp) {
   1236                         if (oam_info_p->fp_glp_group == -1) {
   1237                             oam_info_p->fp_glp_group = group;
   1238                             oam_info_p->fp_glp_entry_count = entry_count;
   1239                         }
   1240                         endpoint_p->fp_entry_rx = entry_arr[i];
   1241                         rv = bcm_esw_field_action_get(unit, entry_arr[i], 
   1242                                                      bcmFieldActionOamLmBasePtr, 
   1243                                                      &param0, &param1);
   1244                         if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) {
   1245                             goto cleanup;
   1246                         } 
   1247                         if (rv != BCM_E_NOT_FOUND) { 
   1248                             endpoint_p->lm_counter_index = param0;
   1249                             SHR_BITSET(oam_info_p->lm_counter_in_use, 
   1250                                 endpoint_p->lm_counter_index);
   1251                         }
   1252                         rv = bcm_esw_field_action_get(unit, entry_arr[i], 
   1253                                           bcmFieldActionOamServicePriMappingPtr,
   1254                                           &param0, &param1);
   1255                         if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) {
   1256                             goto cleanup;
   1257                         } 
   1258                         if (rv != BCM_E_NOT_FOUND) {
   1259                             endpoint_p->pri_map_index = param0;
   1260                         }
   1261                         break;
   1262                     }
   1263                 }
   1264             }
   1265             if (rv == BCM_E_NOT_FOUND) {
   1266                 /* The FP entry was not for an OAM endpoint */
   1267                 rv = BCM_E_NONE;
   1268             }
   1269         }
   1270         sal_free(entry_arr);
   1271         entry_arr = NULL;
   1272     }
   1273 
   1274 cleanup:
   1275     if (entry_arr != NULL) {
   1276         sal_free(entry_arr);
   1277     }
   1278     return rv;
   1279 }
   1280 #endif /* BCM_WARM_BOOT_SUPPORT */
   1281 
   1282 static void _bcm_en_oam_uninstall_vfp(int unit, _bcm_oam_endpoint_t *endpoint_p)
   1283 {
   1284 	_bcm_oam_info_t *oam_info_p;
   1285 
   1286 	SET_OAM_INFO;
   1287 
   1288 	if (endpoint_p->vfp_entry != 0) {
   1289         (void)bcm_esw_field_entry_destroy(unit, endpoint_p->vfp_entry);
   1290         oam_info_p->vfp_entry_count--;
   1291         if (oam_info_p->vfp_entry_count == 0) {
   1292             (void)bcm_esw_field_group_destroy(unit, oam_info_p->vfp_group);
   1293             oam_info_p->vfp_group = 0;
   1294         }
   1295         endpoint_p->vfp_entry = 0;
   1296     }
   1297 }
   1298 
   1299 static void _bcm_en_oam_uninstall_fp(int unit,  _bcm_oam_endpoint_t *endpoint_p)
   1300 {
   1301     int i;
   1302     _bcm_oam_info_t *oam_info_p;
   1303 
   1304     SET_OAM_INFO;
   1305 
   1306     if (endpoint_p->fp_entry_tx != 0) {
   1307     	(void)bcm_esw_field_entry_destroy(unit, endpoint_p->fp_entry_tx);
   1308     }
   1309     if (endpoint_p->fp_entry_rx != 0) {
   1310         (void)bcm_esw_field_entry_destroy(unit, endpoint_p->fp_entry_rx);
   1311     }
   1312     if (endpoint_p->vp != 0) {
   1313         if (endpoint_p->fp_entry_tx != 0) {
   1314             oam_info_p->fp_vp_entry_count--;
   1315 
   1316             if (oam_info_p->fp_vp_entry_count == 0) {
   1317                (void)bcm_esw_field_group_destroy(unit, oam_info_p->fp_vp_group);
   1318                 oam_info_p->fp_vp_group = 0;
   1319             }
   1320         }
   1321         endpoint_p->vp = 0;  
   1322     } else {
   1323         for (i = 0; i < BCM_SWITCH_TRUNK_MAX_PORTCNT; i++) {
   1324             if (endpoint_p->fp_entry_trunk[i]) {
   1325                 (void)bcm_esw_field_entry_destroy(unit, endpoint_p->fp_entry_trunk[i]);
   1326                 endpoint_p->fp_entry_trunk[i] = 0;
   1327             }
   1328         }
   1329         if ((endpoint_p->fp_entry_tx != 0) || (endpoint_p->fp_entry_rx != 0)) {
   1330             oam_info_p->fp_glp_entry_count--;
   1331 
   1332             if (oam_info_p->fp_glp_entry_count == 0) {
   1333                 (void)bcm_esw_field_group_destroy(unit, oam_info_p->fp_glp_group);
   1334                 oam_info_p->fp_glp_group = 0;
   1335             }
   1336         }
   1337     }
   1338 
   1339     endpoint_p->fp_entry_tx = 0;
   1340     endpoint_p->fp_entry_rx = 0;
   1341 }
   1342 
   1343 static int _bcm_en_oam_install_vfp(int unit, int endpoint_index, 
   1344     bcm_oam_endpoint_info_t *endpoint_info)
   1345 {
   1346     _bcm_oam_info_t *oam_info_p;
   1347     _bcm_oam_endpoint_t *endpoint_p;
   1348     bcm_gport_t port_id;
   1349     bcm_mac_t mac_ones = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
   1350     
   1351     SET_OAM_INFO;
   1352     SET_ENDPOINT(endpoint_index);
   1353     
   1354     if (oam_info_p->vfp_group == 0) {
   1355         /* Create group first */
   1356         BCM_IF_ERROR_RETURN(bcm_esw_field_group_create(unit,
   1357                                  oam_info_p->vfp_qs,
   1358                                  BCM_FIELD_GROUP_PRIO_ANY,
   1359                                  &oam_info_p->vfp_group));
   1360     }
   1361     BCM_IF_ERROR_RETURN    
   1362         (bcm_esw_field_entry_create(unit,
   1363                                     oam_info_p->vfp_group,
   1364                                     &endpoint_p->vfp_entry));
   1365 
   1366     BCM_IF_ERROR_RETURN
   1367         (bcm_esw_field_qualify_DstMac(unit, endpoint_p->vfp_entry,
   1368                                       endpoint_info->src_mac_address, mac_ones));
   1369         
   1370     BCM_IF_ERROR_RETURN
   1371         (bcm_esw_field_qualify_SrcMac(unit, endpoint_p->vfp_entry,
   1372                                       endpoint_info->dst_mac_address, mac_ones));
   1373                              
   1374     BCM_IF_ERROR_RETURN
   1375         (bcm_esw_field_qualify_OuterVlanId(unit, endpoint_p->vfp_entry,
   1376                                            endpoint_info->vlan, 0x0fff));
   1377 
   1378     BCM_GPORT_MPLS_PORT_ID_SET(port_id, endpoint_p->vp);
   1379 
   1380     BCM_IF_ERROR_RETURN
   1381       (bcm_esw_field_action_add(unit, endpoint_p->vfp_entry,
   1382 				bcmFieldActionIncomingMplsPortSet,
   1383 				port_id, 0));
   1384   
   1385     BCM_IF_ERROR_RETURN
   1386         (bcm_esw_field_action_add(unit, endpoint_p->vfp_entry,
   1387                                   bcmFieldActionOamPbbteLookupEnable,
   1388                                   1, 0));
   1389     oam_info_p->vfp_entry_count++;
   1390 
   1391 #ifdef BCM_WARM_BOOT_SUPPORT
   1392     SOC_CONTROL_LOCK(unit);
   1393     SOC_CONTROL(unit)->scache_dirty = 1;
   1394     SOC_CONTROL_UNLOCK(unit);
   1395 #endif
   1396     
   1397     return BCM_E_NONE;
   1398 }
   1399 
   1400 /*
   1401  * Function:
   1402  *      _bcm_en_oam_trunk_install_fp
   1403  * Purpose:
   1404  *      Install fp entries for each port in the trunk for LM/DM higig packets sent 
   1405  *      from CPU to hit and perform OAM operations. This is necessary because
   1406  *      there is no trunk information in higig header.
   1407  * Parameters:
   1408  *      unit - (IN) Unit number.
   1409  *      add_mdl - (IN) Whether to install mdl as key.
   1410  *      endpoint_info - (IN) Pointer to an OAM endpoint structure
   1411  * Returns:
   1412  *      BCM_E_XXX
   1413  * Notes:
   1414  */
   1415 static
   1416 int _bcm_en_oam_trunk_install_fp(int unit, int add_mdl, _bcm_oam_endpoint_t *endpoint_p)
   1417 {
   1418     int rv = BCM_E_NONE;
   1419     _bcm_oam_info_t *oam_info_p;
   1420     bcm_field_group_t group;
   1421     bcm_gport_t gport;
   1422     bcm_ip6_t data, mask;
   1423     int i, j;
   1424     int member_count;
   1425     bcm_trunk_member_t *member_array = NULL;
   1426 
   1427     SET_OAM_INFO;
   1428 
   1429     group = oam_info_p->fp_glp_group;
   1430 
   1431     BCM_IF_ERROR_RETURN
   1432         (bcm_esw_trunk_get(unit, endpoint_p->glp & 0x7F, NULL,
   1433                            0, NULL, &member_count));
   1434 
   1435     if (member_count > 0) {
   1436         member_array = sal_alloc(sizeof(bcm_trunk_member_t) * member_count,
   1437                 "trunk member array");
   1438         if (NULL == member_array) {
   1439             return BCM_E_MEMORY;
   1440         }
   1441         rv = bcm_esw_trunk_get(unit, endpoint_p->glp & 0x7F, NULL,
   1442                 member_count, member_array, &member_count);
   1443         if (BCM_FAILURE(rv)) {
   1444             sal_free(member_array);
   1445             return rv;
   1446         }
   1447     }
   1448 
   1449     for (i = 0; i < member_count; i++) {
   1450 
   1451         rv = bcm_esw_field_entry_create(unit, group,
   1452                 &endpoint_p->fp_entry_trunk[i]);
   1453         if (BCM_FAILURE(rv)) {
   1454             sal_free(member_array);
   1455             return rv;
   1456         }
   1457 
   1458         gport = member_array[i].gport;
   1459 
   1460         if (endpoint_p->flags & BCM_OAM_ENDPOINT_UP_FACING) {
   1461             rv = bcm_esw_field_qualify_SrcPort(unit, endpoint_p->fp_entry_trunk[i],
   1462                     0, 0x3f, gport, BCM_FIELD_EXACT_MATCH_MASK);
   1463         } else {
   1464             rv = bcm_esw_field_qualify_DstPort(unit, endpoint_p->fp_entry_trunk[i],
   1465                     0, 0x3f, gport, BCM_FIELD_EXACT_MATCH_MASK);
   1466         }
   1467         if (BCM_FAILURE(rv)) {
   1468             sal_free(member_array);
   1469             return rv;
   1470         }
   1471 
   1472         rv = bcm_esw_field_qualify_OuterVlanId(unit, endpoint_p->fp_entry_trunk[i],
   1473                 endpoint_p->vlan, 0xfff);
   1474         if (BCM_FAILURE(rv)) {
   1475             sal_free(member_array);
   1476             return rv;
   1477         }
   1478 
   1479         if ((add_mdl != 0) && (endpoint_p->vp == 0))
   1480         {
   1481             /*
   1482              * Add ethertype and MDL(with DstIp6) for smaller MDL on the same
   1483              * (Port, VLAN) to trap LM packets to CPU.
   1484              */
   1485             for (j = 0; j < 16; j++) {
   1486                 data[j] = mask[j] = 0;
   1487             }
   1488             data[0] = (endpoint_p->level << 5);
   1489             mask[0] = 0xE0;
   1490 
   1491             rv = bcm_esw_field_qualify_DstIp6(unit, endpoint_p->fp_entry_trunk[i],
   1492                     data, mask);
   1493             if (BCM_FAILURE(rv)) {
   1494                 sal_free(member_array);
   1495                 return rv;
   1496             }
   1497 
   1498             rv = bcm_esw_field_qualify_EtherType(unit, endpoint_p->fp_entry_trunk[i],
   1499                     0x8902, 0xffff);
   1500             if (BCM_FAILURE(rv)) {
   1501                 sal_free(member_array);
   1502                 return rv;
   1503             }
   1504         }
   1505 
   1506         rv = bcm_esw_field_action_add(unit, endpoint_p->fp_entry_trunk[i],
   1507                 bcmFieldActionOamLmepEnable,
   1508                 1, 0);
   1509         if (BCM_FAILURE(rv)) {
   1510             sal_free(member_array);
   1511             return rv;
   1512         }
   1513 
   1514         rv = bcm_esw_field_action_add(unit, endpoint_p->fp_entry_trunk[i],
   1515                 bcmFieldActionOamLmEnable,
   1516                 endpoint_p->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT? 1:0, 0);
   1517         if (BCM_FAILURE(rv)) {
   1518             sal_free(member_array);
   1519             return rv;
   1520         }
   1521 
   1522         rv = bcm_esw_field_action_add(unit, endpoint_p->fp_entry_trunk[i],
   1523                 bcmFieldActionOamDmEnable,
   1524                 endpoint_p->flags & BCM_OAM_ENDPOINT_DELAY_MEASUREMENT? 1:0, 0);
   1525         if (BCM_FAILURE(rv)) {
   1526             sal_free(member_array);
   1527             return rv;
   1528         }
   1529 
   1530         rv = bcm_esw_field_action_add(unit, endpoint_p->fp_entry_trunk[i],
   1531                 bcmFieldActionOamLmepMdl,
   1532                 endpoint_p->level, 0);
   1533         if (BCM_FAILURE(rv)) {
   1534             sal_free(member_array);
   1535             return rv;
   1536         }
   1537 
   1538         rv = bcm_esw_field_action_add(unit, endpoint_p->fp_entry_trunk[i],
   1539                 bcmFieldActionOamUpMep,
   1540                 endpoint_p->flags & BCM_OAM_ENDPOINT_UP_FACING? 1:0, 0);
   1541         if (BCM_FAILURE(rv)) {
   1542             sal_free(member_array);
   1543             return rv;
   1544         }
   1545 
   1546         if (endpoint_p->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT)
   1547         {
   1548             /* Assign LM counter and priority mapping table */
   1549             rv = bcm_esw_field_action_add(unit, endpoint_p->fp_entry_trunk[i],
   1550                     bcmFieldActionOamLmBasePtr,
   1551                     endpoint_p->lm_counter_index, 0);
   1552             if (BCM_FAILURE(rv)) {
   1553                 sal_free(member_array);
   1554                 return rv;
   1555             }
   1556 
   1557             rv = bcm_esw_field_action_add(unit, endpoint_p->fp_entry_trunk[i],
   1558                     bcmFieldActionOamServicePriMappingPtr,
   1559                     endpoint_p->pri_map_index, 0);
   1560             if (BCM_FAILURE(rv)) {
   1561                 sal_free(member_array);
   1562                 return rv;
   1563             }
   1564         }
   1565 
   1566         rv = bcm_esw_field_action_add(unit, endpoint_p->fp_entry_trunk[i],
   1567                 bcmFieldActionOamTx, 1, 0);
   1568         if (BCM_FAILURE(rv)) {
   1569             sal_free(member_array);
   1570             return rv;
   1571         }
   1572     }
   1573 
   1574     if (NULL != member_array) {
   1575         sal_free(member_array);
   1576     }
   1577     return rv;
   1578 }
   1579 
   1580 static
   1581 int _bcm_en_oam_install_fp(int unit, int add_mdl, _bcm_oam_endpoint_t *endpoint_p)
   1582 {
   1583     _bcm_oam_info_t *oam_info_p;
   1584     bcm_field_group_t group;
   1585     bcm_gport_t gport;
   1586     bcm_ip6_t data, mask;
   1587     bcm_module_t module_id;
   1588     bcm_port_t port_id;
   1589     int i, mep_on_trunk = 0, skip_entry_rx = 0;
   1590 
   1591     SET_OAM_INFO;
   1592 
   1593     if ((endpoint_p->vp != 0) && (oam_info_p->fp_vp_group == 0)) {
   1594         /* Create group first */
   1595         BCM_IF_ERROR_RETURN(bcm_esw_field_group_create(unit,
   1596                                  oam_info_p->fp_vp_qs,
   1597                                  BCM_FIELD_GROUP_PRIO_ANY,
   1598                                  &oam_info_p->fp_vp_group));
   1599     }
   1600     
   1601     if ((endpoint_p->vp == 0) && (oam_info_p->fp_glp_group == 0)) {
   1602         /* Create group first */
   1603         BCM_IF_ERROR_RETURN(bcm_esw_field_group_create(unit,
   1604                                  oam_info_p->fp_glp_qs,
   1605                                  BCM_FIELD_GROUP_PRIO_ANY,
   1606                                  &oam_info_p->fp_glp_group));
   1607     }
   1608 
   1609     if (endpoint_p->vp) {
   1610         group = oam_info_p->fp_vp_group;
   1611     } else {
   1612         group = oam_info_p->fp_glp_group;
   1613     }
   1614 
   1615     if (endpoint_p->glp & (1 << SOC_TRUNK_BIT_POS(unit))) {
   1616         mep_on_trunk = 1;
   1617     }
   1618 
   1619     if ((mep_on_trunk != 0) &&
   1620         (endpoint_p->flags & BCM_OAM_ENDPOINT_DELAY_MEASUREMENT) &&
   1621         !(endpoint_p->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT) && 
   1622         !(endpoint_p->flags & BCM_OAM_ENDPOINT_UP_FACING)) {
   1623         /* 
   1624          * Skip the entry to match DM packets sent from CPU for down meps that are 
   1625          * created on trunk and only support delay measurement. Create entry for
   1626          * each port in the trunk instead. This is only applied to DM down meps.
   1627          * The entry is always required for LM MEP to record packet counts.
   1628          */
   1629         skip_entry_rx = 1;
   1630     }
   1631 
   1632     BCM_IF_ERROR_RETURN
   1633         (bcm_esw_field_entry_create(unit,
   1634                                     group,
   1635                                     &endpoint_p->fp_entry_tx));
   1636 
   1637     if (0 == skip_entry_rx) {
   1638         BCM_IF_ERROR_RETURN
   1639             (bcm_esw_field_entry_create(unit,
   1640                                         group,
   1641                                         &endpoint_p->fp_entry_rx));
   1642     }
   1643 
   1644     if (endpoint_p->vp != 0) {
   1645     	BCM_GPORT_MIM_PORT_ID_SET(gport, endpoint_p->vp);
   1646 
   1647     	BCM_IF_ERROR_RETURN
   1648     	    (bcm_esw_field_qualify_SrcMimGport(unit, endpoint_p->fp_entry_tx,
   1649                                                gport));
   1650         BCM_IF_ERROR_RETURN
   1651             (bcm_esw_field_qualify_DstMimGport(unit, endpoint_p->fp_entry_rx,
   1652                                                gport));
   1653     } else {
   1654         if (mep_on_trunk != 0) {
   1655             /* Trunk */
   1656             BCM_GPORT_TRUNK_SET(gport, endpoint_p->glp & 0x7F);
   1657             BCM_IF_ERROR_RETURN
   1658                 (bcm_esw_field_qualify_SrcTrunk(unit, endpoint_p->fp_entry_tx,
   1659                 gport, BCM_FIELD_EXACT_MATCH_MASK));
   1660 
   1661             if (!skip_entry_rx) {
   1662                 BCM_IF_ERROR_RETURN
   1663                 (bcm_esw_field_qualify_DstTrunk(unit, endpoint_p->fp_entry_rx,
   1664                     gport, BCM_FIELD_EXACT_MATCH_MASK));
   1665             }
   1666         } else {
   1667             module_id = (endpoint_p->glp & SOC_MODID_MASK(unit)) >> SOC_MODID_BIT_POS(unit);
   1668             port_id = (endpoint_p->glp & SOC_PORT_ADDR_MAX(unit));
   1669 
   1670             if (module_id != 0) {
   1671                 /* Modport */
   1672                 BCM_GPORT_MODPORT_SET(gport, module_id, port_id);
   1673             } else {
   1674                 /* Local port */
   1675                 BCM_IF_ERROR_RETURN(bcm_esw_port_gport_get(unit, port_id, &gport));
   1676             }
   1677             BCM_IF_ERROR_RETURN
   1678                 (bcm_esw_field_qualify_SrcPort(unit, endpoint_p->fp_entry_tx,
   1679                     0, 0x3f, gport, BCM_FIELD_EXACT_MATCH_MASK));
   1680             BCM_IF_ERROR_RETURN
   1681                 (bcm_esw_field_qualify_DstPort(unit, endpoint_p->fp_entry_rx,
   1682                     0, 0x3f, gport, BCM_FIELD_EXACT_MATCH_MASK));
   1683         }
   1684 
   1685         BCM_IF_ERROR_RETURN
   1686             (bcm_esw_field_qualify_OuterVlanId(unit, endpoint_p->fp_entry_tx,
   1687                                                endpoint_p->vlan, 0xfff));
   1688 
   1689         if (0 == skip_entry_rx) {
   1690             BCM_IF_ERROR_RETURN
   1691             (bcm_esw_field_qualify_OuterVlanId(unit, endpoint_p->fp_entry_rx,
   1692                                                endpoint_p->vlan, 0xfff));
   1693         }
   1694     }
   1695 
   1696     if ((add_mdl != 0) && (endpoint_p->vp == 0))
   1697     {
   1698         /*
   1699          * Add ethertype and MDL(with DstIp6) for smaller MDL on the same
   1700          * (Port, VLAN) to trap LM packets to CPU.
   1701          */
   1702         for (i = 0; i < 16; i++) {
   1703             data[i] = mask[i] = 0;
   1704         }
   1705         data[0] = (endpoint_p->level << 5);
   1706         mask[0] = 0xE0;
   1707 
   1708         BCM_IF_ERROR_RETURN
   1709             (bcm_esw_field_qualify_DstIp6(unit, endpoint_p->fp_entry_tx,
   1710                                           data, mask));
   1711         BCM_IF_ERROR_RETURN
   1712             (bcm_esw_field_qualify_EtherType(unit, endpoint_p->fp_entry_tx,
   1713                                         0x8902, 0xffff));
   1714 
   1715         if (0 == skip_entry_rx) {
   1716             BCM_IF_ERROR_RETURN
   1717             (bcm_esw_field_qualify_DstIp6(unit, endpoint_p->fp_entry_rx,
   1718                                           data, mask));
   1719             BCM_IF_ERROR_RETURN
   1720             (bcm_esw_field_qualify_EtherType(unit, endpoint_p->fp_entry_rx,
   1721                                         0x8902, 0xffff));
   1722         }
   1723     }
   1724 
   1725     BCM_IF_ERROR_RETURN
   1726         (bcm_esw_field_action_add(unit, endpoint_p->fp_entry_tx,
   1727                                   bcmFieldActionOamLmepEnable,
   1728                                   1, 0));
   1729     BCM_IF_ERROR_RETURN
   1730         (bcm_esw_field_action_add(unit, endpoint_p->fp_entry_tx,
   1731             bcmFieldActionOamLmEnable,
   1732             endpoint_p->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT? 1:0, 0));
   1733 
   1734     BCM_IF_ERROR_RETURN
   1735         (bcm_esw_field_action_add(unit, endpoint_p->fp_entry_tx,
   1736             bcmFieldActionOamDmEnable,
   1737             endpoint_p->flags & BCM_OAM_ENDPOINT_DELAY_MEASUREMENT? 1:0, 0));
   1738 
   1739     BCM_IF_ERROR_RETURN
   1740         (bcm_esw_field_action_add(unit, endpoint_p->fp_entry_tx,
   1741                                   bcmFieldActionOamLmepMdl,
   1742                                   endpoint_p->level, 0));
   1743 
   1744     BCM_IF_ERROR_RETURN
   1745         (bcm_esw_field_action_add(unit, endpoint_p->fp_entry_tx,
   1746              bcmFieldActionOamUpMep,
   1747              endpoint_p->flags & BCM_OAM_ENDPOINT_UP_FACING? 1:0, 0));
   1748     
   1749     if (endpoint_p->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT)
   1750     {
   1751         /* Assign LM counter and priority mapping table */
   1752         BCM_IF_ERROR_RETURN
   1753             (bcm_esw_field_action_add(unit, endpoint_p->fp_entry_tx,
   1754                                   bcmFieldActionOamLmBasePtr,
   1755                                   endpoint_p->lm_counter_index, 0));
   1756 
   1757         BCM_IF_ERROR_RETURN
   1758             (bcm_esw_field_action_add(unit, endpoint_p->fp_entry_tx,
   1759                                   bcmFieldActionOamServicePriMappingPtr,
   1760                                   endpoint_p->pri_map_index, 0));
   1761     }
   1762 
   1763     BCM_IF_ERROR_RETURN
   1764         (bcm_esw_field_action_add(unit, endpoint_p->fp_entry_tx,
   1765              bcmFieldActionOamTx,
   1766              endpoint_p->flags & BCM_OAM_ENDPOINT_UP_FACING ? 1:0, 0));
   1767 
   1768     if (0 == skip_entry_rx) {
   1769 
   1770     BCM_IF_ERROR_RETURN
   1771         (bcm_esw_field_action_add(unit, endpoint_p->fp_entry_rx,
   1772                                   bcmFieldActionOamLmepEnable,
   1773                                   1, 0));
   1774     BCM_IF_ERROR_RETURN
   1775         (bcm_esw_field_action_add(unit, endpoint_p->fp_entry_rx,
   1776             bcmFieldActionOamLmEnable,
   1777             endpoint_p->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT? 1:0, 0));
   1778     BCM_IF_ERROR_RETURN
   1779         (bcm_esw_field_action_add(unit, endpoint_p->fp_entry_rx,
   1780             bcmFieldActionOamDmEnable,
   1781             endpoint_p->flags & BCM_OAM_ENDPOINT_DELAY_MEASUREMENT? 1:0, 0));
   1782     
   1783     BCM_IF_ERROR_RETURN
   1784         (bcm_esw_field_action_add(unit, endpoint_p->fp_entry_rx,
   1785                                   bcmFieldActionOamLmepMdl,
   1786                                   endpoint_p->level, 0));
   1787     BCM_IF_ERROR_RETURN
   1788         (bcm_esw_field_action_add(unit, endpoint_p->fp_entry_rx,
   1789                  bcmFieldActionOamUpMep,
   1790                  endpoint_p->flags & BCM_OAM_ENDPOINT_UP_FACING? 1:0, 0));
   1791     
   1792     if (endpoint_p->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT)
   1793     {
   1794         /* Allocate LM counter and priority mapping table */
   1795         BCM_IF_ERROR_RETURN
   1796             (bcm_esw_field_action_add(unit, endpoint_p->fp_entry_rx,
   1797                                       bcmFieldActionOamLmBasePtr,
   1798                                       endpoint_p->lm_counter_index, 0));
   1799         BCM_IF_ERROR_RETURN
   1800             (bcm_esw_field_action_add(unit, endpoint_p->fp_entry_rx,
   1801                                       bcmFieldActionOamServicePriMappingPtr,
   1802                                       endpoint_p->pri_map_index, 0));
   1803     }
   1804     
   1805     BCM_IF_ERROR_RETURN
   1806         (bcm_esw_field_action_add(unit, endpoint_p->fp_entry_rx,
   1807                  bcmFieldActionOamTx,
   1808                  endpoint_p->flags & BCM_OAM_ENDPOINT_UP_FACING ? 0:1, 0));
   1809 
   1810     } /* if (0 == skip_entry_rx) */
   1811 
   1812     if (endpoint_p->vp != 0) {
   1813         oam_info_p->fp_vp_entry_count++;
   1814     } else {
   1815         oam_info_p->fp_glp_entry_count++;
   1816     }
   1817 
   1818     if ((mep_on_trunk != 0) &&
   1819         !(endpoint_p->flags & BCM_OAM_ENDPOINT_UP_FACING)) {
   1820         /* Create fp entry for each port in the trunk for down mep only. */
   1821         BCM_IF_ERROR_RETURN
   1822             (_bcm_en_oam_trunk_install_fp(unit, add_mdl, endpoint_p));
   1823     }
   1824 
   1825 #ifdef BCM_WARM_BOOT_SUPPORT
   1826     SOC_CONTROL_LOCK(unit);
   1827     SOC_CONTROL(unit)->scache_dirty = 1;
   1828     SOC_CONTROL_UNLOCK(unit);
   1829 #endif
   1830 
   1831     return BCM_E_NONE;
   1832 }
   1833 
   1834 static void _bcm_en_oam_free_memory(int unit, _bcm_oam_info_t *oam_info_p)
   1835 {
   1836     if (NULL != oam_info_p->remote_endpoints) {
   1837         sal_free(oam_info_p->remote_endpoints);
   1838         oam_info_p->remote_endpoints = NULL;
   1839     }
   1840 
   1841     if (NULL != oam_info_p->remote_endpoints_in_use) {
   1842         sal_free(oam_info_p->remote_endpoints_in_use);
   1843         oam_info_p->remote_endpoints_in_use = NULL;
   1844     }
   1845 
   1846     if (NULL != oam_info_p->local_rx_endpoints_in_use) {
   1847         sal_free(oam_info_p->local_rx_endpoints_in_use);
   1848         oam_info_p->local_rx_endpoints_in_use = NULL;
   1849     }
   1850 
   1851     if (NULL != oam_info_p->local_tx_endpoints_in_use) {
   1852         sal_free(oam_info_p->local_tx_endpoints_in_use);
   1853         oam_info_p->local_tx_endpoints_in_use = NULL;
   1854     }
   1855 
   1856     if (NULL != oam_info_p->lm_counter_in_use) {
   1857         sal_free(oam_info_p->lm_counter_in_use);
   1858         oam_info_p->lm_counter_in_use = NULL;
   1859     }
   1860 
   1861     if (NULL != oam_info_p->endpoints) {
   1862         sal_free(oam_info_p->endpoints);
   1863         oam_info_p->endpoints = NULL;
   1864     }
   1865 
   1866     if (NULL != oam_info_p->groups) {
   1867         sal_free(oam_info_p->groups);
   1868         oam_info_p->groups = NULL;
   1869     }
   1870 
   1871     if (ing_pri_map_profile[unit]) {
   1872         sal_free(ing_pri_map_profile[unit]);
   1873         ing_pri_map_profile[unit] = NULL;
   1874     }
   1875 
   1876 #if defined(BCM_KATANA_SUPPORT)  && defined(INCLUDE_BHH)
   1877     if (SOC_IS_KATANAX(unit)) {
   1878         if (NULL != oam_info_p->dma_buffer){
   1879             soc_cm_sfree(oam_info_p->unit, oam_info_p->dma_buffer);
   1880             oam_info_p->dma_buffer = NULL;
   1881         }
   1882         if (NULL != oam_info_p->dmabuf_reply){
   1883             soc_cm_sfree(oam_info_p->unit, oam_info_p->dmabuf_reply);
   1884             oam_info_p->dmabuf_reply = NULL;
   1885         }
   1886     }
   1887 #endif
   1888 
   1889 #if defined(BCM_KATANA_SUPPORT)
   1890     if (SOC_IS_KATANAX(unit)) {
   1891         sal_free(oam_opcode_profile[unit]);
   1892         oam_opcode_profile[unit] = NULL;
   1893     }
   1894 #endif /* BCM_KATANA_SUPPORT */
   1895 
   1896 }
   1897 
   1898 static void _bcm_en_oam_event_unregister_all(_bcm_oam_info_t *oam_info_p)
   1899 {
   1900     _bcm_oam_event_handler_t *event_handler_p;
   1901     _bcm_oam_event_handler_t *event_handler_to_delete_p;
   1902 
   1903     event_handler_p = oam_info_p->event_handler_list_p;
   1904 
   1905     while (event_handler_p != NULL)
   1906     {
   1907         event_handler_to_delete_p = event_handler_p;
   1908         event_handler_p = event_handler_p->next_p;
   1909 
   1910         sal_free(event_handler_to_delete_p);
   1911     }
   1912     oam_info_p->event_handler_list_p = NULL;
   1913 }
   1914 
   1915 /*
   1916  * Function:
   1917  *      bcm_en_oam_init
   1918  * Purpose:
   1919  *      Initialize the OAM subsystem
   1920  * Parameters:
   1921  *      unit - (IN) Unit number.
   1922  * Returns:
   1923  *      BCM_E_XXX
   1924  * Notes:
   1925  */
   1926 int 
   1927 bcm_en_oam_init(
   1928     int unit)
   1929 {
   1930     _bcm_oam_info_t *oam_info_p;
   1931     bcm_oam_endpoint_t endpoint_index;
   1932     bcm_port_t port_index;
   1933     uint32 register_value, temp_index;
   1934     soc_mem_t mem;
   1935     int entry_words;
   1936     uint32 mem_entries[BCM_OAM_INTPRI_MAX];
   1937     void *entries[1];
   1938     int result, i;
   1939 #if defined(BCM_KATANA_SUPPORT)  && defined(INCLUDE_BHH)
   1940     int uc;
   1941     uint8 carrier_code[] = {0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF};
   1942     char *carrier_code_str;
   1943     uint32 node_id = 0;
   1944     bhh_sdk_msg_ctrl_init_t msg_init;
   1945     uint8 *buffer, *buffer_ptr;
   1946     uint16 buffer_len, reply_len;
   1947     int priority;
   1948     int ukernel_not_ready = 0;
   1949     uint8 bhh_consolidate_final_event = 0;
   1950     int status;
   1951 #endif
   1952 
   1953     SET_OAM_INFO;
   1954 
   1955     if (oam_info_p->initialized)
   1956     {
   1957         BCM_IF_ERROR_RETURN(bcm_en_oam_detach(unit));
   1958     }
   1959 
   1960     if (soc_feature(unit, soc_feature_bhh)) {
   1961 #if defined(BCM_KATANA_SUPPORT)  && defined(INCLUDE_BHH)
   1962     if (SOC_IS_KATANAX(unit)) {
   1963         /*
   1964          * Initialize uController side
   1965          */
   1966 
   1967         /*
   1968          * Start BHH application in BTE (Broadcom Task Engine) uController,
   1969          * if not already running (warm boot).
   1970          * Determine which uController is running BHH  by choosing the first
   1971          * uC that returns successfully.
   1972          */
   1973         for (uc = 0; uc < SOC_INFO(unit).num_ucs; uc++) {
   1974              result = soc_uc_status(unit, uc, &status);
   1975             if ((result == SOC_E_NONE) && (status != 0)) {
   1976                 result = soc_cmic_uc_appl_init(unit, uc, MOS_MSG_CLASS_BHH,
   1977                                                _BHH_UC_MSG_TIMEOUT_USECS,
   1978                                                BHH_SDK_VERSION,
   1979                                                BHH_UC_MIN_VERSION,
   1980                                                _bcm_oam_bhh_appl_callback,
   1981                                                NULL);
   1982                 if (SOC_E_NONE == result) {
   1983                     /* BHH started successfully */
   1984                     oam_info_p->uc_num = uc;
   1985                     break;
   1986                 }
   1987             }
   1988         }
   1989 
   1990         if (uc >= SOC_INFO(unit).num_ucs) {  /* Could not find or start BHH appl */
   1991             ukernel_not_ready = 1;
   1992             LOG_ERROR(BSL_LS_BCM_OAM,
   1993                       (BSL_META_U(unit,
   1994                                   "uKernel Not Ready, bhh not started\n")));
   1995         }
   1996     }
   1997 #endif
   1998     }
   1999 
   2000 
   2001     oam_info_p->group_count = soc_mem_index_count(unit, MA_STATEm);
   2002 
   2003     oam_info_p->groups =
   2004         _bcm_en_oam_alloc_clear(oam_info_p->group_count *
   2005 				sizeof(_bcm_oam_group_t), "_bcm_oam_group");
   2006 
   2007     if (oam_info_p->groups == NULL)
   2008     {
   2009         BCM_IF_ERROR_RETURN(bcm_en_oam_detach(unit));
   2010         return BCM_E_MEMORY;
   2011     }
   2012 
   2013     oam_info_p->remote_endpoint_count = soc_mem_index_count(unit, RMEPm);
   2014     oam_info_p->local_tx_endpoint_count = soc_mem_index_count(unit, LMEPm);
   2015 
   2016     oam_info_p->local_rx_endpoint_count =
   2017         soc_mem_index_count(unit, MA_INDEXm);
   2018 
   2019     oam_info_p->endpoint_count = oam_info_p->remote_endpoint_count +
   2020         oam_info_p->local_tx_endpoint_count + oam_info_p->local_rx_endpoint_count;
   2021 
   2022     if (soc_feature(unit, soc_feature_bhh)) {
   2023 #if defined(BCM_KATANA_SUPPORT)  && defined(INCLUDE_BHH)
   2024     oam_info_p->unit = unit;
   2025 
   2026     oam_info_p->ukernel_not_ready = ukernel_not_ready;
   2027 	/* Get SOC properties for BHH */
   2028 	oam_info_p->bhh_endpoint_count =
   2029 	    soc_property_get(unit, spn_BHH_NUM_SESSIONS, 256);
   2030 
   2031         oam_info_p->bhh_max_encap_length =
   2032                              soc_property_get(unit,
   2033                                               spn_BHH_ENCAP_MAX_LENGTH,
   2034                                               _BCM_OAM_BHH_DEFAULT_ENCAP_LENGTH);
   2035 
   2036         if(oam_info_p->bhh_max_encap_length > _BCM_OAM_BHH_MAX_ENCAP_LENGTH) {
   2037             LOG_ERROR(BSL_LS_BCM_OAM,
   2038                       (BSL_META_U(unit,
   2039                                   "Invalid max encap_length=%u\n"),
   2040                                   oam_info_p->bhh_max_encap_length));
   2041             BCM_IF_ERROR_RETURN(bcm_en_oam_detach(unit));
   2042             return BCM_E_CONFIG;
   2043         }
   2044 	carrier_code_str =
   2045 	    soc_property_get_str(unit, spn_BHH_CARRIER_CODE);
   2046 	if (carrier_code_str != NULL) {
   2047 	    /*
   2048 	     * Note that the carrier code is specified in colon separated
   2049 	     * MAC address format.
   2050 	     */
   2051 	    if (_shr_parse_macaddr(carrier_code_str, carrier_code) < 0) {
   2052                 BCM_IF_ERROR_RETURN(bcm_en_oam_detach(unit));
   2053                 return BCM_E_INTERNAL;
   2054             }
   2055 	}
   2056 
   2057 	node_id =
   2058 	    soc_property_get(unit, spn_BHH_NODE_ID, 0);
   2059     bhh_consolidate_final_event = soc_property_get(unit, 
   2060                                            spn_BHH_CONSOLIDATED_FINAL_EVENT, 0); 
   2061     oam_info_p->endpoint_count += oam_info_p->bhh_endpoint_count;
   2062 #endif
   2063     }
   2064 
   2065     oam_info_p->endpoints =
   2066         _bcm_en_oam_alloc_clear(oam_info_p->endpoint_count *
   2067 				sizeof(_bcm_oam_endpoint_t), "_bcm_oam_endpoint");
   2068 
   2069     if (oam_info_p->endpoints == NULL)
   2070     {
   2071         BCM_IF_ERROR_RETURN(bcm_en_oam_detach(unit));
   2072         return BCM_E_MEMORY;
   2073     }
   2074 
   2075     oam_info_p->local_tx_endpoints_in_use =
   2076         _bcm_en_oam_alloc_clear(SHR_BITALLOCSIZE(oam_info_p->local_tx_endpoint_count),
   2077 				"local_tx_endpoints_in_use");
   2078 
   2079     if (oam_info_p->local_tx_endpoints_in_use == NULL)
   2080     {
   2081         BCM_IF_ERROR_RETURN(bcm_en_oam_detach(unit));
   2082         return BCM_E_MEMORY;
   2083     }
   2084         
   2085     /* 
   2086      * Both TX and RX for one MEP 
   2087      */
   2088     oam_info_p->lm_counter_count = 
   2089         soc_mem_index_count(unit, OAM_LM_COUNTERSm) / 2;
   2090 
   2091     oam_info_p->lm_counter_in_use =
   2092         _bcm_en_oam_alloc_clear(SHR_BITALLOCSIZE(oam_info_p->lm_counter_count),
   2093 				"lm_counter_in_use");
   2094 
   2095     if (oam_info_p->lm_counter_in_use == NULL)
   2096     {
   2097         BCM_IF_ERROR_RETURN(bcm_en_oam_detach(unit));
   2098         return BCM_E_MEMORY;
   2099     }
   2100 
   2101     oam_info_p->local_rx_endpoints_in_use =
   2102         _bcm_en_oam_alloc_clear(SHR_BITALLOCSIZE(oam_info_p->local_rx_endpoint_count),
   2103 				"local_rx_endpoints_in_use");
   2104 
   2105     if (oam_info_p->local_rx_endpoints_in_use == NULL)
   2106     {
   2107         BCM_IF_ERROR_RETURN(bcm_en_oam_detach(unit));
   2108         return BCM_E_MEMORY;
   2109     }
   2110 
   2111     for (endpoint_index = 0; endpoint_index < oam_info_p->endpoint_count;
   2112 	 ++endpoint_index)
   2113     {
   2114         oam_info_p->endpoints[endpoint_index].lm_counter_index =
   2115             BCM_OAM_LM_COUNTER_INDEX_INVALID;
   2116     }
   2117 
   2118     oam_info_p->remote_endpoints_in_use =
   2119         _bcm_en_oam_alloc_clear(SHR_BITALLOCSIZE(oam_info_p->remote_endpoint_count),
   2120 				"remote_endpoints_in_use");
   2121 
   2122     if (oam_info_p->remote_endpoints_in_use == NULL)
   2123     {
   2124         BCM_IF_ERROR_RETURN(bcm_en_oam_detach(unit));
   2125         return BCM_E_MEMORY;
   2126     }
   2127 
   2128     oam_info_p->remote_endpoints =
   2129         sal_alloc(oam_info_p->remote_endpoint_count * sizeof(bcm_oam_endpoint_t),
   2130 		  "rmep reverse lookup");
   2131 
   2132     if (oam_info_p->remote_endpoints == NULL)
   2133     {
   2134         BCM_IF_ERROR_RETURN(bcm_en_oam_detach(unit));
   2135         return BCM_E_MEMORY;
   2136     }
   2137 
   2138     for (endpoint_index = 0; endpoint_index < oam_info_p->remote_endpoint_count;
   2139 	 ++endpoint_index)
   2140     {
   2141         oam_info_p->remote_endpoints[endpoint_index] = BCM_OAM_ENDPOINT_INVALID;
   2142     }
   2143 #ifdef BCM_KATANA_SUPPORT
   2144     if (SOC_IS_KATANA(unit)) {
   2145         soc_kt_oam_handler_register(unit, _bcm_en_oam_handle_interrupt);
   2146     } else
   2147 #endif /* BCM_KATANA_SUPPORT */
   2148     {
   2149         soc_enduro_oam_handler_register(unit, _bcm_en_oam_handle_interrupt);
   2150     }
   2151 #ifdef BCM_KATANA_SUPPORT
   2152     if (SOC_IS_KATANAX(unit)) {
   2153         /* Initialize the OAM_OPCODE_PROFILE table */
   2154         if (oam_opcode_profile[unit] == NULL) {
   2155             oam_opcode_profile[unit] =
   2156                 sal_alloc(sizeof(soc_profile_mem_t), "OAM Opcode profile Mem");
   2157             if (oam_opcode_profile[unit] == NULL) {
   2158                 BCM_IF_ERROR_RETURN(bcm_en_oam_detach(unit));
   2159                 return BCM_E_MEMORY;
   2160             }
   2161             soc_profile_mem_t_init(oam_opcode_profile[unit]);
   2162         }
   2163 
   2164         /* Create profile table cache (or re-init if it already exists) */
   2165         mem = OAM_OPCODE_CONTROL_PROFILEm;
   2166         entry_words = sizeof(oam_opcode_control_profile_entry_t) / sizeof(uint32);
   2167         result = soc_profile_mem_create(unit, &mem, &entry_words,
   2168                                         1, oam_opcode_profile[unit]);
   2169         if (SOC_FAILURE(result)) {
   2170             BCM_IF_ERROR_RETURN(bcm_en_oam_detach(unit));
   2171             return result;
   2172         }
   2173 }
   2174 #endif /* BCM_KATANA_SUPPORT */
   2175 
   2176 #ifdef BCM_WARM_BOOT_SUPPORT
   2177     if (!SOC_WARM_BOOT(unit)) {
   2178         bcm_en_oam_scache_alloc(unit);
   2179     }
   2180     if (SOC_WARM_BOOT(unit))
   2181     {
   2182         _bcm_en_oam_warm_boot(unit);
   2183     }
   2184     else
   2185 #endif /* BCM_WARM_BOOT_SUPPORT */
   2186     {
   2187         /* Enable OAM message reception on all ports */
   2188         PBMP_ALL_ITER(unit, port_index)
   2189         {
   2190             result = bcm_esw_port_control_set(unit, port_index,
   2191 				     bcmPortControlOAMEnable, 1);
   2192             if (BCM_FAILURE(result))
   2193             {
   2194                 BCM_IF_ERROR_RETURN(bcm_en_oam_detach(unit));
   2195                 return result;
   2196             }
   2197         }
   2198 
   2199         /* Enable CCM reception timeouts */
   2200         register_value = 0;
   2201 
   2202         soc_reg_field_set(unit, OAM_TIMER_CONTROLr, &register_value,
   2203 			  TIMER_ENABLEf, 1);
   2204 
   2205         soc_reg_field_set(unit, OAM_TIMER_CONTROLr, &register_value,
   2206 			  CLK_GRANf, 1);
   2207 
   2208         result = WRITE_OAM_TIMER_CONTROLr(unit, register_value);
   2209         if (SOC_FAILURE(result))
   2210         {
   2211             BCM_IF_ERROR_RETURN(bcm_en_oam_detach(unit));
   2212             return result;
   2213         }
   2214 
   2215         if (!SOC_IS_KATANA(unit)) 
   2216         {
   2217             /* Common information for outgoing CCM packets */
   2218             result = WRITE_LMEP_COMMON_1r(unit, _BCM_OAM_MAC_DA_UPPER_32);
   2219             if (SOC_FAILURE(result))
   2220             {
   2221                 BCM_IF_ERROR_RETURN(bcm_en_oam_detach(unit));
   2222                 return result;
   2223             }
   2224         }
   2225 
   2226         /* Enable CCM transmission */
   2227         register_value = 0;
   2228 
   2229         soc_reg_field_set(unit, OAM_TX_CONTROLr, &register_value,
   2230 			  TX_ENABLEf, 1);
   2231         soc_reg_field_set(unit, OAM_TX_CONTROLr, &register_value,
   2232 			  CMIC_BUF_ENABLEf, 1);
   2233 
   2234         result = WRITE_OAM_TX_CONTROLr(unit, register_value);
   2235         if (SOC_FAILURE(result)) 
   2236         {
   2237             BCM_IF_ERROR_RETURN(bcm_en_oam_detach(unit));
   2238             return result;
   2239         }
   2240             
   2241         register_value = 0;
   2242         soc_reg_field_set(unit, LMEP_COMMON_2r, &register_value,
   2243 			  DA_15_3f, _BCM_OAM_MAC_DA_LOWER_13 >> 3);
   2244         soc_reg_field_set(unit, LMEP_COMMON_2r, &register_value,
   2245 			  L3f, 1);
   2246 
   2247         result = WRITE_LMEP_COMMON_2r(unit, register_value);
   2248         if (SOC_FAILURE(result))
   2249         {
   2250             BCM_IF_ERROR_RETURN(bcm_en_oam_detach(unit));
   2251             return result;
   2252         }
   2253     }
   2254         
   2255     oam_info_p->vfp_entry_count = 0;
   2256         
   2257     BCM_FIELD_QSET_INIT(oam_info_p->vfp_qs);
   2258     BCM_FIELD_QSET_ADD(oam_info_p->vfp_qs, bcmFieldQualifyDstMac);
   2259     BCM_FIELD_QSET_ADD(oam_info_p->vfp_qs, bcmFieldQualifySrcMac);
   2260     BCM_FIELD_QSET_ADD(oam_info_p->vfp_qs, bcmFieldQualifyOuterVlanId);
   2261     BCM_FIELD_QSET_ADD(oam_info_p->vfp_qs, bcmFieldQualifyStageLookup);
   2262     
   2263     oam_info_p->fp_vp_entry_count = 0;
   2264     oam_info_p->fp_glp_entry_count = 0;
   2265 
   2266     BCM_FIELD_QSET_INIT(oam_info_p->fp_vp_qs);
   2267     BCM_FIELD_QSET_ADD(oam_info_p->fp_vp_qs, bcmFieldQualifyOuterVlanId);
   2268     BCM_FIELD_QSET_ADD(oam_info_p->fp_vp_qs, bcmFieldQualifyDstMimGport);
   2269     BCM_FIELD_QSET_ADD(oam_info_p->fp_vp_qs, bcmFieldQualifySrcMimGport);
   2270     BCM_FIELD_QSET_ADD(oam_info_p->fp_vp_qs, bcmFieldQualifyStageIngress);
   2271         
   2272     BCM_FIELD_QSET_INIT(oam_info_p->fp_glp_qs);
   2273     BCM_FIELD_QSET_ADD(oam_info_p->fp_glp_qs, bcmFieldQualifyOuterVlanId);
   2274     BCM_FIELD_QSET_ADD(oam_info_p->fp_glp_qs, bcmFieldQualifyDstPort);
   2275     BCM_FIELD_QSET_ADD(oam_info_p->fp_glp_qs, bcmFieldQualifyDstTrunk);
   2276     BCM_FIELD_QSET_ADD(oam_info_p->fp_glp_qs, bcmFieldQualifySrcPort);
   2277     BCM_FIELD_QSET_ADD(oam_info_p->fp_glp_qs, bcmFieldQualifySrcTrunk);
   2278     BCM_FIELD_QSET_ADD(oam_info_p->fp_glp_qs, bcmFieldQualifyEtherType);
   2279     BCM_FIELD_QSET_ADD(oam_info_p->fp_glp_qs, bcmFieldQualifyDstIp6);
   2280     BCM_FIELD_QSET_ADD(oam_info_p->fp_glp_qs, bcmFieldQualifyStageIngress);
   2281 
   2282     /* 
   2283      * Enable ingress filter for CPU port so LM/DM packets sent from CPU
   2284      * can be processed.
   2285      */
   2286     result = bcm_esw_port_control_set(unit, CMIC_PORT(unit), 
   2287 			     bcmPortControlFilterIngress, 1);
   2288     if (BCM_FAILURE(result))
   2289     {
   2290         BCM_IF_ERROR_RETURN(bcm_en_oam_detach(unit));
   2291         return result;
   2292     }
   2293 
   2294     /* Initialize the ING_VLAN_TAG_ACTION_PROFILE table */
   2295     if (ing_pri_map_profile[unit] == NULL) 
   2296     {
   2297         ing_pri_map_profile[unit] = 
   2298             sal_alloc(sizeof(soc_profile_mem_t), "Ing Pri Map Profile Mem");
   2299         if (ing_pri_map_profile[unit] == NULL) 
   2300         {
   2301             BCM_IF_ERROR_RETURN(bcm_en_oam_detach(unit));
   2302             return BCM_E_MEMORY;
   2303         }
   2304         soc_profile_mem_t_init(ing_pri_map_profile[unit]);
   2305     }
   2306 
   2307     /* Create profile table cache (or re-init if it already exists) */
   2308     mem = ING_SERVICE_PRI_MAPm;
   2309     entry_words = sizeof(ing_service_pri_map_entry_t) / sizeof(uint32);
   2310     result = soc_profile_mem_create(unit, &mem, &entry_words, 1,
   2311                                     ing_pri_map_profile[unit]);
   2312     if (SOC_FAILURE(result)) {
   2313         BCM_IF_ERROR_RETURN(bcm_en_oam_detach(unit));
   2314         return result;
   2315     }
   2316 
   2317 
   2318     /* Initialize the ING_SERVICE_PRI_MAP_PROFILE_DEFAULT. All priorities
   2319      * Map to zero.
   2320      */
   2321     for (i = 0; i < BCM_OAM_INTPRI_MAX; i++) 
   2322     {
   2323         mem_entries[i] = 0;
   2324         if (SOC_MEM_FIELD_VALID(unit, mem, OFFSET_VALIDf)) {
   2325             soc_mem_field32_set(unit, mem, &mem_entries[i], OFFSET_VALIDf, 1);
   2326         }
   2327     }
   2328     entries[0] = &mem_entries;
   2329     result = soc_profile_mem_add(unit, ing_pri_map_profile[unit],
   2330                                  (void *) &entries, BCM_OAM_INTPRI_MAX,
   2331                                  &temp_index);
   2332     if (SOC_FAILURE(result)) {
   2333         BCM_IF_ERROR_RETURN(bcm_en_oam_detach(unit));
   2334         return result;
   2335     }
   2336 
   2337 
   2338 #ifdef BCM_WARM_BOOT_SUPPORT
   2339     if (SOC_WARM_BOOT(unit))
   2340     {
   2341         /* Recover FP groups and entries associated with OAM */
   2342         oam_info_p->vfp_group = -1;
   2343         oam_info_p->fp_vp_group = -1;
   2344         oam_info_p->fp_glp_group = -1;
   2345         result = bcm_esw_field_group_traverse(unit,
   2346                                               _bcm_en_oam_field_group_process,
   2347                                               NULL);
   2348         if (BCM_FAILURE(result)) {
   2349             BCM_IF_ERROR_RETURN(bcm_en_oam_detach(unit));
   2350             return result;
   2351         }
   2352     }
   2353 #endif 
   2354 
   2355     /*
   2356      * BHH init
   2357      */
   2358     if (soc_feature(unit, soc_feature_bhh)) {
   2359 #if defined(BCM_KATANA_SUPPORT)  && defined(INCLUDE_BHH)
   2360     if (SOC_IS_KATANAX(unit)) {
   2361         if(ukernel_not_ready == 0) {
   2362             /*
   2363              * Initialize HOST side
   2364              */
   2365             oam_info_p->cpu_cosq =
   2366                 soc_property_get(unit, spn_BHH_COSQ, 42);
   2367 
   2368             /*
   2369              * Allocate DMA buffers
   2370              *
   2371              * DMA buffer will be used to send and receive 'long' messages
   2372              * between SDK Host and uController (BTE).
   2373              */
   2374             oam_info_p->dma_buffer_len = sizeof(shr_bhh_msg_ctrl_t);
   2375 
   2376             /* Adding  feature specific for dma_buf_len as currently
   2377              * required buffer length for faults_get can be configurable
   2378              * by user during init. So, taking the max value of either of
   2379              * them for the purpose.Putting it under fature_check for
   2380              * giving flexibility to user.
   2381              */
   2382 #ifdef INCLUDE_OAM_FAULTS_MULTI_GET
   2383             if(soc_feature(unit, soc_feature_faults_multi_ep_get)) {
   2384                 oam_info_p->dma_buffer_len = MAX((oam_info_p->bhh_endpoint_count * sizeof(uint32)),
   2385                                                   oam_info_p->dma_buffer_len);
   2386             }
   2387 #endif
   2388             oam_info_p->dma_buffer = soc_cm_salloc(unit, 
   2389                                                    oam_info_p->dma_buffer_len,
   2390                                                    "BHH DMA buffer");
   2391             if (!oam_info_p->dma_buffer) {
   2392                 BCM_IF_ERROR_RETURN(bcm_en_oam_detach(unit));
   2393                 return BCM_E_MEMORY;
   2394             }
   2395             sal_memset(oam_info_p->dma_buffer, 0, oam_info_p->dma_buffer_len);
   2396 
   2397             oam_info_p->dmabuf_reply = soc_cm_salloc(unit, 
   2398                                                      oam_info_p->dma_buffer_len,
   2399                                                      "BHH uC reply");
   2400             if (!oam_info_p->dmabuf_reply) {
   2401                 BCM_IF_ERROR_RETURN(bcm_en_oam_detach(unit));
   2402                 return BCM_E_MEMORY;
   2403             }
   2404             sal_memset(oam_info_p->dmabuf_reply, 0, oam_info_p->dma_buffer_len);
   2405 
   2406             /* RX DMA channel (0..3) local to the uC */
   2407             oam_info_p->rx_channel = BCM_KT_BHH_RX_CHANNEL;
   2408 
   2409 #if defined(BCM_WARM_BOOT_SUPPORT)
   2410     if (!SOC_WARM_BOOT(unit)) {
   2411 #endif
   2412             /* Set control message data */
   2413             sal_memset(&msg_init, 0, sizeof(msg_init));
   2414             msg_init.num_sessions       = oam_info_p->bhh_endpoint_count;
   2415             msg_init.rx_channel         = oam_info_p->rx_channel;
   2416             msg_init.node_id            = node_id; 
   2417             sal_memcpy(msg_init.carrier_code, carrier_code, 
   2418                        SHR_BHH_CARRIER_CODE_LEN); 
   2419             msg_init.max_encap_length = oam_info_p->bhh_max_encap_length;
   2420             if (bhh_consolidate_final_event) {
   2421                     msg_init.flags |= BHH_SDK_MSG_CTRL_INIT_ONLY_FINAL_EVENT;
   2422             }
   2423             /* Pack control message data into DMA buffer */
   2424             buffer     = oam_info_p->dma_buffer;
   2425             buffer_ptr = bhh_sdk_msg_ctrl_init_pack(unit, buffer, &msg_init);
   2426             buffer_len = buffer_ptr - buffer;
   2427 
   2428             /* Send BHH Init message to uC */
   2429             result = _bcm_en_oam_bhh_msg_send_receive(unit,
   2430                                                 MOS_MSG_SUBCLASS_BHH_INIT,
   2431                                                 buffer_len, 0,
   2432                                                 MOS_MSG_SUBCLASS_BHH_INIT_REPLY,
   2433                                                 &reply_len);
   2434 
   2435             if (BCM_FAILURE(result) || (reply_len != 0)) {
   2436                 BCM_IF_ERROR_RETURN(bcm_en_oam_detach(unit));
   2437                 return BCM_E_INTERNAL;
   2438             }
   2439 #if defined(BCM_WARM_BOOT_SUPPORT)
   2440     }
   2441 #endif
   2442 
   2443             /*
   2444              * Start event message callback thread
   2445              */
   2446             priority = soc_property_get(unit,
   2447                                         spn_BHH_THREAD_PRI,
   2448                                         BHH_THREAD_PRI_DFLT);
   2449 
   2450             if (oam_info_p->event_thread_id == NULL) {
   2451                 if ((oam_info_p->event_thread_id =
   2452                      sal_thread_create("bcmBHH", SAL_THREAD_STKSZ,
   2453                                       priority,
   2454                                       _bcm_en_oam_bhh_callback_thread,
   2455                                        (void*)oam_info_p)) == SAL_THREAD_ERROR) {
   2456 
   2457                     oam_info_p->event_thread_id = NULL;
   2458                     BCM_IF_ERROR_RETURN(bcm_en_oam_detach(unit));
   2459                     return BCM_E_MEMORY;
   2460                 }
   2461             }
   2462             /*
   2463              * End BHH init
   2464              */
   2465         }
   2466         /*
   2467          * Initialize HW
   2468          */
   2469         result = _bcm_en_oam_bhh_hw_init(unit);
   2470         if (BCM_FAILURE(result)) {
   2471             BCM_IF_ERROR_RETURN(bcm_en_oam_detach(unit));
   2472                 return result;
   2473         }
   2474     }
   2475 #endif
   2476     }
   2477 
   2478     oam_info_p->initialized = 1;
   2479 
   2480     return BCM_E_NONE;
   2481 }
   2482 
   2483 #if defined(BCM_KATANA_SUPPORT) && defined(INCLUDE_BHH)
   2484 
   2485 /*
   2486  * Function:
   2487  *      bcm_en_oam_bhh_hw_init
   2488  * Purpose:
   2489  *      Initialize the HW for BHH packet processing.
   2490  *      Configure:
   2491  *      - Copy to CPU BHH error packets
   2492  *      - CPU COS Queue for BHH packets
   2493  *      - RX DMA channel
   2494  * Parameters:
   2495  *      unit - (IN) Unit number.
   2496  * Returns:
   2497  *      BCM_E_XXX
   2498  * Notes:
   2499  */
   2500 STATIC int
   2501 _bcm_en_oam_bhh_hw_init(int unit)
   2502 {
   2503     int rv = BCM_E_NONE;
   2504      _bcm_oam_info_t *oam_info_p;
   2505     uint32 val; 
   2506     int index;
   2507     int ach_error_index;
   2508     int invalid_error_index;
   2509     int cosq_map_size;
   2510     bcm_rx_reasons_t reasons, reasons_mask;
   2511     uint8 int_prio, int_prio_mask;
   2512     uint32 packet_type, packet_type_mask;
   2513     bcm_cos_queue_t cosq;
   2514     bcm_rx_chan_t chan_id;
   2515 
   2516     SET_OAM_INFO;
   2517 
   2518     /*
   2519      * Send BHH error packet to CPU
   2520      *
   2521      * Configure CPU_CONTROL_0 register
   2522      */
   2523     BCM_IF_ERROR_RETURN(READ_CPU_CONTROL_0r(unit, &val));
   2524     soc_reg_field_set(unit, CPU_CONTROL_0r, &val,
   2525                       BFD_UNKNOWN_VERSION_TOCPUf, 1);
   2526     soc_reg_field_set(unit, CPU_CONTROL_0r, &val,
   2527                       BFD_YOUR_DISCRIMINATOR_NOT_FOUND_TOCPUf, 1);
   2528     soc_reg_field_set(unit, CPU_CONTROL_0r, &val,
   2529                       BFD_UNKNOWN_CONTROL_PACKET_TOCPUf, 1);
   2530     soc_reg_field_set(unit, CPU_CONTROL_0r, &val,
   2531                       BFD_UNKNOWN_ACH_CHANNEL_TYPE_TOCPUf, 1);
   2532     soc_reg_field_set(unit, CPU_CONTROL_0r, &val,
   2533                       BFD_UNKNOWN_ACH_VERSION_TOCPUf, 1);
   2534     BCM_IF_ERROR_RETURN(WRITE_CPU_CONTROL_0r(unit, val));
   2535 
   2536     /*
   2537      * Set BFD ACH Channel Types
   2538      */
   2539 #if 0
   2540     BCM_IF_ERROR_RETURN(READ_BFD_RX_ACH_TYPE_MPLSTPr(unit, &val));
   2541     soc_reg_field_set(unit, BFD_RX_ACH_TYPE_MPLSTPr, &val,
   2542                       BFD_ACH_TYPE_MPLSTP_CVf,
   2543                       SHR_BHH_ACH_CHANNEL_TYPE);
   2544     BCM_IF_ERROR_RETURN(WRITE_BFD_RX_ACH_TYPE_MPLSTPr(unit, val));
   2545 #endif
   2546 
   2547     if(oam_info_p->ukernel_not_ready == 0) {
   2548         /*
   2549          * Direct BHH packets to designated CPU COS Queue...or more accurately
   2550          * BFD error packets.
   2551          *
   2552          * Reasons:
   2553          *   - bcmRxReasonBFD:               BFD error
   2554          *   - bcmRxReasonBfdUnknownVersion: BFD Unknown ACH
   2555          * NOTE:
   2556          *     The user input 'cpu_qid' (bcm_BHH_endpoint_t) could be
   2557          *     used to select different CPU COS queue. Currently,
   2558          *     all priorities are mapped into the same CPU COS Queue.
   2559          */
   2560 
   2561         /* Find available entries in CPU COS queue map table */
   2562         ach_error_index    = -1;   /* COSQ map index for error packets */
   2563         invalid_error_index    = -1;   /* COSQ map index for error packets */
   2564         BCM_IF_ERROR_RETURN
   2565             (bcm_esw_rx_cosq_mapping_size_get(unit, &cosq_map_size));
   2566     
   2567         for (index = 0; index < cosq_map_size; index++) {
   2568             rv = bcm_esw_rx_cosq_mapping_get(unit, index,
   2569                                              &reasons, &reasons_mask,
   2570                                              &int_prio, &int_prio_mask,
   2571                                              &packet_type, &packet_type_mask,
   2572                                              &cosq);
   2573             if (rv == BCM_E_NOT_FOUND) {
   2574                 /* Assign first available index */
   2575                 rv = BCM_E_NONE;
   2576                 if (ach_error_index == -1) {
   2577                     ach_error_index = index;
   2578                 } else if (invalid_error_index == -1) {
   2579                     invalid_error_index = index;
   2580                     break;
   2581                 }
   2582             }
   2583             if (BCM_FAILURE(rv)) {
   2584                 return rv;
   2585             }
   2586         }
   2587 
   2588         if (ach_error_index == -1 || invalid_error_index == -1) {
   2589             return BCM_E_FULL;
   2590         }
   2591 
   2592         /* Set CPU COS Queue mapping */
   2593         BCM_RX_REASON_CLEAR_ALL(reasons);
   2594         BCM_RX_REASON_SET(reasons, bcmRxReasonBfd);  /* BFD Error */
   2595         BCM_RX_REASON_SET(reasons, bcmRxReasonBfdUnknownVersion); /* Despite the name this reason */
   2596         /* code covers Unknown ACH */
   2597 
   2598         BCM_IF_ERROR_RETURN
   2599             (bcm_esw_rx_cosq_mapping_set(unit, ach_error_index,
   2600                                          reasons, reasons,
   2601                                          0, 0, /* Any priority */
   2602                                          0, 0, /* Any packet type */
   2603                                          oam_info_p->cpu_cosq));
   2604         oam_info_p->cpu_cosq_ach_error_index = ach_error_index;
   2605 
   2606 
   2607         BCM_RX_REASON_CLEAR_ALL(reasons);
   2608         BCM_RX_REASON_SET(reasons, bcmRxReasonBfd);  /* BFD Error */
   2609         BCM_RX_REASON_SET(reasons, bcmRxReasonBfdInvalidPacket); 
   2610 
   2611         BCM_IF_ERROR_RETURN
   2612             (bcm_esw_rx_cosq_mapping_set(unit, invalid_error_index,
   2613                                          reasons, reasons,
   2614                                          0, 0, /* Any priority */
   2615                                          0, 0, /* Any packet type */
   2616                                          oam_info_p->cpu_cosq));
   2617         oam_info_p->cpu_cosq_invalid_error_index = invalid_error_index;
   2618 
   2619 
   2620         /*
   2621          * Assign RX DMA channel to CPU COS Queue
   2622          * (This is the RX channel to listen on for BHH packets).
   2623          *
   2624          * DMA channels (12) are assigned 4 per processor:
   2625          * (see /src/bcm/common/rx.c)
   2626          *   channels 0..3  --> PCI host
   2627          *   channels 4..7  --> uController 0
   2628          *   chnanels 8..11 --> uController 1
   2629          *
   2630          * The uControllers designate the 4 local DMA channels as follows:
   2631          *   local channel  0     --> TX
   2632          *   local channel  1..3  --> RX
   2633          *
   2634          * Each uController application needs to use a different
   2635          * RX DMA channel to listen on.
   2636          */
   2637         chan_id = (BCM_RX_CHANNELS * (SOC_ARM_CMC(unit, oam_info_p->uc_num))) +
   2638             oam_info_p->rx_channel;
   2639 
   2640         rv = _bcm_common_rx_queue_channel_set(unit, oam_info_p->cpu_cosq, chan_id);
   2641         if (rv != BCM_E_NONE ) {
   2642             LOG_ERROR(BSL_LS_BCM_COMMON,
   2643                       (BSL_META_U(unit,
   2644                                   "BHH(unit %d) Error: No BHH COS Queue available from uC%d - %s\n"),
   2645                        unit, oam_info_p->uc_num, bcm_errmsg(BCM_E_CONFIG))); 
   2646         }
   2647     }
   2648 
   2649     return rv;
   2650 }
   2651 
   2652 
   2653 /*
   2654  * Function:
   2655  *      _bcm_en_oam_bhh_find_l2x_entry
   2656  */
   2657 STATIC int
   2658 _bcm_en_oam_bhh_find_l2x_entry(int unit, uint32 key, int key_type, int ses_type,
   2659 			       int *index, l2x_entry_t *l2_entry)
   2660 {
   2661     l2x_entry_t l2_key;
   2662 
   2663     sal_memset(&l2_key, 0, sizeof(l2_key));
   2664 
   2665     soc_mem_field32_set(unit, L2Xm, &l2_key, KEY_TYPEf, key_type);
   2666     soc_mem_field32_set(unit, L2Xm, &l2_key,
   2667                         SESSION_IDENTIFIER_TYPEf, ses_type);
   2668 
   2669     if (ses_type) {
   2670         soc_mem_field32_set(unit, L2Xm, &l2_key, LABELf, key);
   2671     } else {
   2672         soc_mem_field32_set(unit, L2Xm, &l2_key,
   2673                             YOUR_DISCRIMINATORf, key);
   2674     }
   2675 
   2676     return soc_mem_search(unit, L2Xm, MEM_BLOCK_ANY, index,
   2677                           &l2_key, l2_entry, 0);
   2678 
   2679 }
   2680 
   2681 /*
   2682  * Function:
   2683  *      _bcm_en_oam_bhh_session_hw_delete
   2684  * Purpose:
   2685  *      Delete BHH Session in HW device.
   2686  * Parameters:
   2687  *      unit       - (IN) Unit number.
   2688  *      endpoint_p - (IN) Pointer to BHH endpoint structure.
   2689  * Returns:
   2690  *      BCM_E_XXX
   2691  * Notes:
   2692  */
   2693 STATIC int
   2694 _bcm_en_oam_bhh_session_hw_delete(int unit, _bcm_oam_endpoint_t *endpoint_p)
   2695 {
   2696     int rv = BCM_E_NONE;
   2697     int l2_index = 0;
   2698     l2x_entry_t l2_entry;
   2699 #if defined(BCM_TRIUMPH_SUPPORT) && defined(BCM_MPLS_SUPPORT)
   2700     mpls_entry_entry_t mpls_entry;
   2701     mpls_entry_entry_t mpls_key;
   2702     int mpls_index = 0;
   2703 #endif /* BCM_TRIUMPH_SUPPORT &&  BCM_MPLS_SUPPORT */
   2704 
   2705 
   2706     switch(endpoint_p->type) {
   2707     case bcmOAMEndpointTypeBHHMPLS:
   2708     case bcmOAMEndpointTypeBHHMPLSVccv:
   2709 #if defined(BCM_TRIUMPH_SUPPORT) && defined(BCM_MPLS_SUPPORT)
   2710         SOC_IF_ERROR_RETURN(bcm_tr_mpls_lock (unit));
   2711 
   2712         sal_memset(&mpls_key, 0, sizeof(mpls_key));
   2713         soc_MPLS_ENTRYm_field32_set(unit, &mpls_key,
   2714                                     MPLS_LABELf, endpoint_p->label);
   2715 
   2716         SOC_IF_ERROR_RETURN(soc_mem_search(unit, MPLS_ENTRYm,
   2717                                            MEM_BLOCK_ANY, &mpls_index,
   2718                                            &mpls_key, &mpls_entry, 0));
   2719 
   2720         if ((soc_MPLS_ENTRYm_field32_get(unit,
   2721                                          &mpls_entry, VALIDf) != 0x1)) {
   2722             bcm_tr_mpls_unlock (unit);
   2723             return BCM_E_PARAM;
   2724         }
   2725 
   2726         soc_MPLS_ENTRYm_field32_set(unit, &mpls_entry, BFD_ENABLEf, 0);
   2727 
   2728         SOC_IF_ERROR_RETURN(soc_mem_write(unit, MPLS_ENTRYm,
   2729                                           MEM_BLOCK_ANY,
   2730                                           mpls_index, &mpls_entry));
   2731 
   2732         bcm_tr_mpls_unlock (unit);
   2733 
   2734         if (BCM_SUCCESS(_bcm_en_oam_bhh_find_l2x_entry(unit,
   2735 						       endpoint_p->label,
   2736 						       4, 1,
   2737 						       &l2_index, &l2_entry))) {
   2738             soc_mem_delete_index(unit, L2Xm, MEM_BLOCK_ANY, l2_index);
   2739 
   2740         } else {
   2741             return BCM_E_PARAM;
   2742         }
   2743 #endif /* BCM_TRIUMPH_SUPPORT &&  BCM_MPLS_SUPPORT */
   2744         break;
   2745 
   2746     default:
   2747         break;
   2748     }
   2749 
   2750     return rv;
   2751 }
   2752 
   2753 /*
   2754  * Function:
   2755  *      _bcm_en_oam_bhh_msg_send_receive
   2756  * Purpose:
   2757  *      Sends given BHH control message to the uController.
   2758  *      Receives and verifies expected reply.
   2759  *      Performs DMA operation if required.
   2760  * Parameters:
   2761  *      unit        - (IN) Unit number.
   2762  *      s_subclass  - (IN) BHH message subclass.
   2763  *      s_len       - (IN) Value for 'len' field in message struct.
   2764  *                         Length of buffer to flush if DMA send is required.
   2765  *      s_data      - (IN) Value for 'data' field in message struct.
   2766  *                         Ignored if message requires a DMA send/receive
   2767  *                         operation.
   2768  *      r_subclass  - (IN) Expected reply message subclass.
   2769  *      r_len       - (OUT) Returns value in 'len' reply message field.
   2770  * Returns:
   2771  *      BCM_E_XXX
   2772  * Notes:
   2773  *     - The uc_msg 'len' and 'data' fields of mos_msg_data_t
   2774  *       can take any arbitrary data.
   2775  *
   2776  *     BHH Long Control message:
   2777  *     - BHH control messages that require send/receive of information
   2778  *       that cannot fit in the uc_msg 'len' and 'data' fields need to
   2779  *       use DMA operations to exchange information (long control message).
   2780  *
   2781  *     - BHH convention for long control messages for
   2782  *        'mos_msg_data_t' fields:
   2783  *          'len'    size of the DMA buffer to send to uController
   2784  *          'data'   physical DMA memory address to send or receive
   2785  *
   2786  *      DMA Operations:
   2787  *      - DMA read/write operation is performed when a long BHH control
   2788  *        message is involved.
   2789  *
   2790  *      - Messages that require DMA operation (long control message)
   2791  *        is indicated by MOS_MSG_DMA_MSG().
   2792  *
   2793  *      - Callers must 'pack' and 'unpack' corresponding information
   2794  *        into/from DMA buffer indicated by BHH_INFO(unit)->dma_buffer.
   2795  */
   2796 STATIC int
   2797 _bcm_en_oam_bhh_msg_send_receive(int unit, uint8 s_subclass,
   2798                              uint16 s_len, uint32 s_data,
   2799                              uint8 r_subclass, uint16 *r_len)
   2800 {
   2801     int rv = BCM_E_NONE;
   2802      _bcm_oam_info_t *oam_info_p;
   2803     mos_msg_data_t send, reply;
   2804     uint8 *dma_buffer;
   2805     int dma_buffer_len;
   2806     uint32 uc_rv;
   2807 
   2808     SET_OAM_INFO;
   2809 
   2810     sal_memset(&send, 0, sizeof(send));
   2811     sal_memset(&reply, 0, sizeof(reply));
   2812     send.s.mclass = MOS_MSG_CLASS_BHH;
   2813     send.s.subclass = s_subclass;
   2814     send.s.len = bcm_htons(s_len);
   2815 
   2816     /*
   2817      * Set 'data' to DMA buffer address if a DMA operation is
   2818      * required for send or receive.
   2819      */
   2820     dma_buffer = oam_info_p->dma_buffer;
   2821     dma_buffer_len = oam_info_p->dma_buffer_len;
   2822     if (MOS_MSG_DMA_MSG(s_subclass) ||
   2823         MOS_MSG_DMA_MSG(r_subclass)) {
   2824         send.s.data = bcm_htonl(soc_cm_l2p(unit, dma_buffer));
   2825     } else {
   2826         send.s.data = bcm_htonl(s_data);
   2827     }
   2828 
   2829     /* Flush DMA memory */
   2830     if (MOS_MSG_DMA_MSG(s_subclass)) {
   2831         soc_cm_sflush(unit, dma_buffer, s_len);
   2832     }
   2833 
   2834     /* Invalidate DMA memory to read */
   2835     if (MOS_MSG_DMA_MSG(r_subclass)) {
   2836         soc_cm_sinval(unit, dma_buffer, dma_buffer_len);
   2837     }
   2838 
   2839     rv = soc_cmic_uc_msg_send_receive(unit, oam_info_p->uc_num,
   2840                                       &send, &reply,
   2841                                       _BHH_UC_MSG_TIMEOUT_USECS);
   2842 
   2843     /* Check reply class, subclass */
   2844     if ((rv != SOC_E_NONE) ||
   2845         (reply.s.mclass != MOS_MSG_CLASS_BHH) ||
   2846         (reply.s.subclass != r_subclass)) {
   2847         return BCM_E_INTERNAL;
   2848     }
   2849 
   2850     /* Convert BHH uController error code to BCM */
   2851     uc_rv = bcm_ntohl(reply.s.data);
   2852     switch(uc_rv) {
   2853     case SHR_BHH_UC_E_NONE:
   2854         rv = BCM_E_NONE;
   2855         break;
   2856     case SHR_BHH_UC_E_INTERNAL:
   2857         rv = BCM_E_INTERNAL;
   2858         break;
   2859     case SHR_BHH_UC_E_MEMORY:
   2860         rv = BCM_E_MEMORY;
   2861         break;
   2862     case SHR_BHH_UC_E_PARAM:
   2863         rv = BCM_E_PARAM;
   2864         break;
   2865     case SHR_BHH_UC_E_RESOURCE:
   2866         rv = BCM_E_RESOURCE;
   2867         break;
   2868     case SHR_BHH_UC_E_EXISTS:
   2869         rv = BCM_E_EXISTS;
   2870         break;
   2871     case SHR_BHH_UC_E_NOT_FOUND:
   2872         rv = BCM_E_NOT_FOUND;
   2873         break;
   2874     case SHR_BHH_UC_E_INIT:
   2875         rv = BCM_E_INIT;
   2876         break;
   2877     default:
   2878         rv = BCM_E_INTERNAL;
   2879         break;
   2880     }
   2881         
   2882     *r_len = bcm_ntohs(reply.s.len);
   2883 
   2884     return rv;
   2885 }
   2886 
   2887 STATIC uint8 *
   2888 _bcm_en_oam_bhh_ach_header_pack(uint8 *buffer, _ach_header_t *ach)
   2889 {
   2890     uint32  tmp;
   2891 
   2892     tmp = ((ach->f_nibble & 0xf) << 28) | ((ach->version & 0xf) << 24) |
   2893         (ach->reserved << 16) | ach->channel_type;
   2894 
   2895     _BHH_ENCAP_PACK_U32(buffer, tmp);
   2896 
   2897     return buffer;
   2898 }
   2899 
   2900 STATIC uint8 *
   2901 _bcm_en_oam_bhh_mpls_label_pack(uint8 *buffer, _mpls_label_t *mpls)
   2902 {
   2903     uint32  tmp;
   2904 
   2905     tmp = ((mpls->label & 0xfffff) << 12) | ((mpls->exp & 0x7) << 9) |
   2906         ((mpls->s & 0x1) << 8) | mpls->ttl;
   2907     _BHH_ENCAP_PACK_U32(buffer, tmp);
   2908 
   2909     return buffer;
   2910 }
   2911 
   2912 STATIC uint8 *
   2913 _bcm_en_oam_bhh_l2_header_pack(uint8 *buffer, _l2_header_t *l2)
   2914 {
   2915     uint32  tmp;
   2916     int     i;
   2917 
   2918     for (i = 0; i < _BHH_MAC_ADDR_LENGTH; i++) {
   2919         _BHH_ENCAP_PACK_U8(buffer, l2->dst_mac[i]);
   2920     }
   2921 
   2922     for (i = 0; i < _BHH_MAC_ADDR_LENGTH; i++) {
   2923         _BHH_ENCAP_PACK_U8(buffer, l2->src_mac[i]);
   2924     }
   2925 
   2926     /* Vlan Tag tpid = 0 indicates untagged */
   2927     if (0 != l2->vlan_tag.tpid) {
   2928         tmp =  (l2->vlan_tag.tpid            << 16) |
   2929               ((l2->vlan_tag.tci.prio & 0x7) << 13) |
   2930               ((l2->vlan_tag.tci.cfi  & 0x1) << 12) |
   2931                (l2->vlan_tag.tci.vid  & 0xfff);
   2932         _BHH_ENCAP_PACK_U32(buffer, tmp);
   2933     }
   2934 
   2935     /*Inner Vlan Tag inner_tpid = 0 indicates single tag  */
   2936     if (0 != l2->vlan_tag_inner.tpid) {
   2937         tmp = (l2->vlan_tag_inner.tpid            << 16) |
   2938              ((l2->vlan_tag_inner.tci.prio & 0x7) << 13) |
   2939              ((l2->vlan_tag_inner.tci.cfi  & 0x1) << 12) |
   2940               (l2->vlan_tag_inner.tci.vid  & 0xfff);
   2941         _BHH_ENCAP_PACK_U32(buffer, tmp);
   2942     }
   2943     _BHH_ENCAP_PACK_U16(buffer, l2->etype);
   2944 
   2945     return (buffer);
   2946 }
   2947 
   2948 /*
   2949  * Function:
   2950  *      bcm_en_oam_mpls_tp_channel_type_tx_get
   2951  * Purpose:
   2952  *      Get MPLS TP(BHH) ACH Channel type
   2953  * Parameters:
   2954  *      unit                (IN)  BCM device number
   2955  *      channel_type        (IN)  Channel type is ignored in XGS devices
   2956  *      Value               (OUT) User define MPLS TP(BHH) ACH channel type
   2957  *
   2958  * Returns:
   2959  *      BCM_E_NONE          No error
   2960  *      BCM_E_XXXX          Error
   2961  */
   2962 int
   2963 bcm_en_oam_mpls_tp_channel_type_tx_get(int unit,
   2964                                         bcm_oam_mpls_tp_channel_type_t channel_type,
   2965                                         int *value)
   2966 {
   2967     *value = en_oam_mpls_tp_ach_channel_type;
   2968     return BCM_E_NONE;
   2969 }
   2970 
   2971 /*
   2972  * Function:
   2973  *      bcm_en_oam_mpls_tp_channel_type_tx_set
   2974  * Purpose:
   2975  *      Update MPLS TP(BHH) ACH Channel type with user defined value
   2976  * Parameters:
   2977  *      unit                (IN) BCM device number
   2978  *      channel_type        (IN) Channel type is ignored in XGS devices
   2979  *      Value               (IN) User define MPLS TP(BHH) ACH channel type
   2980  *
   2981  * Returns:
   2982  *      BCM_E_NONE          No error
   2983  *      BCM_E_XXXX          Error
   2984  */
   2985 int
   2986 bcm_en_oam_mpls_tp_channel_type_tx_set(int unit,
   2987                                         bcm_oam_mpls_tp_channel_type_t channel_type,
   2988                                         int value)
   2989 {
   2990     uint8               *buffer, *buffer_ptr;
   2991     uint16              buffer_len, reply_len;
   2992     int                 rv = BCM_E_NONE;
   2993     _bcm_oam_info_t     *oam_info_p;
   2994     uint32              *msg;
   2995 
   2996     SET_OAM_INFO;
   2997     CHECK_INIT;
   2998 
   2999     if(oam_info_p->ukernel_not_ready) {
   3000         return BCM_E_INIT;
   3001     }
   3002 
   3003     if ((value != SHR_BHH_ACH_CHANNEL_TYPE) &&
   3004         (value != SHR_BHH_ACH_CHANNEL_TYPE_1)) {
   3005         return BCM_E_CONFIG;
   3006     }
   3007 
   3008     en_oam_mpls_tp_ach_channel_type = value;
   3009     msg = (uint32 *)&en_oam_mpls_tp_ach_channel_type;
   3010 
   3011     /* Pack control message data into DMA buffer */
   3012     buffer     = oam_info_p->dma_buffer;
   3013     buffer_ptr = bhh_sdk_msg_ctrl_ach_channel_type_msg_pack(buffer, msg);
   3014     buffer_len = buffer_ptr - buffer;
   3015 
   3016     rv = _bcm_en_oam_bhh_msg_send_receive(
   3017                                            unit,
   3018                                            MOS_MSG_SUBCLASS_BHH_ACH_CHANNEL_TYPE,
   3019                                            buffer_len, 0,
   3020                                            MOS_MSG_SUBCLASS_BHH_ACH_CHANNEL_TYPE_REPLY,
   3021                                            &reply_len);
   3022 
   3023     if (BCM_FAILURE(rv)) {
   3024         return (rv);
   3025     }
   3026 
   3027     return BCM_E_NONE;
   3028 }
   3029 
   3030 STATIC int
   3031 _bcm_en_oam_bhh_ach_header_get(uint32 packet_flags, _ach_header_t *ach)
   3032 {
   3033     sal_memset(ach, 0, sizeof(*ach));
   3034 
   3035     ach->f_nibble = SHR_BHH_ACH_FIRST_NIBBLE;
   3036     ach->version  = SHR_BHH_ACH_VERSION;
   3037     ach->reserved = 0;
   3038 
   3039     ach->channel_type = en_oam_mpls_tp_ach_channel_type;
   3040 
   3041     return BCM_E_NONE;
   3042 }
   3043 
   3044 STATIC int
   3045 _bcm_en_oam_bhh_mpls_label_get(uint32 label, uint8 exp, uint8 s, uint8 ttl,
   3046                            _mpls_label_t *mpls)
   3047 {
   3048     sal_memset(mpls, 0, sizeof(*mpls));
   3049 
   3050     mpls->label = label;
   3051     mpls->exp   = exp & 0x07;
   3052     mpls->s     = s;
   3053     if(ttl)
   3054         mpls->ttl   = ttl;
   3055     else
   3056         mpls->ttl   = _BHH_MPLS_DFLT_TTL;
   3057 
   3058     return BCM_E_NONE;
   3059 }
   3060 
   3061 STATIC int
   3062 _bcm_en_oam_bhh_mpls_gal_label_get(_mpls_label_t *mpls, uint8 oam_exp)
   3063 {
   3064     return _bcm_en_oam_bhh_mpls_label_get(SHR_BHH_MPLS_GAL_LABEL,
   3065                                       oam_exp, 1, 1, mpls);
   3066 }
   3067 
   3068 STATIC int
   3069 _bcm_en_oam_bhh_mpls_labels_get(int unit, _bcm_oam_endpoint_t *endpoint_p,
   3070                                 uint32 packet_flags,
   3071                                 int max_count,
   3072                                 _mpls_label_t *pw_label,
   3073                                 _mpls_label_t *mpls,
   3074                                 int *mpls_count, bcm_if_t *l3_intf_id)
   3075 {
   3076     int count = 0;
   3077     bcm_l3_egress_t l3_egress;
   3078     bcm_mpls_port_t mpls_port;
   3079     bcm_mpls_egress_label_t label_array[_BHH_MPLS_MAX_LABELS];
   3080     bcm_mpls_egress_label_t tmp_label;
   3081     int label_count;
   3082     int i = 0;
   3083 
   3084     /* Get L3 objects */
   3085     bcm_l3_egress_t_init(&l3_egress);
   3086     if (BCM_FAILURE(bcm_esw_l3_egress_get(unit, endpoint_p->egress_if, &l3_egress))) {
   3087         return BCM_E_PARAM;
   3088     }
   3089 
   3090     /* Look for a tunnel associated with this interface */
   3091     if (BCM_SUCCESS
   3092         (bcm_esw_mpls_tunnel_initiator_get(unit, l3_egress.intf,
   3093                                            _BHH_MPLS_MAX_LABELS,
   3094                                            label_array, &label_count))) {
   3095 
   3096         /* We need to swap the labels configured in tunnel initiator as
   3097          * it returns labels in reverse order than how it should be in pkt.
   3098          */
   3099         for (i = 0; i < (label_count / 2); i++) {
   3100             sal_memcpy(&tmp_label, &label_array[i], sizeof(tmp_label));
   3101             sal_memcpy(&label_array[i], &label_array[label_count - 1 - i],
   3102                        sizeof(tmp_label));
   3103             sal_memcpy(&label_array[label_count - 1 - i], &tmp_label,
   3104                        sizeof(tmp_label));
   3105         }
   3106 
   3107         /* Add VRL Label */
   3108         if (endpoint_p->type == bcmOAMEndpointTypeBHHMPLS) {
   3109             if ((l3_egress.mpls_label != BCM_MPLS_LABEL_INVALID) &&
   3110                 (endpoint_p->egr_label != BCM_MPLS_LABEL_INVALID)  &&
   3111                 (label_count < _BHH_MPLS_MAX_LABELS) ) {
   3112 
   3113                 label_array[label_count].label = l3_egress.mpls_label;
   3114                 label_array[label_count].exp = l3_egress.mpls_exp;
   3115                 label_array[label_count].ttl = l3_egress.mpls_ttl;
   3116                 label_count++;
   3117             }
   3118             /* Traverse through Label stack and match on control label, this
   3119              * label should be the one just above GAL in the label stack, any
   3120              * following labels should not be added.
   3121              */
   3122             for (i = 0;  i < label_count; i++) {
   3123                 if (label_array[i].label == endpoint_p->egr_label) {
   3124                     label_count = i + 1;
   3125                     label_array[i].exp = endpoint_p->egr_label_exp;
   3126                     if (soc_property_get(unit, spn_MPLS_OAM_EGRESS_LABEL_TTL, 0) &&
   3127                         endpoint_p->egr_label_ttl) {
   3128                         label_array[i].ttl = endpoint_p->egr_label_ttl;
   3129                     }
   3130                     break;
   3131                 }
   3132             }
   3133         }
   3134     }
   3135 
   3136         /* MPLS Router Alert */
   3137     if (packet_flags & _BHH_ENCAP_PKT_MPLS_ROUTER_ALERT) {
   3138         /* Ignore overrun error as RAL is only added for PW MEPs and so overrun
   3139          * condition will not exist.
   3140          */
   3141         /* coverity[overrun-local] */
   3142         label_array[label_count].label = SHR_BHH_MPLS_ROUTER_ALERT_LABEL;
   3143         label_array[label_count].exp = 0;
   3144         label_array[label_count].ttl = 0;
   3145         label_count++;
   3146     }
   3147 
   3148     /* Use GPORT to resolve interface */
   3149     if (BCM_GPORT_IS_MPLS_PORT(endpoint_p->gport)) {
   3150         /* Get mpls port and label info */
   3151         bcm_mpls_port_t_init(&mpls_port);
   3152         mpls_port.mpls_port_id = endpoint_p->gport;
   3153         if (BCM_FAILURE(bcm_esw_mpls_port_get(unit, endpoint_p->vpn,
   3154                                               &mpls_port))) {
   3155             return BCM_E_PARAM;
   3156         }
   3157         if (endpoint_p->type == bcmOAMEndpointTypeBHHMPLSVccv &&
   3158             endpoint_p->vccv_type == bcmOamBhhVccvTtl) {
   3159             mpls_port.egress_label.ttl = 0x1;
   3160         }
   3161         label_array[label_count].label = mpls_port.egress_label.label;
   3162         if (endpoint_p->egr_label == mpls_port.egress_label.label) {
   3163             label_array[label_count].exp = endpoint_p->egr_label_exp;
   3164             if (soc_property_get(unit, spn_MPLS_OAM_EGRESS_LABEL_TTL, 0) &&
   3165                 endpoint_p->egr_label_ttl) {
   3166                 label_array[label_count].ttl = endpoint_p->egr_label_ttl;
   3167             }
   3168         } else {
   3169             label_array[label_count].exp   = mpls_port.egress_label.exp;
   3170             label_array[label_count].ttl   = mpls_port.egress_label.ttl;
   3171         }
   3172         label_count++;
   3173     }
   3174 
   3175     for (i=0;  i < label_count; i++) {
   3176         _bcm_en_oam_bhh_mpls_label_get(label_array[i].label,
   3177                                         label_array[i].exp,
   3178                                         0,
   3179                                         label_array[i].ttl,
   3180                                         &mpls[count++]);
   3181     }
   3182 
   3183     /* Set Bottom of Stack if there is no GAL label */
   3184     if (!(packet_flags & _BHH_ENCAP_PKT_GAL)) {
   3185         mpls[count - 1].s = 1;
   3186     }
   3187 
   3188     *mpls_count = count;
   3189 
   3190     return BCM_E_NONE;
   3191 
   3192 }
   3193 
   3194 STATIC int
   3195 _bcm_en_oam_bhh_l2_header_get(int unit, _bcm_oam_endpoint_t *endpoint_p,
   3196                           bcm_port_t port, uint16 etype,
   3197                           _l2_header_t *l2)
   3198 {
   3199     uint16 tpid;
   3200     bcm_l3_egress_t l3_egress;
   3201     bcm_l3_intf_t l3_intf;
   3202     bcm_vlan_control_vlan_t vc;
   3203     int tpid_select;
   3204     bcm_pbmp_t pbmp, ubmp;
   3205 
   3206     sal_memset(l2, 0, sizeof(*l2));
   3207     /* Get L3 interfaces */
   3208     bcm_l3_egress_t_init(&l3_egress);
   3209     bcm_l3_intf_t_init(&l3_intf);
   3210 
   3211     if (BCM_FAILURE
   3212         (bcm_esw_l3_egress_get(unit, endpoint_p->egress_if, &l3_egress))) {
   3213         return (BCM_E_PARAM);
   3214     }
   3215 
   3216     l3_intf.l3a_intf_id = l3_egress.intf;
   3217     if (BCM_FAILURE(bcm_esw_l3_intf_get(unit, &l3_intf))) {
   3218         return (BCM_E_PARAM);
   3219     }
   3220 
   3221     /* Get TPID */
   3222     BCM_IF_ERROR_RETURN(bcm_esw_vlan_control_port_get(unit,
   3223                                                       port,
   3224                                                       bcmVlanPortOuterTpidSelect,
   3225                                                       &tpid_select));
   3226     if (tpid_select == BCM_PORT_OUTER_TPID) {
   3227         BCM_IF_ERROR_RETURN(bcm_esw_port_tpid_get(unit, port, &tpid));
   3228     } else {
   3229         BCM_IF_ERROR_RETURN(
   3230                      bcm_esw_vlan_control_vlan_get(unit, l3_intf.l3a_vid, &vc));
   3231         tpid = vc.outer_tpid;
   3232     }
   3233 
   3234     sal_memcpy(l2->dst_mac, l3_egress.mac_addr, _BHH_MAC_ADDR_LENGTH);
   3235     sal_memcpy(l2->src_mac, l3_intf.l3a_mac_addr, _BHH_MAC_ADDR_LENGTH);
   3236     l2->vlan_tag.tpid     = tpid;
   3237     l2->vlan_tag.tci.prio = endpoint_p->vlan_pri;
   3238     l2->vlan_tag.tci.cfi  = 0;
   3239     l2->vlan_tag.tci.vid  = l3_intf.l3a_vid;
   3240 
   3241     BCM_IF_ERROR_RETURN(bcm_esw_vlan_port_get(unit,
   3242                                               l2->vlan_tag.tci.vid,
   3243                                               &pbmp,
   3244                                               &ubmp));
   3245     if (BCM_PBMP_MEMBER(ubmp, port)) {
   3246         l2->vlan_tag.tpid = 0;  /* Set to 0 to indicate untagged */
   3247     }
   3248 
   3249     if (l3_intf.l3a_inner_vlan != 0) {
   3250         BCM_IF_ERROR_RETURN(bcm_esw_port_inner_tpid_get(unit, port, &tpid));
   3251         l2->vlan_tag_inner.tpid     = tpid;
   3252         l2->vlan_tag_inner.tci.prio = endpoint_p->inner_vlan_pri;
   3253         l2->vlan_tag_inner.tci.cfi  = 0;
   3254         l2->vlan_tag_inner.tci.vid  = l3_intf.l3a_inner_vlan;
   3255     }
   3256     l2->etype             = etype;
   3257 
   3258     return BCM_E_NONE;
   3259 }
   3260 /*
   3261  * Function:
   3262  *      _bcm_en_oam_bhh_encap_build_pack
   3263  * Purpose:
   3264  *      Builds and packs the BHH packet encapsulation for a given
   3265  *      BHH tunnel type.
   3266  * Parameters:
   3267  *      unit            - (IN) Unit number.
   3268  *      port            - (IN) Port.
   3269  *      endpoint_config - (IN/OUT) Pointer to BHH endpoint structure.
   3270  *      packet_flags    - (IN) Flags for building packet.
   3271  *      buffer          - (OUT) Buffer returning BHH encapsulation.
   3272  * Returns:
   3273  *      BCM_E_XXX
   3274  * Notes:
   3275  *      The returning BHH encapsulation includes only all the
   3276  *      encapsulation headers/labels and does not include
   3277  *      the BHH control packet.
   3278  */
   3279 STATIC int
   3280 _bcm_en_oam_bhh_encap_build_pack(int unit, bcm_port_t port,
   3281                              _bcm_oam_endpoint_t *endpoint_p,
   3282                              uint32 packet_flags,
   3283                              uint8 *buffer,
   3284 			     uint32 *encap_length)
   3285 {
   3286     uint8          *cur_ptr = buffer;
   3287     uint16         etype = 0;
   3288     bcm_if_t       l3_intf_id = -1;
   3289     _ach_header_t  ach;
   3290     _mpls_label_t  mpls_gal;
   3291     _mpls_label_t  mpls_labels[_BHH_MPLS_MAX_LABELS];
   3292     _mpls_label_t  pw_label;
   3293     int            mpls_count = 0;
   3294     _l2_header_t   l2;
   3295     int i;
   3296 
   3297 
   3298     /*
   3299      * Get necessary headers/labels information.
   3300      *
   3301      * Following order is important since some headers/labels
   3302      * may depend on previous header/label information.
   3303      */
   3304     if (packet_flags & _BHH_ENCAP_PKT_G_ACH) {
   3305         BCM_IF_ERROR_RETURN
   3306             (_bcm_en_oam_bhh_ach_header_get(packet_flags, &ach));
   3307     }
   3308 
   3309     if (packet_flags & _BHH_ENCAP_PKT_GAL) {
   3310         if (endpoint_p->egr_label == SHR_BHH_MPLS_GAL_LABEL) {
   3311             BCM_IF_ERROR_RETURN
   3312                 (_bcm_en_oam_bhh_mpls_gal_label_get(&mpls_gal,
   3313                                                     endpoint_p->egr_label_exp));
   3314         } else {
   3315             BCM_IF_ERROR_RETURN
   3316                 (_bcm_en_oam_bhh_mpls_gal_label_get(&mpls_gal, 0));
   3317         }
   3318     }
   3319 
   3320     if (packet_flags & _BHH_ENCAP_PKT_MPLS) {
   3321         etype = SHR_BHH_L2_ETYPE_MPLS_UCAST;
   3322         BCM_IF_ERROR_RETURN
   3323             (_bcm_en_oam_bhh_mpls_labels_get(unit, endpoint_p,
   3324                                              packet_flags,    
   3325                                              _BHH_MPLS_MAX_LABELS,
   3326                                              &pw_label,
   3327                                              mpls_labels, 
   3328                                              &mpls_count,
   3329                                              &l3_intf_id));
   3330     }
   3331 
   3332     /* Always build L2 Header */
   3333     BCM_IF_ERROR_RETURN
   3334         (_bcm_en_oam_bhh_l2_header_get(unit, 
   3335                                        endpoint_p,
   3336                                        port, 
   3337                                        etype, 
   3338                                        &l2));
   3339 
   3340 
   3341     /*
   3342      * Pack header/labels into given buffer (network packet format).
   3343      *
   3344      * Following packing order must be followed to correctly
   3345      * build the packet encapsulation.
   3346      */
   3347     cur_ptr = buffer;
   3348 
   3349     /* L2 Header is always present */
   3350     cur_ptr = _bcm_en_oam_bhh_l2_header_pack(cur_ptr, &l2);
   3351 
   3352     if (packet_flags & _BHH_ENCAP_PKT_MPLS) {
   3353 	for (i = 0;i < mpls_count;i++) {
   3354 	    cur_ptr = _bcm_en_oam_bhh_mpls_label_pack(cur_ptr, &mpls_labels[i]);
   3355 	}
   3356     }
   3357     if (packet_flags & _BHH_ENCAP_PKT_GAL) {    
   3358         cur_ptr = _bcm_en_oam_bhh_mpls_label_pack(cur_ptr, &mpls_gal);
   3359     }
   3360 
   3361     if (packet_flags & _BHH_ENCAP_PKT_G_ACH) {
   3362         cur_ptr = _bcm_en_oam_bhh_ach_header_pack(cur_ptr, &ach);
   3363     }
   3364 
   3365 
   3366     /* Set BHH encapsulation length */
   3367     *encap_length = cur_ptr - buffer;
   3368 
   3369     return BCM_E_NONE;
   3370 }
   3371 
   3372 /*
   3373  * Function:
   3374  *      _bcm_en_oam_bhh_encap_data_dump
   3375  * Purpose:
   3376  *      Dumps buffer contents.
   3377  * Parameters:
   3378  *      buffer  - (IN) Buffer to dump data.
   3379  *      length  - (IN) Length of buffer.
   3380  * Returns:
   3381  *      None
   3382  */
   3383 void
   3384 _bcm_en_oam_bhh_encap_data_dump(uint8 *buffer, int length)
   3385 {
   3386     int i;
   3387 
   3388     LOG_CLI((BSL_META("\nBHH encapsulation (length=%d):\n"), length));
   3389 
   3390     for (i = 0; i < length; i++) {
   3391         if ((i % 16) == 0) {
   3392             LOG_CLI((BSL_META("\n")));
   3393         }
   3394         LOG_CLI((BSL_META(" %02x"), buffer[i]));
   3395     }
   3396 
   3397     LOG_CLI((BSL_META("\n")));
   3398     return;
   3399 }
   3400 
   3401 /*
   3402  * Function:
   3403  *      _bcm_en_oam_bhh_encap_create
   3404  * Purpose:
   3405  *      Creates a BHH packet encapsulation.
   3406  * Parameters:
   3407  *      unit            - (IN) Unit number.
   3408  *      port_id         - (IN) Port.
   3409  *      endpoint_config - (IN/OUT) Pointer to BHH endpoint structure.
   3410  *      encap_data      - (OUT) Buffer returning BHH encapsulation.
   3411  * Returns:
   3412  *      BCM_E_XXX
   3413  * Notes:
   3414  *      The returning BHH encapsulation buffer includes all the
   3415  *      corresponding headers/labels EXCEPT for the BHH control packet.
   3416  */
   3417 STATIC int
   3418 _bcm_en_oam_bhh_encap_create(int unit, bcm_port_t port_id,
   3419                          _bcm_oam_endpoint_t *endpoint_p,
   3420                          uint8 *encap_data,
   3421 			 uint8  *encap_type,
   3422 			 uint32 *encap_length)
   3423 {
   3424     uint32 packet_flags;
   3425     _bcm_oam_info_t *oam_info_p;
   3426 
   3427     SET_OAM_INFO;
   3428 
   3429     packet_flags = 0;
   3430 
   3431     /*
   3432      * Get BHH encapsulation packet format flags
   3433      *
   3434      * Also, perform the following for each BHH tunnel type:
   3435      * - Check for valid parameter values
   3436      * - Set specific values required by the BHH tunnel definition 
   3437      *   (e.g. such as ttl=1,...)
   3438      */
   3439     switch (endpoint_p->type) {
   3440     case bcmOAMEndpointTypeBHHMPLS:
   3441         packet_flags |=
   3442             (_BHH_ENCAP_PKT_MPLS |
   3443              _BHH_ENCAP_PKT_GAL |
   3444              _BHH_ENCAP_PKT_G_ACH);
   3445         break;
   3446 
   3447     case bcmOAMEndpointTypeBHHMPLSVccv:
   3448         switch(endpoint_p->vccv_type) {
   3449 
   3450         case bcmOamBhhVccvChannelAch:
   3451             packet_flags |=
   3452                 (_BHH_ENCAP_PKT_MPLS |
   3453                  _BHH_ENCAP_PKT_PW |
   3454                  _BHH_ENCAP_PKT_G_ACH);
   3455         break;
   3456 
   3457         case bcmOamBhhVccvRouterAlert:
   3458             packet_flags |=
   3459                 (_BHH_ENCAP_PKT_MPLS |
   3460                  _BHH_ENCAP_PKT_PW |
   3461                  _BHH_ENCAP_PKT_MPLS_ROUTER_ALERT |
   3462                  _BHH_ENCAP_PKT_G_ACH); 
   3463             break;
   3464 
   3465         case bcmOamBhhVccvTtl:
   3466             packet_flags |=
   3467                 (_BHH_ENCAP_PKT_MPLS |
   3468                  _BHH_ENCAP_PKT_PW |
   3469                  _BHH_ENCAP_PKT_G_ACH); 
   3470             break;
   3471 
   3472 	case bcmOamBhhVccvGal13:
   3473             packet_flags |=
   3474                 (_BHH_ENCAP_PKT_MPLS |
   3475                  _BHH_ENCAP_PKT_PW |
   3476                  _BHH_ENCAP_PKT_GAL  |
   3477                  _BHH_ENCAP_PKT_G_ACH);
   3478             break;
   3479 
   3480 	default:
   3481 	    return BCM_E_PARAM;
   3482 	    break;
   3483 	}
   3484         break;
   3485 
   3486     default:
   3487         return BCM_E_PARAM;
   3488     }
   3489 
   3490     /* Build header/labels and pack in buffer */
   3491     BCM_IF_ERROR_RETURN
   3492         (_bcm_en_oam_bhh_encap_build_pack(unit, port_id,
   3493                                       endpoint_p,
   3494                                       packet_flags,
   3495                                       encap_data,
   3496 	                              encap_length));
   3497 
   3498     /* Set encap type (indicates uC side that checksum is required) */
   3499     *encap_type = SHR_BHH_ENCAP_TYPE_RAW;
   3500 #ifdef _BHH_DEBUG_DUMP
   3501     _bcm_en_oam_bhh_encap_data_dump(encap_data, *encap_length);
   3502 #endif
   3503 
   3504     if (*encap_length > oam_info_p->bhh_max_encap_length) {
   3505         LOG_ERROR(BSL_LS_BCM_OAM,
   3506                 (BSL_META_U(unit,
   3507                 "OAM(unit %d) Error: Encap length greater than max,"
   3508                 "encap_length=%u max=%u\n"),
   3509                  unit, *encap_length, oam_info_p->bhh_max_encap_length));
   3510         return BCM_E_CONFIG;
   3511     }
   3512 
   3513     return BCM_E_NONE;
   3514 }
   3515     
   3516 /*
   3517  * Function:
   3518  *      _bcm_en_oam_bhh_encap_hw_set
   3519  * Purpose:
   3520  *      Sets BHH encapsulation type in HW device.
   3521  * Parameters:
   3522  *      unit            - (IN) Unit number.
   3523  *      module_id       - (IN) Module id.
   3524  *      port_id         - (IN) Port.
   3525  *      is_local        - (IN) Indicates if module id is local.
   3526  *      endpoint_config - (IN) Pointer to BHH endpoint structure.
   3527  * Returns:
   3528  *      BCM_E_XXX
   3529  * Notes:
   3530  */
   3531 STATIC int
   3532 _bcm_en_oam_bhh_encap_hw_set(int unit, _bcm_oam_endpoint_t *endpoint_p,
   3533                          bcm_module_t module_id, bcm_port_t port_id,
   3534 			     int is_local, bcm_cos_t int_pri)
   3535 {
   3536     int rv = BCM_E_NONE;
   3537     l2x_entry_t l2_entry;
   3538     _bcm_oam_info_t *oam_info_p;
   3539 #if defined(BCM_TRIUMPH_SUPPORT) && defined(BCM_MPLS_SUPPORT)
   3540     bcm_l3_egress_t l3_egress;
   3541     int ingress_if;
   3542     int i;
   3543     int num_entries;
   3544     mpls_entry_entry_t mpls_entry;
   3545     mpls_entry_entry_t mpls_key;
   3546     int vccv_type = 0;
   3547     int mpls_index = 0;
   3548 #endif /* BCM_TRIUMPH_SUPPORT &&  BCM_MPLS_SUPPORT */
   3549 
   3550     SET_OAM_INFO;
   3551 
   3552     COMPILER_REFERENCE(oam_info_p);
   3553 
   3554     switch(endpoint_p->type) {
   3555     case bcmOAMEndpointTypeBHHMPLS:
   3556     case bcmOAMEndpointTypeBHHMPLSVccv:
   3557 
   3558 #if defined(BCM_TRIUMPH_SUPPORT) && defined(BCM_MPLS_SUPPORT)
   3559 
   3560         /* Insert mpls label field to L2_ENTRY table. */
   3561         sal_memset(&l2_entry, 0, sizeof(l2_entry));
   3562         
   3563         soc_mem_field32_set(unit, L2Xm, &l2_entry, KEY_TYPEf, 4);
   3564         soc_mem_field32_set(unit, L2Xm, &l2_entry, SESSION_IDENTIFIER_TYPEf,
   3565                             1);
   3566         soc_mem_field32_set(unit, L2Xm, &l2_entry, LABELf,
   3567                             endpoint_p->label);
   3568         soc_mem_field32_set(unit, L2Xm, &l2_entry, VALIDf, 1);
   3569 
   3570         if (!is_local) {
   3571             /* Set BHH_REMOTE = 1, DST_MOD, DST_PORT */
   3572             soc_mem_field32_set(unit, L2Xm, &l2_entry, BFD_REMOTEf, 1);
   3573             soc_mem_field32_set(unit, L2Xm, &l2_entry, BFD_DST_MODf,
   3574                                 module_id);
   3575             soc_mem_field32_set(unit, L2Xm, &l2_entry, BFD_DST_PORTf,
   3576                                 port_id);
   3577             soc_mem_field32_set(unit, L2Xm, &l2_entry, BFD_INT_PRIf,
   3578                                 int_pri);
   3579         } else {
   3580             soc_mem_field32_set(unit, L2Xm, &l2_entry, BFD_CPU_QUEUE_CLASSf,
   3581                                 endpoint_p->cpu_qid);
   3582         }
   3583 
   3584         soc_mem_insert(unit, L2Xm, MEM_BLOCK_ANY, &l2_entry);
   3585 
   3586         SOC_IF_ERROR_RETURN(bcm_tr_mpls_lock (unit));
   3587 
   3588         sal_memset(&mpls_key, 0, sizeof(mpls_key));
   3589         soc_MPLS_ENTRYm_field32_set(unit, &mpls_key, MPLS_LABELf,
   3590                                     endpoint_p->label);
   3591 
   3592         SOC_IF_ERROR_RETURN(soc_mem_search(unit, MPLS_ENTRYm,
   3593                                            MEM_BLOCK_ANY, &mpls_index,
   3594                                            &mpls_key, &mpls_entry, 0));
   3595 
   3596         if ((soc_MPLS_ENTRYm_field32_get(unit, &mpls_entry,
   3597                                          VALIDf) != 0x1)) {
   3598             bcm_tr_mpls_unlock (unit);
   3599             return BCM_E_PARAM;
   3600         }
   3601 
   3602         if (endpoint_p->type == bcmOAMEndpointTypeBHHMPLSVccv) {
   3603             /* Get the control channel type */
   3604             vccv_type = soc_MPLS_ENTRYm_field32_get(unit, &mpls_entry,
   3605                                                     MPLS__PW_CC_TYPEf);
   3606 
   3607             if (vccv_type == 0) { /* No VCCV type configured */
   3608                 soc_MPLS_ENTRYm_field32_set(unit, &mpls_entry,
   3609                                             MPLS__PW_CC_TYPEf,
   3610                                             (endpoint_p->vccv_type + 1));
   3611 
   3612             } else if (vccv_type != (endpoint_p->vccv_type + 1)) {
   3613                 /* Endpoint add configuration conflicts with MPLS
   3614                  * port add config
   3615                  */
   3616                 bcm_tr_mpls_unlock(unit);
   3617                 return BCM_E_PARAM;
   3618             }
   3619         }
   3620 
   3621 
   3622         soc_MPLS_ENTRYm_field32_set(unit, &mpls_entry,
   3623                                     SESSION_IDENTIFIER_TYPEf, 1);
   3624         soc_MPLS_ENTRYm_field32_set(unit, &mpls_entry, BFD_ENABLEf, 1);
   3625         rv = soc_mem_write(unit, MPLS_ENTRYm,
   3626                                           MEM_BLOCK_ANY, mpls_index,
   3627                                           &mpls_entry);
   3628         if (rv != SOC_E_NONE) {
   3629             bcm_tr_mpls_unlock(unit);
   3630             return rv;
   3631         }
   3632 
   3633 
   3634         /*
   3635          * PW CC-3
   3636          *
   3637          * Set MPLS entry DECAP_USE_TTL=0 for corresponding
   3638          * Tunnel Terminator label.
   3639          */
   3640         if (endpoint_p->type == bcmOAMEndpointTypeBHHMPLSVccv) {
   3641             if (endpoint_p->vccv_type == bcmOamBhhVccvTtl) {
   3642                 rv = bcm_esw_l3_egress_get(unit, endpoint_p->egress_if,
   3643                                            &l3_egress);
   3644                 if (rv != BCM_E_NONE) {
   3645                     bcm_tr_mpls_unlock(unit);
   3646                     return rv;
   3647                 }
   3648 
   3649                 /* Look for Tunnel Terminator label */
   3650                 num_entries = soc_mem_index_count(unit, MPLS_ENTRYm);
   3651                 for (i = 0; i < num_entries; i++) {
   3652                     rv = READ_MPLS_ENTRYm(unit, MEM_BLOCK_ANY, i, &mpls_entry);
   3653                     if (rv != SOC_E_NONE) {
   3654                         bcm_tr_mpls_unlock(unit);
   3655                         return rv;
   3656                     }
   3657 
   3658                     if (!soc_MPLS_ENTRYm_field32_get(unit, &mpls_entry, VALIDf)) {
   3659                         continue;
   3660                     }
   3661                     if (soc_MPLS_ENTRYm_field32_get(unit, &mpls_entry,
   3662                                                     MPLS_ACTION_IF_BOSf) == 0x1) {
   3663                         continue;    /* L2_SVP */
   3664                     }
   3665 
   3666                     ingress_if = soc_MPLS_ENTRYm_field32_get(unit, &mpls_entry,
   3667                                                              L3_IIFf);
   3668                     if (ingress_if == l3_egress.intf) {
   3669                         /* Label found */
   3670                         soc_MPLS_ENTRYm_field32_set(unit, &mpls_entry,
   3671                                                     DECAP_USE_TTLf, 0);
   3672                         rv = soc_mem_write(unit, MPLS_ENTRYm,
   3673                                            MEM_BLOCK_ALL, i,
   3674                                            &mpls_entry);
   3675                         if (rv != SOC_E_NONE) {
   3676                             bcm_tr_mpls_unlock(unit);
   3677                             return rv;
   3678                         }
   3679                         break;
   3680                     }
   3681                 }
   3682             }
   3683         }
   3684 
   3685         bcm_tr_mpls_unlock (unit);
   3686 #endif /* BCM_TRIUMPH_SUPPORT &&  BCM_MPLS_SUPPORT */
   3687         break;
   3688 
   3689     default:
   3690         rv = BCM_E_UNAVAIL;
   3691         break;
   3692         }
   3693 
   3694     return rv;
   3695 }
   3696 
   3697 /* BHH Event Handler */
   3698 typedef struct _event_handler_s {
   3699     struct _event_handler_s *next;
   3700     bcm_oam_event_types_t event_types;
   3701     bcm_oam_event_cb cb;
   3702     void *user_data;
   3703 } _event_handler_t;
   3704 
   3705 /*
   3706  * Function:
   3707  *      _bcm_en_oam_bhh_event_mask_set
   3708  * Purpose:
   3709  *      Set the BHH Events mask.
   3710  *      Events are set per BHH module.
   3711  * Parameters:
   3712  *      unit        - (IN) Unit number.
   3713  * Returns:
   3714  *      BCM_E_NONE Operation completed successfully
   3715  *      BCM_E_XXX  Operation failed
   3716  * Notes:
   3717  */
   3718 STATIC int
   3719 _bcm_en_oam_bhh_event_mask_set(int unit)
   3720 {
   3721     _bcm_oam_info_t *oam_info_p;
   3722     _bcm_oam_event_handler_t *event_handler_p;
   3723     uint32 event_mask = 0;
   3724     uint16 reply_len;
   3725 
   3726     SET_OAM_INFO;
   3727 
   3728     /* Get event mask from all callbacks */
   3729     for (event_handler_p = oam_info_p->event_handler_list_p;
   3730          event_handler_p != NULL;
   3731          event_handler_p = event_handler_p->next_p) {
   3732 
   3733         if (SHR_BITGET(event_handler_p->event_types.w,
   3734                        bcmOAMEventBHHLBTimeout)) {
   3735             event_mask |= BHH_BTE_EVENT_LB_TIMEOUT;
   3736         }
   3737         if (SHR_BITGET(event_handler_p->event_types.w,
   3738                        bcmOAMEventBHHLBDiscoveryUpdate)) {
   3739             event_mask |= BHH_BTE_EVENT_LB_DISCOVERY_UPDATE;
   3740         }
   3741         if (SHR_BITGET(event_handler_p->event_types.w,
   3742                        bcmOAMEventBHHCCMTimeout)) {
   3743             event_mask |= BHH_BTE_EVENT_CCM_TIMEOUT;
   3744         }
   3745         if (SHR_BITGET(event_handler_p->event_types.w,
   3746                        bcmOAMEventBHHCCMState)) {
   3747             event_mask |= BHH_BTE_EVENT_STATE;
   3748         }
   3749         if (SHR_BITGET(event_handler_p->event_types.w,
   3750                        bcmOAMEventBHHCCMTimeoutClear)) {
   3751             event_mask |= BHH_BTE_EVENT_CCM_TIMEOUT_CLEAR;
   3752         }
   3753         if (SHR_BITGET(event_handler_p->event_types.w,
   3754                        bcmOAMEventBHHCCMRdi)) {
   3755             event_mask |= BHH_BTE_EVENT_CCM_RDI;
   3756         }
   3757         if (SHR_BITGET(event_handler_p->event_types.w,
   3758                        bcmOAMEventBHHCCMUnknownMegLevel)) {
   3759             event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_MEG_LEVEL;
   3760         }
   3761         if (SHR_BITGET(event_handler_p->event_types.w,
   3762                        bcmOAMEventBHHCCMUnknownMegId)) {
   3763             event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_MEG_ID;
   3764         }
   3765         if (SHR_BITGET(event_handler_p->event_types.w,
   3766                        bcmOAMEventBHHCCMUnknownMepId)) {
   3767             event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_MEP_ID;
   3768         }
   3769         if (SHR_BITGET(event_handler_p->event_types.w,
   3770                        bcmOAMEventBHHCCMUnknownPeriod)) {
   3771             event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_PERIOD;
   3772         }
   3773         if (SHR_BITGET(event_handler_p->event_types.w,
   3774                        bcmOAMEventBHHCCMUnknownPriority)) {
   3775             event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_PRIORITY;
   3776         }
   3777         if (SHR_BITGET(event_handler_p->event_types.w,
   3778                        bcmOAMEventBHHCCMRdiClear)) {
   3779             event_mask |= BHH_BTE_EVENT_CCM_RDI_CLEAR;
   3780         }
   3781         if (SHR_BITGET(event_handler_p->event_types.w,
   3782                        bcmOAMEventBHHCCMUnknownMegLevelClear)) {
   3783             event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_MEG_LEVEL_CLEAR;
   3784         }
   3785         if (SHR_BITGET(event_handler_p->event_types.w,
   3786                        bcmOAMEventBHHCCMUnknownMegIdClear)) {
   3787             event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_MEG_ID_CLEAR;
   3788         }
   3789         if (SHR_BITGET(event_handler_p->event_types.w,
   3790                        bcmOAMEventBHHCCMUnknownMepIdClear)) {
   3791             event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_MEP_ID_CLEAR;
   3792         }
   3793         if (SHR_BITGET(event_handler_p->event_types.w,
   3794                        bcmOAMEventBHHCCMUnknownPeriodClear)) {
   3795             event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_PERIOD_CLEAR;
   3796         }
   3797         if (SHR_BITGET(event_handler_p->event_types.w,
   3798                        bcmOAMEventBHHCCMUnknownPriorityClear)) {
   3799             event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_PRIORITY_CLEAR;
   3800         }
   3801         if (SHR_BITGET(event_handler_p->event_types.w, bcmOAMEventCsfLos)) {
   3802             event_mask |= BHH_BTE_EVENT_CSF_LOS;
   3803         }
   3804         if (SHR_BITGET(event_handler_p->event_types.w, bcmOAMEventCsfFdi)) {
   3805             event_mask |= BHH_BTE_EVENT_CSF_FDI;
   3806         }
   3807         if (SHR_BITGET(event_handler_p->event_types.w, bcmOAMEventCsfRdi)) {
   3808             event_mask |= BHH_BTE_EVENT_CSF_RDI;
   3809         }
   3810         if (SHR_BITGET(event_handler_p->event_types.w, bcmOAMEventCsfDci)) {
   3811             event_mask |= BHH_BTE_EVENT_CSF_DCI;
   3812         }
   3813     }
   3814 
   3815     /* Update BHH event mask in uKernel */
   3816     if (event_mask != oam_info_p->event_mask) {
   3817         /* Send BHH Event Mask message to uC */
   3818         BCM_IF_ERROR_RETURN(_bcm_en_oam_bhh_msg_send_receive
   3819 			    (unit,
   3820 			     MOS_MSG_SUBCLASS_BHH_EVENT_MASK_SET,
   3821 			     0, event_mask,
   3822 			     MOS_MSG_SUBCLASS_BHH_EVENT_MASK_SET_REPLY,
   3823 			     &reply_len));
   3824 
   3825         if (reply_len != 0) {
   3826             return BCM_E_INTERNAL;
   3827         }
   3828     }
   3829 
   3830     oam_info_p->event_mask = event_mask;
   3831 
   3832     return BCM_E_NONE;
   3833 }
   3834 
   3835 /*
   3836  * Function:
   3837  *      _bcm_en_oam_bhh_callback_thread
   3838  * Purpose:
   3839  *      Thread to listen for event messages from uController.
   3840  * Parameters:
   3841  *      param - Pointer to BFD info structure.
   3842  * Returns:
   3843  *      None
   3844  */
   3845 STATIC void
   3846 _bcm_en_oam_bhh_callback_thread(void *param)
   3847 {
   3848     int rv;
   3849     _bcm_oam_info_t *oam_info_p = (_bcm_oam_info_t*)param;
   3850     bcm_oam_event_types_t events;
   3851     bcm_oam_event_type_t event_type;
   3852     bhh_msg_event_t event_msg;
   3853     int sess_id;
   3854     uint32 event_mask, flags = 0;
   3855     _bcm_oam_event_handler_t *event_handler_p;
   3856     _bcm_oam_endpoint_t *endpoint_p;
   3857     char thread_name[SAL_THREAD_NAME_MAX_LEN];
   3858 
   3859     thread_name[0] = 0;
   3860     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   3861                 (BSL_META_U(oam_info_p->unit,
   3862                             "BHH callback thread starting\n")));
   3863     sal_thread_name(oam_info_p->event_thread_id, thread_name, sizeof (thread_name));
   3864 
   3865     while (1) {
   3866         /* Wait on notifications from uController */
   3867         rv = soc_cmic_uc_msg_receive(oam_info_p->unit, oam_info_p->uc_num,
   3868                                      MOS_MSG_CLASS_BHH_EVENT, &event_msg,
   3869                                      sal_sem_FOREVER);
   3870 
   3871         if (BCM_FAILURE(rv)) {
   3872             break;  /*  Thread exit */
   3873         } else {
   3874 
   3875             event_handler_p = oam_info_p->event_handler_list_p;
   3876 
   3877 	    /* Get data from event message */
   3878             sess_id =
   3879                 BCM_OAM_BHH_GET_SDK_EP(oam_info_p, ((int)bcm_ntohs(event_msg.s.len)));
   3880 
   3881 	    if (sess_id < 0 ||
   3882 		sess_id >= oam_info_p->endpoint_count) {
   3883 		    LOG_CLI((BSL_META_U(oam_info_p->unit,
   3884                                         "****** Invalid sess_id:%d ******\n"), sess_id));
   3885 	    } else {
   3886 		SET_ENDPOINT(sess_id);
   3887 		event_mask = bcm_ntohl(event_msg.s.data);
   3888         
   3889 		/* Set events */
   3890 		sal_memset(&events, 0, sizeof(events));
   3891 
   3892 		if (event_mask & BHH_BTE_EVENT_LB_TIMEOUT) {
   3893 /*		    LOG_CLI((BSL_META_U(oam_info_p->unit,
   3894                                         "****** OAM BHH LB Timeout ******\n")));*/
   3895 
   3896 		    if (oam_info_p->event_handler_count[bcmOAMEventBHHLBTimeout] > 0)
   3897 			SHR_BITSET(events.w, bcmOAMEventBHHLBTimeout);
   3898 		}
   3899 		if (event_mask & BHH_BTE_EVENT_LB_DISCOVERY_UPDATE) {
   3900 /*		    LOG_CLI((BSL_META_U(oam_info_p->unit,
   3901                                         "****** OAM BHH LB Discovery Update ******\n")));*/
   3902 		    if (oam_info_p->event_handler_count[bcmOAMEventBHHLBDiscoveryUpdate] > 0)
   3903 			SHR_BITSET(events.w, bcmOAMEventBHHLBDiscoveryUpdate);
   3904 		}
   3905 		if (event_mask & BHH_BTE_EVENT_CCM_TIMEOUT) {
   3906 /*		    LOG_CLI((BSL_META_U(oam_info_p->unit,
   3907                                         "****** OAM BHH CCM Timeout ******\n")));*/
   3908 		    if (oam_info_p->event_handler_count[bcmOAMEventBHHCCMTimeout] > 0)
   3909 			SHR_BITSET(events.w, bcmOAMEventBHHCCMTimeout);
   3910 		}
   3911 		if (event_mask & BHH_BTE_EVENT_CCM_TIMEOUT_CLEAR) {
   3912 		    if (oam_info_p->event_handler_count[bcmOAMEventBHHCCMTimeoutClear] > 0)
   3913 			SHR_BITSET(events.w, bcmOAMEventBHHCCMTimeoutClear);
   3914 		}
   3915 		if (event_mask & BHH_BTE_EVENT_STATE) {
   3916 /*		    LOG_CLI((BSL_META_U(oam_info_p->unit,
   3917                                         "****** OAM BHH State ******\n")));*/
   3918 		    if (oam_info_p->event_handler_count[bcmOAMEventBHHCCMState] > 0)
   3919 			SHR_BITSET(events.w, bcmOAMEventBHHCCMState);
   3920 		}
   3921 
   3922         if (event_mask & BHH_BTE_EVENT_CCM_RDI) {
   3923 /*          LOG_CLI((BSL_META_U(oam_info_p->unit,
   3924                                         "****** OAM BHH CCM RDI ******\n")));*/
   3925             if (oam_info_p->event_handler_count[bcmOAMEventBHHCCMRdi] > 0)
   3926             SHR_BITSET(events.w, bcmOAMEventBHHCCMRdi);
   3927         }
   3928         if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_LEVEL) {
   3929 /*          LOG_CLI((BSL_META_U(oam_info_p->unit,
   3930                                         "****** OAM BHH CCM Unknown MEG Level ******\n")));*/
   3931             if (oam_info_p->event_handler_count[bcmOAMEventBHHCCMUnknownMegLevel] > 0)
   3932             SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownMegLevel);
   3933         }
   3934         if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_ID) {
   3935 /*          LOG_CLI((BSL_META_U(oam_info_p->unit,
   3936                                         "****** OAM BHH CCM Unknown MEG ID ******\n")));*/
   3937             if (oam_info_p->event_handler_count[bcmOAMEventBHHCCMUnknownMegId] > 0)
   3938             SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownMegId);
   3939         }
   3940         if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_MEP_ID) {
   3941 /*          LOG_CLI((BSL_META_U(oam_info_p->unit,
   3942                                         "****** OAM BHH CCM Unknown MEP ID ******\n")));*/
   3943             if (oam_info_p->event_handler_count[bcmOAMEventBHHCCMUnknownMepId] > 0)
   3944             SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownMepId);
   3945         }
   3946         if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_PERIOD) {
   3947             if (oam_info_p->event_handler_count[bcmOAMEventBHHCCMUnknownPeriod] > 0)
   3948             SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownPeriod);
   3949         }
   3950         if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_PRIORITY) {
   3951             if (oam_info_p->event_handler_count[bcmOAMEventBHHCCMUnknownPriority] > 0)
   3952             SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownPriority);
   3953         }
   3954         if (event_mask & BHH_BTE_EVENT_CCM_RDI_CLEAR) {
   3955             if (oam_info_p->event_handler_count[bcmOAMEventBHHCCMRdiClear] > 0)
   3956             SHR_BITSET(events.w, bcmOAMEventBHHCCMRdiClear);
   3957         }
   3958         if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_LEVEL_CLEAR) {
   3959             if (oam_info_p->event_handler_count[bcmOAMEventBHHCCMUnknownMegLevelClear] > 0)
   3960             SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownMegLevelClear);
   3961         }
   3962         if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_ID_CLEAR) {
   3963             if (oam_info_p->event_handler_count[bcmOAMEventBHHCCMUnknownMegIdClear] > 0)
   3964             SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownMegIdClear);
   3965         }
   3966         if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_MEP_ID_CLEAR) {
   3967             if (oam_info_p->event_handler_count[bcmOAMEventBHHCCMUnknownMepIdClear] > 0)
   3968             SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownMepIdClear);
   3969         }
   3970         if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_PERIOD_CLEAR) {
   3971             if (oam_info_p->event_handler_count[bcmOAMEventBHHCCMUnknownPeriodClear] > 0)
   3972             SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownPeriodClear);
   3973         }
   3974         if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_PRIORITY_CLEAR) {
   3975             if (oam_info_p->event_handler_count[bcmOAMEventBHHCCMUnknownPriorityClear] > 0)
   3976             SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownPriorityClear);
   3977         }
   3978         if (event_mask & BHH_BTE_EVENT_CSF_LOS) {
   3979             if (oam_info_p->event_handler_count[bcmOAMEventCsfLos] > 0) {
   3980                 SHR_BITSET(events.w, bcmOAMEventCsfLos);
   3981             }
   3982         }
   3983         if (event_mask & BHH_BTE_EVENT_CSF_FDI) {
   3984             if (oam_info_p->event_handler_count[bcmOAMEventCsfFdi] > 0) {
   3985                 SHR_BITSET(events.w, bcmOAMEventCsfFdi);
   3986             }
   3987         }
   3988         if (event_mask & BHH_BTE_EVENT_CSF_RDI) {
   3989             if (oam_info_p->event_handler_count[bcmOAMEventCsfRdi] > 0) {
   3990                 SHR_BITSET(events.w, bcmOAMEventCsfRdi);
   3991             }
   3992         }
   3993         if (event_mask & BHH_BTE_EVENT_CSF_DCI) {
   3994             if (oam_info_p->event_handler_count[bcmOAMEventCsfDci] > 0) {
   3995                 SHR_BITSET(events.w, bcmOAMEventCsfDci);
   3996             }
   3997         }
   3998 
   3999      
   4000 		/* Loop over registered callbacks,
   4001 		 * If any match the events field, then invoke
   4002 		 */
   4003 		for (event_handler_p = oam_info_p->event_handler_list_p;
   4004 		     event_handler_p != NULL;
   4005 		     event_handler_p = event_handler_p->next_p) {
   4006 		    for (event_type = bcmOAMEventBHHLBTimeout; event_type < bcmOAMEventCount; ++event_type) {
   4007 			if (SHR_BITGET(events.w, event_type)) {
   4008 			    if (SHR_BITGET(event_handler_p->event_types.w,
   4009 					   event_type)) {
   4010 				event_handler_p->cb(oam_info_p->unit, 
   4011 						    flags,
   4012 						    event_type, 
   4013 						    endpoint_p->group_index, /* Group index */
   4014 						    sess_id, /* Endpoint index */
   4015 						    event_handler_p->user_data);
   4016 			    }
   4017 			}
   4018 		    }
   4019 		}
   4020 	    }
   4021 	}
   4022     }
   4023 
   4024     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   4025                 (BSL_META_U(oam_info_p->unit,
   4026                             "BHH callback thread exiting\n")));
   4027     oam_info_p->event_thread_id   = NULL;
   4028     sal_thread_exit(0);
   4029 }
   4030 
   4031 /*
   4032  * Function:
   4033  *     bcm_en_oam_loopback_add
   4034  * Purpose:
   4035  *     
   4036  * Parameters:
   4037  *     unit - Device unit number
   4038  * Returns:
   4039  *     None
   4040  */
   4041 int
   4042 bcm_en_oam_loopback_add(int unit, bcm_oam_loopback_t *loopback_p)
   4043 {
   4044     _bcm_oam_info_t *oam_info_p;
   4045     int result = BCM_E_UNAVAIL;
   4046     bhh_sdk_msg_ctrl_loopback_add_t msg;
   4047     _bcm_oam_endpoint_t *endpoint_p;
   4048     uint8 *buffer, *buffer_ptr;
   4049     uint16 buffer_len, reply_len;
   4050     uint32 flags = 0;
   4051     int sess_id = 0;
   4052 
   4053     SET_OAM_INFO;
   4054 
   4055     CHECK_INIT;
   4056 
   4057     if(oam_info_p->ukernel_not_ready) {
   4058         return BCM_E_INIT;
   4059     }
   4060 
   4061     BCM_OAM_BHH_VALIDATE_END_POINT(oam_info_p, loopback_p->id);
   4062 
   4063     SET_ENDPOINT(loopback_p->id);
   4064 
   4065     sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(oam_info_p, loopback_p->id);
   4066 
   4067     /*
   4068      * Only BHH is supported
   4069      */
   4070     if (endpoint_p->type == bcmOAMEndpointTypeBHHMPLS ||
   4071 	endpoint_p->type == bcmOAMEndpointTypeBHHMPLSVccv) {
   4072 
   4073 	/*
   4074 	 * Convert host space flags to uKernel space flags
   4075 	 */
   4076 
   4077         if (loopback_p->flags & BCM_OAM_LOOPBACK_TX_ENABLE) {
   4078             flags |= BCM_BHH_TX_ENABLE;
   4079         }
   4080 
   4081         if (loopback_p->flags & BCM_OAM_BHH_INC_REQUESTING_MEP_TLV) {
   4082             flags |= BCM_BHH_INC_REQUESTING_MEP_TLV;
   4083         }
   4084 
   4085         if (loopback_p->flags & BCM_OAM_BHH_LBM_INGRESS_DISCOVERY_MEP_TLV) {
   4086             flags |= BCM_BHH_LBM_INGRESS_DISCOVERY_MEP_TLV;
   4087         } else if (loopback_p->flags & BCM_OAM_BHH_LBM_EGRESS_DISCOVERY_MEP_TLV) {
   4088             flags |= BCM_BHH_LBM_EGRESS_DISCOVERY_MEP_TLV;
   4089         } else if (loopback_p->flags & BCM_OAM_BHH_LBM_ICC_MEP_TLV) {
   4090             flags |= BCM_BHH_LBM_ICC_MEP_TLV;
   4091         } else if (loopback_p->flags & BCM_OAM_BHH_LBM_ICC_MIP_TLV) {
   4092             flags |= BCM_BHH_LBM_ICC_MIP_TLV;
   4093         } else {
   4094             flags |= BCM_BHH_LBM_ICC_MEP_TLV; /* Default */
   4095         }
   4096 
   4097         if (loopback_p->flags & BCM_OAM_BHH_LBR_ICC_MEP_TLV) {
   4098             flags |= BCM_BHH_LBR_ICC_MEP_TLV;
   4099         } else if (loopback_p->flags & BCM_OAM_BHH_LBR_ICC_MIP_TLV) {
   4100             flags |= BCM_BHH_LBR_ICC_MIP_TLV;
   4101         }
   4102 
   4103         sal_memset(&msg, 0, sizeof(msg));
   4104 	msg.flags   = flags;
   4105 	msg.sess_id = sess_id;
   4106     msg.int_pri = loopback_p->int_pri;
   4107     msg.pkt_pri = loopback_p->pkt_pri;
   4108 
   4109 	/*
   4110 	 * Set period
   4111 	 */
   4112 	msg.period  = en_ccm_periods[_bcm_en_oam_quantize_ccm_period(loopback_p->period)];
   4113 
   4114 	/*
   4115 	 * Check TTL
   4116 	 */
   4117         if (loopback_p->ttl == 0 || loopback_p->ttl > 255) {
   4118             return BCM_E_PARAM;
   4119         }
   4120 
   4121         if (endpoint_p->type == bcmOAMEndpointTypeBHHMPLSVccv &&
   4122             endpoint_p->vccv_type == bcmOamBhhVccvTtl) {
   4123 
   4124             msg.ttl = 1; /* Only TTL 1 is valid */
   4125         } else {
   4126             msg.ttl = loopback_p->ttl;
   4127         }
   4128 
   4129 	/* Pack control message data into DMA buffer */
   4130 	buffer     = oam_info_p->dma_buffer;
   4131 	buffer_ptr = bhh_sdk_msg_ctrl_loopback_add_pack(buffer, &msg);
   4132 	buffer_len = buffer_ptr - buffer;
   4133 
   4134 	/* Send BHH Session Update message to uC */
   4135 	BCM_IF_ERROR_RETURN
   4136 	    (_bcm_en_oam_bhh_msg_send_receive(unit,
   4137 					  MOS_MSG_SUBCLASS_BHH_LOOPBACK_ADD,
   4138 					  buffer_len, 0,
   4139 					  MOS_MSG_SUBCLASS_BHH_LOOPBACK_ADD_REPLY,
   4140 					  &reply_len));
   4141 	if (reply_len != 0) {
   4142 	    result =  BCM_E_INTERNAL;
   4143 	} else {
   4144 	    result = BCM_E_NONE;
   4145 	}
   4146     }
   4147     else {
   4148         return BCM_E_UNAVAIL;
   4149     }
   4150 
   4151     return result;
   4152 }
   4153 
   4154 
   4155 
   4156 /*
   4157  * Function:
   4158  *     bcm_en_oam_loopback_get
   4159  * Purpose:
   4160  *     
   4161  * Parameters:
   4162  *     unit - Device unit number
   4163  * Returns:
   4164  *     None
   4165  */
   4166 int
   4167 bcm_en_oam_loopback_get(int unit, bcm_oam_loopback_t *loopback_p)
   4168 {
   4169     _bcm_oam_info_t *oam_info_p;
   4170     int result = BCM_E_UNAVAIL;
   4171     bhh_sdk_msg_ctrl_loopback_get_t msg;
   4172     _bcm_oam_endpoint_t *endpoint_p;
   4173     uint8 *buffer, *buffer_ptr;
   4174     uint16 buffer_len, reply_len;
   4175     int sess_id = 0;
   4176 
   4177     SET_OAM_INFO;
   4178 
   4179     CHECK_INIT;
   4180 
   4181     if(oam_info_p->ukernel_not_ready) {
   4182         return BCM_E_INIT;
   4183     }
   4184 
   4185     BCM_OAM_BHH_VALIDATE_END_POINT(oam_info_p, loopback_p->id);
   4186 
   4187     SET_ENDPOINT(loopback_p->id);
   4188 
   4189     sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(oam_info_p, loopback_p->id);
   4190 
   4191     /*
   4192      * Only BHH is supported
   4193      */
   4194     if (endpoint_p->type == bcmOAMEndpointTypeBHHMPLS ||
   4195 	endpoint_p->type == bcmOAMEndpointTypeBHHMPLSVccv) {
   4196 
   4197         sal_memset(&msg, 0, sizeof(msg));
   4198 	/* Send BHH Session Update message to uC */
   4199 	BCM_IF_ERROR_RETURN
   4200 	    (_bcm_en_oam_bhh_msg_send_receive(unit,
   4201 					  MOS_MSG_SUBCLASS_BHH_LOOPBACK_GET,
   4202 					  sess_id, 0,
   4203 					  MOS_MSG_SUBCLASS_BHH_LOOPBACK_GET_REPLY,
   4204 					  &reply_len));
   4205 
   4206 	/* Pack control message data into DMA buffer */
   4207 	buffer     = oam_info_p->dma_buffer;
   4208 	buffer_ptr = bhh_sdk_msg_ctrl_loopback_get_unpack(buffer, &msg);
   4209 	buffer_len = buffer_ptr - buffer;
   4210 
   4211 	if (reply_len != buffer_len) {
   4212 	    result =  BCM_E_INTERNAL;
   4213 	} else {
   4214 	    /*
   4215 	     * Convert kernel space flags to host space flags
   4216 	     */
   4217             if (msg.flags & BCM_BHH_INC_REQUESTING_MEP_TLV) {
   4218 		loopback_p->flags |= BCM_OAM_BHH_INC_REQUESTING_MEP_TLV;
   4219             }
   4220 
   4221             if (msg.flags & BCM_BHH_LBM_INGRESS_DISCOVERY_MEP_TLV) {
   4222                 loopback_p->flags |= BCM_OAM_BHH_LBM_INGRESS_DISCOVERY_MEP_TLV;
   4223             } else if (msg.flags & BCM_BHH_LBM_EGRESS_DISCOVERY_MEP_TLV) {
   4224                 loopback_p->flags |= BCM_OAM_BHH_LBM_EGRESS_DISCOVERY_MEP_TLV;
   4225             } else if (msg.flags & BCM_BHH_LBM_ICC_MEP_TLV) {
   4226                 loopback_p->flags |= BCM_OAM_BHH_LBM_ICC_MEP_TLV;
   4227             } else if (msg.flags & BCM_BHH_LBM_ICC_MIP_TLV) {
   4228                 loopback_p->flags |= BCM_OAM_BHH_LBM_ICC_MIP_TLV;
   4229             }
   4230 
   4231             if (msg.flags & BCM_BHH_LBR_ICC_MEP_TLV) {
   4232                 loopback_p->flags |= BCM_OAM_BHH_LBR_ICC_MEP_TLV;
   4233             } else if (msg.flags & BCM_BHH_LBR_ICC_MIP_TLV) {
   4234                 loopback_p->flags |= BCM_OAM_BHH_LBR_ICC_MIP_TLV;
   4235             }
   4236 
   4237             if (msg.flags & BCM_BHH_TX_ENABLE) {
   4238                 loopback_p->flags |= BCM_OAM_LOOPBACK_TX_ENABLE;
   4239             }
   4240 
   4241             loopback_p->period                  = msg.period;
   4242             loopback_p->ttl                     = msg.ttl;
   4243             loopback_p->discovered_me.flags     = msg.discovery_flags;
   4244             loopback_p->discovered_me.name      = msg.discovery_id;
   4245             loopback_p->discovered_me.ttl       = msg.discovery_ttl;
   4246             loopback_p->rx_count                = msg.rx_count;
   4247             loopback_p->tx_count                = msg.tx_count;
   4248             loopback_p->drop_count              = msg.drop_count;
   4249             loopback_p->unexpected_response     = msg.unexpected_response;
   4250             loopback_p->out_of_sequence         = msg.out_of_sequence;
   4251             loopback_p->local_mipid_missmatch   = msg.local_mipid_missmatch;
   4252             loopback_p->remote_mipid_missmatch  = msg.remote_mipid_missmatch;
   4253             loopback_p->invalid_target_mep_tlv  = msg.invalid_target_mep_tlv;
   4254             loopback_p->invalid_mep_tlv_subtype = msg.invalid_mep_tlv_subtype;
   4255             loopback_p->invalid_tlv_offset      = msg.invalid_tlv_offset;
   4256             loopback_p->int_pri                 = msg.int_pri;
   4257             loopback_p->pkt_pri                 = msg.pkt_pri;
   4258 
   4259             result = BCM_E_NONE;
   4260         }
   4261     }
   4262     else {
   4263         return BCM_E_UNAVAIL;
   4264     }
   4265 
   4266     return result;
   4267 }
   4268 
   4269 /*
   4270  * Function:
   4271  *     bcm_en_oam_loopback_delete
   4272  * Purpose:
   4273  *     
   4274  * Parameters:
   4275  *     unit - Device unit number
   4276  * Returns:
   4277  *     None
   4278  */
   4279 int
   4280 bcm_en_oam_loopback_delete(int unit, bcm_oam_loopback_t *loopback_p)
   4281 {
   4282     _bcm_oam_info_t *oam_info_p;
   4283     int result = BCM_E_UNAVAIL;
   4284     shr_bhh_msg_ctrl_loopback_delete_t msg;
   4285     _bcm_oam_endpoint_t *endpoint_p;
   4286     uint8 *buffer, *buffer_ptr;
   4287     uint16 buffer_len, reply_len;
   4288     int sess_id = 0;
   4289 
   4290     SET_OAM_INFO;
   4291 
   4292     CHECK_INIT;
   4293 
   4294     if(oam_info_p->ukernel_not_ready) {
   4295         return BCM_E_INIT;
   4296     }
   4297 
   4298     BCM_OAM_BHH_VALIDATE_END_POINT(oam_info_p, loopback_p->id);
   4299 
   4300     SET_ENDPOINT(loopback_p->id);
   4301 
   4302     sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(oam_info_p, loopback_p->id);
   4303 
   4304     /*
   4305      * Only BHH is supported
   4306      */
   4307     if (endpoint_p->type == bcmOAMEndpointTypeBHHMPLS ||
   4308 	endpoint_p->type == bcmOAMEndpointTypeBHHMPLSVccv) {
   4309 
   4310 	msg.sess_id = sess_id;
   4311 
   4312 	/* Pack control message data into DMA buffer */
   4313 	buffer     = oam_info_p->dma_buffer;
   4314 	buffer_ptr = shr_bhh_msg_ctrl_loopback_delete_pack(buffer, &msg);
   4315 	buffer_len = buffer_ptr - buffer;
   4316 
   4317 	/* Send BHH Session Update message to uC */
   4318 	BCM_IF_ERROR_RETURN
   4319 	    (_bcm_en_oam_bhh_msg_send_receive(unit,
   4320 					  MOS_MSG_SUBCLASS_BHH_LOOPBACK_DELETE,
   4321 					  buffer_len, 0,
   4322 					  MOS_MSG_SUBCLASS_BHH_LOOPBACK_DELETE_REPLY,
   4323 					  &reply_len));
   4324 	if (reply_len != 0) {
   4325 	    result =  BCM_E_INTERNAL;
   4326 	} else {
   4327 	    result = BCM_E_NONE;
   4328 	}
   4329     }
   4330     else {
   4331         return BCM_E_UNAVAIL;
   4332     }
   4333 
   4334     return result;
   4335 }
   4336 
   4337 /*
   4338  * Function:
   4339  *      bcm_en_oam_csf_add
   4340  * Purpose:
   4341  *      Start CSF PDU transmission
   4342  * Parameters:
   4343  *      unit    - (IN)    Unit number.
   4344  *      csf_ptr - (INOUT) CSF object
   4345  * Returns:
   4346  *      BCM_E_XXX
   4347  * Notes:
   4348  */
   4349 int bcm_en_oam_csf_add(int unit, bcm_oam_csf_t *csf_p)
   4350 {
   4351     _bcm_oam_info_t            *oam_info_p;
   4352     _bcm_oam_endpoint_t        *endpoint_p;
   4353     bhh_sdk_msg_ctrl_csf_add_t  msg;
   4354     uint8                      *buffer, *buffer_ptr;
   4355     uint16                      buffer_len, reply_len;
   4356     int                         sess_id = 0;
   4357     int                         rv = BCM_E_NONE;
   4358 
   4359     SET_OAM_INFO;
   4360     CHECK_INIT;
   4361     if(oam_info_p->ukernel_not_ready) {
   4362         return BCM_E_INIT;
   4363     }
   4364 
   4365     BCM_OAM_BHH_VALIDATE_END_POINT(oam_info_p, csf_p->id);
   4366     SET_ENDPOINT(csf_p->id);
   4367     sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(oam_info_p, csf_p->id);
   4368 
   4369     if ((csf_p->period != BCM_OAM_ENDPOINT_CCM_PERIOD_1S) &&
   4370         (csf_p->period != BCM_OAM_ENDPOINT_CCM_PERIOD_1M)) {
   4371         /* Only 1S and 1M are supported */
   4372         return BCM_E_PARAM;
   4373     }
   4374 
   4375     /*
   4376      * Only BHH is supported
   4377      */
   4378     if (endpoint_p->type != bcmOAMEndpointTypeBHHMPLS &&
   4379         endpoint_p->type != bcmOAMEndpointTypeBHHMPLSVccv) {
   4380         return BCM_E_UNAVAIL;
   4381     }
   4382 
   4383     sal_memset(&msg, 0, sizeof(msg));
   4384     msg.sess_id = sess_id;
   4385     msg.int_pri = csf_p->int_pri;
   4386     msg.pkt_pri = csf_p->pkt_pri;
   4387 
   4388     switch(csf_p->type) {
   4389         case BCM_OAM_CSF_LOS:
   4390             msg.type = SHR_CSF_TYPE_LOS;
   4391             break;
   4392 
   4393         case BCM_OAM_CSF_FDI:
   4394             msg.type = SHR_CSF_TYPE_FDI;
   4395             break;
   4396 
   4397         case BCM_OAM_CSF_RDI:
   4398             msg.type = SHR_CSF_TYPE_RDI;
   4399             break;
   4400 
   4401         case BCM_OAM_CSF_DCI:
   4402             msg.type = SHR_CSF_TYPE_DCI;
   4403             break;
   4404 
   4405         default:
   4406             return BCM_E_PARAM;
   4407     }
   4408 
   4409     /*
   4410      * Set period
   4411      */
   4412     msg.period  = csf_p->period;
   4413 
   4414     /* Pack control message data into DMA buffer */
   4415     buffer     = oam_info_p->dma_buffer;
   4416     buffer_ptr = bhh_sdk_msg_ctrl_csf_add_pack(buffer, &msg);
   4417     buffer_len = buffer_ptr - buffer;
   4418 
   4419     /* Send BHH Session Update message to uC */
   4420     rv = _bcm_en_oam_bhh_msg_send_receive(unit,
   4421                                           MOS_MSG_SUBCLASS_BHH_CSF_ADD,
   4422                                           buffer_len, 0,
   4423                                           MOS_MSG_SUBCLASS_BHH_CSF_ADD_REPLY,
   4424                                           &reply_len);
   4425 
   4426     if(BCM_SUCCESS(rv) && (reply_len != 0)) {
   4427         rv =  BCM_E_INTERNAL;
   4428     }
   4429 
   4430     return rv;
   4431 }
   4432 
   4433 /*
   4434  * Function:
   4435  *      bcm_en_oam_csf_get
   4436  * Purpose:
   4437  *      Get CSF info
   4438  * Parameters:
   4439  *      unit    - (IN)  Unit number.
   4440  *      csf_ptr - (OUT) CSF object
   4441  * Returns:
   4442  *      BCM_E_XXX
   4443  * Notes:
   4444  */
   4445 int bcm_en_oam_csf_get(int unit, bcm_oam_csf_t *csf_p)
   4446 {
   4447     _bcm_oam_info_t             *oam_info_p;
   4448     bhh_sdk_msg_ctrl_csf_get_t   msg;
   4449     _bcm_oam_endpoint_t         *endpoint_p;
   4450     uint8                       *buffer, *buffer_ptr;
   4451     uint16                       buffer_len, reply_len;
   4452     int                          sess_id = 0;
   4453     int                          rv = BCM_E_NONE;
   4454 
   4455     SET_OAM_INFO;
   4456     CHECK_INIT;
   4457     if(oam_info_p->ukernel_not_ready) {
   4458         return BCM_E_INIT;
   4459     }
   4460 
   4461     BCM_OAM_BHH_VALIDATE_END_POINT(oam_info_p, csf_p->id);
   4462     SET_ENDPOINT(csf_p->id);
   4463     sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(oam_info_p, csf_p->id);
   4464 
   4465 
   4466     /*
   4467      * Only BHH is supported
   4468      */
   4469     if (endpoint_p->type != bcmOAMEndpointTypeBHHMPLS &&
   4470         endpoint_p->type != bcmOAMEndpointTypeBHHMPLSVccv) {
   4471         return BCM_E_UNAVAIL;
   4472     }
   4473 
   4474     /* Send BHH Session Update message to uC */
   4475     sal_memset(&msg, 0, sizeof(msg));
   4476     rv = _bcm_en_oam_bhh_msg_send_receive(unit,
   4477                                           MOS_MSG_SUBCLASS_BHH_CSF_GET,
   4478                                           sess_id, 0,
   4479                                           MOS_MSG_SUBCLASS_BHH_CSF_GET_REPLY,
   4480                                           &reply_len);
   4481     if(BCM_FAILURE(rv)) {
   4482         LOG_ERROR(BSL_LS_BCM_OAM,
   4483                   (BSL_META_U(unit,
   4484                               "OAM(unit %d) Error: Endpoint EP=%d %s.\n"),
   4485                    unit, csf_p->id, bcm_errmsg(rv)));
   4486         return (rv);
   4487     }
   4488 
   4489     /* Pack control message data into DMA buffer */
   4490     buffer     = oam_info_p->dma_buffer;
   4491     buffer_ptr = bhh_sdk_msg_ctrl_csf_get_unpack(buffer, &msg);
   4492     buffer_len = buffer_ptr - buffer;
   4493 
   4494 
   4495     if (reply_len != buffer_len) {
   4496         return BCM_E_INTERNAL;
   4497     }
   4498 
   4499     switch(msg.type) {
   4500         case SHR_CSF_TYPE_LOS:
   4501             csf_p->type = BCM_OAM_CSF_LOS;
   4502             break;
   4503 
   4504         case SHR_CSF_TYPE_FDI:
   4505             csf_p->type = BCM_OAM_CSF_FDI;
   4506             break;
   4507 
   4508         case SHR_CSF_TYPE_RDI:
   4509             csf_p->type = BCM_OAM_CSF_RDI;
   4510             break;
   4511 
   4512         case SHR_CSF_TYPE_DCI:
   4513             csf_p->type = BCM_OAM_CSF_DCI;
   4514             break;
   4515 
   4516         default:
   4517             return BCM_E_INTERNAL;
   4518     }
   4519 
   4520     csf_p->period  = msg.period;
   4521     csf_p->flags   = msg.flags;
   4522     csf_p->pkt_pri = msg.pkt_pri;
   4523     csf_p->int_pri = msg.int_pri;
   4524 
   4525     return BCM_E_NONE;
   4526 
   4527 }
   4528 
   4529 /*
   4530  * Function:
   4531  *      bcm_en_oam_csf_delete
   4532  * Purpose:
   4533  *      Stop CSF PDU transmission
   4534  * Parameters:
   4535  *      unit    - (IN  Unit number.
   4536  *      csf_ptr - (IN) CSF object
   4537  * Returns:
   4538  *      BCM_E_XXX
   4539  * Notes:
   4540  */
   4541 int bcm_en_oam_csf_delete(int unit, bcm_oam_csf_t *csf_p)
   4542 {
   4543     _bcm_oam_info_t      *oam_info_p;
   4544     _bcm_oam_endpoint_t  *endpoint_p;
   4545     uint16                reply_len;
   4546     int                   sess_id;
   4547     int                   rv = BCM_E_NONE;
   4548 
   4549     SET_OAM_INFO;
   4550     CHECK_INIT;
   4551     if(oam_info_p->ukernel_not_ready) {
   4552         return BCM_E_INIT;
   4553     }
   4554 
   4555     BCM_OAM_BHH_VALIDATE_END_POINT(oam_info_p, csf_p->id);
   4556     SET_ENDPOINT(csf_p->id);
   4557     sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(oam_info_p, csf_p->id);
   4558 
   4559     /*
   4560      * Only BHH is supported
   4561      */
   4562     if (endpoint_p->type != bcmOAMEndpointTypeBHHMPLS &&
   4563         endpoint_p->type != bcmOAMEndpointTypeBHHMPLSVccv) {
   4564         return BCM_E_UNAVAIL;
   4565     }
   4566 
   4567     /* Send BHH Session Update message to uC */
   4568     rv = _bcm_en_oam_bhh_msg_send_receive(unit,
   4569                                           MOS_MSG_SUBCLASS_BHH_CSF_DELETE,
   4570                                           sess_id, 0,
   4571                                           MOS_MSG_SUBCLASS_BHH_CSF_DELETE_REPLY,
   4572                                           &reply_len);
   4573     return (rv);
   4574 }
   4575 #endif /* defined(BCM_KATANA_SUPPORT)  && defined(INCLUDE_BHH) */
   4576 
   4577 
   4578 /*
   4579  * Function:
   4580  *      bcm_en_oam_detach
   4581  * Purpose:
   4582  *      Shut down the OAM subsystem
   4583  * Parameters:
   4584  *      unit - (IN) Unit number.
   4585  * Returns:
   4586  *      BCM_E_XXX
   4587  * Notes:
   4588  */
   4589 int 
   4590 bcm_en_oam_detach(
   4591     int unit)
   4592 {
   4593     _bcm_oam_info_t *oam_info_p;
   4594     bcm_port_t port_index;
   4595 #if defined(BCM_KATANA_SUPPORT) && defined(INCLUDE_BHH)
   4596     int rv;
   4597     uint16 reply_len;
   4598     sal_usecs_t timeout;
   4599     int status;
   4600 #endif
   4601 
   4602     SET_OAM_INFO;
   4603 
   4604     if (!oam_info_p->initialized)
   4605     {
   4606         return BCM_E_NONE;
   4607     }
   4608 
   4609     /* Disable CCM transmission */
   4610 
   4611     SOC_IF_ERROR_RETURN(WRITE_OAM_TX_CONTROLr(unit, 0));
   4612     
   4613     /* Disable OAM message reception on all ports */
   4614 
   4615     PBMP_ALL_ITER(unit, port_index)
   4616     {
   4617         BCM_IF_ERROR_RETURN(bcm_esw_port_control_set(unit,
   4618             port_index, bcmPortControlOAMEnable, 0));
   4619     }
   4620 
   4621     /*
   4622      * BHH specific 
   4623      */
   4624     if (soc_feature(unit, soc_feature_bhh)) {
   4625 #if defined(BCM_KATANA_SUPPORT) && defined(INCLUDE_BHH)
   4626     if (SOC_IS_KATANAX(unit)) {
   4627         if (oam_info_p->ukernel_not_ready == 0) {
   4628             /*
   4629              * Event Handler thread exit signal
   4630              */
   4631             timeout = sal_time_usecs() + 5000000;
   4632             while (NULL !=  oam_info_p->event_thread_id) {
   4633                 soc_cmic_uc_msg_receive_cancel(unit, oam_info_p->uc_num,
   4634                                                MOS_MSG_CLASS_BHH_EVENT);
   4635 
   4636                 if (sal_time_usecs() < timeout) {
   4637                     /*give some time to already running bhh callback thread
   4638                      * to schedule and exit */
   4639                     sal_usleep(10000);
   4640                 } else {
   4641                     /*timeout*/
   4642                     LOG_ERROR(BSL_LS_BCM_OAM,
   4643                               (BSL_META_U(unit,
   4644                                           "BHH event thread did not exit.\n")));
   4645                     return BCM_E_INTERNAL;
   4646                 }
   4647             }
   4648 
   4649             /*
   4650              * Send BHH Uninit message to uC
   4651              * Ignore error since that may indicate uKernel was reloaded.
   4652              */
   4653 #if defined(BCM_WARM_BOOT_SUPPORT)
   4654     if (!SOC_WARM_BOOT(unit)) {
   4655 #endif
   4656         SOC_IF_ERROR_RETURN(soc_uc_status(unit, oam_info_p->uc_num, &status));
   4657         if (status) {
   4658             rv = _bcm_en_oam_bhh_msg_send_receive(unit,
   4659                                             MOS_MSG_SUBCLASS_BHH_UNINIT,
   4660                                             0, 0,
   4661                                             MOS_MSG_SUBCLASS_BHH_UNINIT_REPLY,
   4662                                             &reply_len);
   4663             if (BCM_SUCCESS(rv) && (reply_len != 0)) {
   4664                 return BCM_E_INTERNAL;
   4665             }
   4666          }
   4667 #if defined(BCM_WARM_BOOT_SUPPORT)
   4668     }
   4669 #endif
   4670 
   4671             /* 
   4672              * Delete CPU COS queue mapping entries for BHH packets 
   4673              */
   4674             if (oam_info_p->cpu_cosq_ach_error_index >= 0) {
   4675                 BCM_IF_ERROR_RETURN
   4676                     (bcm_esw_rx_cosq_mapping_delete(unit,
   4677                                          oam_info_p->cpu_cosq_ach_error_index));
   4678                 oam_info_p->cpu_cosq_ach_error_index = -1;
   4679             }
   4680             if (oam_info_p->cpu_cosq_invalid_error_index >= 0) {
   4681                 BCM_IF_ERROR_RETURN
   4682                     (bcm_esw_rx_cosq_mapping_delete(unit,
   4683                                      oam_info_p->cpu_cosq_invalid_error_index));
   4684                 oam_info_p->cpu_cosq_invalid_error_index = -1;
   4685             }
   4686         }
   4687     }
   4688 #endif
   4689     }
   4690 
   4691 #ifdef BCM_KATANA_SUPPORT
   4692     if (SOC_IS_KATANA(unit)) {
   4693         soc_kt_oam_handler_register(unit, NULL);
   4694     } else
   4695 #endif /* BCM_KATANA_SUPPORT */
   4696     {
   4697         soc_enduro_oam_handler_register(unit, NULL);
   4698     }
   4699     _bcm_en_oam_event_unregister_all(oam_info_p);
   4700 
   4701     BCM_IF_ERROR_RETURN(bcm_en_oam_group_destroy_all(unit));
   4702 
   4703     /* De-initialize the ING_SERVICE_PRI_MAP table */
   4704     if (ing_pri_map_profile[unit]) {
   4705         SOC_IF_ERROR_RETURN(soc_profile_mem_destroy(unit,
   4706                                                     ing_pri_map_profile[unit]));
   4707         sal_free(ing_pri_map_profile[unit]);
   4708         ing_pri_map_profile[unit] = NULL;
   4709     }
   4710 
   4711 #if defined(BCM_KATANA_SUPPORT)
   4712     if (SOC_IS_KATANAX(unit)) {
   4713         /* De-initialize the OAM_OPCODE_PROFILE table */
   4714         SOC_IF_ERROR_RETURN(soc_profile_mem_destroy(unit,
   4715                                                     oam_opcode_profile[unit]));
   4716     }
   4717 #endif /* BCM_KATANA_SUPPORT */
   4718 
   4719     _bcm_en_oam_free_memory(unit, oam_info_p);
   4720     sal_memset(oam_info_p, 0 , sizeof(_bcm_oam_info_t));
   4721 
   4722     return BCM_E_NONE;
   4723 }
   4724 
   4725 static void _bcm_en_oam_group_name_mangle(uint8 *name_p,
   4726     uint8 *mangled_name_p)
   4727 {
   4728     uint8 *byte_p = name_p + BCM_OAM_GROUP_NAME_LENGTH - 1;
   4729     int bytes_left = BCM_OAM_GROUP_NAME_LENGTH;
   4730 
   4731     while (bytes_left > 0)
   4732     {
   4733         *mangled_name_p = *byte_p;
   4734 
   4735         ++mangled_name_p;
   4736         --byte_p;
   4737         --bytes_left;
   4738     }
   4739 }
   4740 
   4741 /*
   4742  * Function:
   4743  *      bcm_en_oam_group_create
   4744  * Purpose:
   4745  *      Create or replace an OAM group object
   4746  * Parameters:
   4747  *      unit - (IN) Unit number.
   4748  *      group_info - (IN/OUT) Pointer to an OAM group structure
   4749  * Returns:
   4750  *      BCM_E_XXX
   4751  * Notes:
   4752  */
   4753 int 
   4754 bcm_en_oam_group_create(
   4755     int unit, 
   4756     bcm_oam_group_info_t *group_info)
   4757 {
   4758     _bcm_oam_info_t *oam_info_p;
   4759     _bcm_oam_group_t *group_p;
   4760     int replace;
   4761     int group_index = 0;
   4762     int copy_to_cpu = 0;
   4763 
   4764 #if defined(BCM_KATANA_SUPPORT)  && defined(INCLUDE_BHH)
   4765     bhh_sdk_msg_ctrl_sess_set_t msg_sess;
   4766     uint8 *buffer, *buffer_ptr;
   4767     uint16 buffer_len, reply_len;
   4768     uint32 session_flags = 0;
   4769     _bcm_oam_endpoint_t *endpoint_p;
   4770     int endpoint_index;
   4771 #endif
   4772 
   4773     maid_reduction_entry_t maid_reduction_entry;
   4774     ma_state_entry_t ma_state_entry;
   4775     uint8 mangled_group_name[MANGLED_GROUP_NAME_LENGTH];
   4776 
   4777     SET_OAM_INFO;
   4778 
   4779     CHECK_INIT;
   4780 
   4781     replace = group_info->flags & BCM_OAM_GROUP_REPLACE;
   4782 
   4783     if (group_info->flags & BCM_OAM_GROUP_WITH_ID)
   4784     {
   4785         if (soc_feature(unit, soc_feature_oam_lookup_bypass_cpu_tx_packets)) 
   4786         {
   4787             if(group_info->id == 0)
   4788             {
   4789                 return BCM_E_PARAM;
   4790             }
   4791   
   4792         }
   4793         group_index = group_info->id;
   4794 
   4795         VALIDATE_GROUP_INDEX(group_index);
   4796 
   4797         if (!replace && (oam_info_p->groups[group_index].in_use))
   4798         {
   4799             return BCM_E_EXISTS;
   4800         }
   4801     }
   4802     else
   4803     {
   4804         if (replace)
   4805         {
   4806             return BCM_E_PARAM;
   4807         }
   4808 
   4809        if (soc_feature(unit, soc_feature_oam_lookup_bypass_cpu_tx_packets)) {
   4810            group_index = 1;
   4811        }
   4812         for (; group_index < oam_info_p->group_count;
   4813             ++group_index)
   4814         {
   4815             if (!oam_info_p->groups[group_index].in_use)
   4816             {
   4817                 break;
   4818             }
   4819         }
   4820 
   4821         if (group_index >= oam_info_p->group_count)
   4822         {
   4823             return BCM_E_FULL;
   4824         }
   4825 
   4826         group_info->id = group_index;
   4827     }
   4828 
   4829     SET_GROUP(group_index);
   4830 
   4831     memcpy(group_p->name, group_info->name, BCM_OAM_GROUP_NAME_LENGTH);
   4832 
   4833     /* MAID_REDUCTION entry */
   4834 
   4835     _bcm_en_oam_group_name_mangle(group_p->name, mangled_group_name);
   4836 
   4837     sal_memset(&maid_reduction_entry, 0, sizeof(maid_reduction_entry_t));
   4838 
   4839     soc_MAID_REDUCTIONm_field32_set(unit, &maid_reduction_entry, REDUCED_MAIDf,
   4840         soc_draco_crc32(mangled_group_name, MANGLED_GROUP_NAME_LENGTH));
   4841 
   4842     soc_MAID_REDUCTIONm_field32_set(unit, &maid_reduction_entry, SW_RDIf,
   4843         (group_info->flags & BCM_OAM_GROUP_REMOTE_DEFECT_TX) ? 1 : 0);
   4844 
   4845     if (soc_feature(unit, soc_feature_bhh)) { 
   4846 #if defined(BCM_KATANA_SUPPORT)  && defined(INCLUDE_BHH)
   4847         /* Send message to uC to set the Soft RDI, if RDI flag is set */
   4848         if (group_info->flags & BCM_OAM_GROUP_REMOTE_DEFECT_TX) { 
   4849       
   4850             /* Get the endpoint info of the group */   
   4851             for (endpoint_index = 0; endpoint_index < oam_info_p->endpoint_count;
   4852                  ++endpoint_index) {
   4853                  SET_ENDPOINT(endpoint_index);
   4854 
   4855                  if (endpoint_p->in_use && endpoint_p->group_index == group_index) { 
   4856               
   4857                      /* Set the RDI flag in session bits */ 
   4858                      session_flags |= SHR_BHH_SESS_SET_F_RDI;
   4859               
   4860                      /* Get the session is from endpoint */
   4861                      msg_sess.sess_id =
   4862                          BCM_OAM_BHH_GET_UKERNEL_EP(oam_info_p,
   4863                                                     endpoint_index);     
   4864                         
   4865                      /* Pack control message data into DMA buffer */
   4866                      msg_sess.flags = session_flags;
   4867 
   4868                      buffer     = oam_info_p->dma_buffer;
   4869                      buffer_ptr = bhh_sdk_msg_ctrl_sess_set_pack(buffer, &msg_sess);
   4870                      buffer_len = buffer_ptr - buffer;
   4871 
   4872                      /* Send BHH Session Update message to uC */
   4873                      BCM_IF_ERROR_RETURN
   4874                             (_bcm_en_oam_bhh_msg_send_receive(unit,
   4875                                                       MOS_MSG_SUBCLASS_BHH_SESS_SET,
   4876                                                       buffer_len, 0,
   4877                                                       MOS_MSG_SUBCLASS_BHH_SESS_SET_REPLY,
   4878                                                       &reply_len));
   4879                      if (reply_len != 0) {
   4880                          return BCM_E_INTERNAL;
   4881                      }
   4882                  }
   4883             }
   4884         }  
   4885 #endif
   4886     }
   4887     copy_to_cpu = ((group_info->flags & BCM_OAM_GROUP_COPY_TO_CPU) ? 1 : 0);
   4888     soc_MAID_REDUCTIONm_field32_set(unit, &maid_reduction_entry,
   4889                                         COPY_TO_CPUf, copy_to_cpu);
   4890 
   4891     soc_MAID_REDUCTIONm_field32_set(unit, &maid_reduction_entry, VALIDf, 1);
   4892 
   4893     SOC_IF_ERROR_RETURN(WRITE_MAID_REDUCTIONm(unit, MEM_BLOCK_ALL,
   4894         group_index, &maid_reduction_entry));
   4895 
   4896     /* MA_STATE entry */
   4897     sal_memset(&ma_state_entry, 0, sizeof(ma_state_entry_t));
   4898 
   4899     if (replace) {
   4900         /* Keep defect status if group is being replaced */
   4901         SOC_IF_ERROR_RETURN(READ_MA_STATEm(unit, MEM_BLOCK_ALL, group_index, 
   4902             &ma_state_entry));
   4903     } 
   4904 
   4905     soc_MA_STATEm_field32_set(unit, &ma_state_entry, LOWESTALARMPRIf,
   4906 								group_info->lowest_alarm_priority);
   4907 
   4908     soc_MA_STATEm_field32_set(unit, &ma_state_entry, VALIDf, 1);
   4909 
   4910     SOC_IF_ERROR_RETURN(WRITE_MA_STATEm(unit, MEM_BLOCK_ALL, group_index,
   4911         &ma_state_entry));
   4912 
   4913     /* Local control block */
   4914 
   4915     group_p->in_use = 1;
   4916 
   4917 #ifdef BCM_WARM_BOOT_SUPPORT
   4918     SOC_CONTROL_LOCK(unit);
   4919     SOC_CONTROL(unit)->scache_dirty = 1;
   4920     SOC_CONTROL_UNLOCK(unit);
   4921 #endif
   4922 
   4923     return BCM_E_NONE;
   4924 }
   4925 
   4926 static int _bcm_en_oam_read_clear_faults(int unit, int entry_index,
   4927     _bcm_oam_fault_t *faults, soc_mem_t mem, uint32 *entry_p,
   4928     uint32 *fault_bits_p, uint32 *persistent_fault_bits_p,
   4929     uint32 clear_persistent_fault_bits)
   4930 {
   4931     _bcm_oam_fault_t *fault_p;
   4932     uint32 ccm_read_control_reg_value = 0;
   4933     uint32 clear_mask = 0; /* Mask to clear persistent faults*/
   4934 
   4935     for (fault_p = faults; fault_p->mask != 0; ++fault_p)
   4936     {
   4937         /* Current fault state */
   4938 
   4939         if (soc_mem_field32_get(unit, mem, entry_p,
   4940             fault_p->current_field) != 0)
   4941         {
   4942             *fault_bits_p |= fault_p->mask;
   4943         }
   4944 
   4945         /* Sticky fault state */
   4946 
   4947         if (soc_mem_field32_get(unit, mem, entry_p,
   4948             fault_p->sticky_field) != 0)
   4949         {
   4950             *persistent_fault_bits_p |= fault_p->mask;
   4951 
   4952             /* Clear persistent faults if requested */
   4953 
   4954             if (clear_persistent_fault_bits)
   4955             {
   4956                 clear_mask |= fault_p->clear_sticky_mask;
   4957             }
   4958         }
   4959     }
   4960 
   4961     /* If any clear bits were set, do the clear now */
   4962 
   4963     if (clear_persistent_fault_bits && clear_mask)
   4964     {
   4965         soc_reg_field_set(unit, CCM_READ_CONTROLr, 
   4966             &ccm_read_control_reg_value, BITS_TO_CLEARf, clear_mask);
   4967 
   4968         soc_reg_field_set(unit, CCM_READ_CONTROLr,
   4969             &ccm_read_control_reg_value, ENABLE_CLEARf, 1);
   4970         /*
   4971          * MA_STATE table, MEMORYf should be 0.
   4972          */  
   4973         if (mem == MA_STATEm) {
   4974             soc_reg_field_set(unit, CCM_READ_CONTROLr,
   4975                 &ccm_read_control_reg_value, MEMORYf, 0);
   4976         } else {
   4977             soc_reg_field_set(unit, CCM_READ_CONTROLr,
   4978                 &ccm_read_control_reg_value, MEMORYf, 1);
   4979         }
   4980 
   4981         soc_reg_field_set(unit, CCM_READ_CONTROLr,
   4982             &ccm_read_control_reg_value, INDEXf, entry_index);
   4983 
   4984         SOC_IF_ERROR_RETURN(WRITE_CCM_READ_CONTROLr(unit,
   4985             ccm_read_control_reg_value));
   4986     }
   4987 
   4988     return BCM_E_NONE;
   4989 }
   4990 
   4991 #if defined(BCM_KATANA_SUPPORT)  && defined(INCLUDE_BHH)
   4992 /*
   4993  * Function:
   4994  *      _bcm_en_oam_get_group_sw_rdi
   4995  * Purpose:
   4996  *     Get OAM group SW RDI information.
   4997  * Parameters:
   4998  *     unit         - (IN) BCM device number
   4999  *     group_index  - (IN) Group hardware table index
   5000  *     group_sw_rdi - (OUT) Pointer to group SW RDI
   5001  * Returns:
   5002  *     BCM_E_NONE      - No errors.
   5003  *     BCM_E_XXX       - Otherwise.
   5004  */
   5005 STATIC int
   5006 _bcm_en_oam_get_group_sw_rdi(int unit, bcm_oam_group_t group_index,
   5007                        uint8 *group_sw_rdi)
   5008 {
   5009     maid_reduction_entry_t  maid_reduction_entry; /* MAID reduction entry.    */
   5010 
   5011     BCM_IF_ERROR_RETURN(READ_MAID_REDUCTIONm(unit, MEM_BLOCK_ANY,
   5012                                              group_index,
   5013                                              &maid_reduction_entry));
   5014 
   5015     if (1 == soc_MAID_REDUCTIONm_field32_get(unit, &maid_reduction_entry,
   5016                                              SW_RDIf)) {
   5017         *group_sw_rdi = 1;
   5018     }
   5019     return (BCM_E_NONE);
   5020 }
   5021 #endif
   5022 
   5023 static int _bcm_en_oam_get_group(int unit, int group_index,
   5024     _bcm_oam_group_t *group_p, bcm_oam_group_info_t *group_info)
   5025 {
   5026     maid_reduction_entry_t maid_reduction_entry;
   5027     ma_state_entry_t ma_state_entry;
   5028 
   5029     group_info->id = group_index;
   5030 
   5031     if (!(group_info->flags & BCM_OAM_GROUP_GET_FAULTS_ONLY)) { 
   5032         memcpy(group_info->name, group_p->name, BCM_OAM_GROUP_NAME_LENGTH);
   5033 
   5034         /* MAID_REDUCTION entry */
   5035 
   5036         SOC_IF_ERROR_RETURN(READ_MAID_REDUCTIONm(unit, MEM_BLOCK_ANY, group_index,
   5037             &maid_reduction_entry));
   5038 
   5039         if (soc_MAID_REDUCTIONm_field32_get(unit, &maid_reduction_entry,
   5040             SW_RDIf) != 0)
   5041         {
   5042             group_info->flags |= BCM_OAM_GROUP_REMOTE_DEFECT_TX;
   5043         }
   5044 
   5045 	    if (soc_MAID_REDUCTIONm_field32_get(unit, &maid_reduction_entry,
   5046             COPY_TO_CPUf) != 0)
   5047         {
   5048             group_info->flags |= BCM_OAM_GROUP_COPY_TO_CPU;
   5049         }
   5050     } else {
   5051           group_info->flags &= ~BCM_OAM_GROUP_GET_FAULTS_ONLY;
   5052     }
   5053 
   5054     /* MA_STATE entry */
   5055 
   5056     SOC_IF_ERROR_RETURN(READ_MA_STATEm(unit, MEM_BLOCK_ANY, group_index,
   5057         &ma_state_entry));
   5058 	
   5059 	/* Get the Lowest Alarm Priority value*/
   5060 	group_info->lowest_alarm_priority =
   5061 		soc_MA_STATEm_field32_get(unit, &ma_state_entry, LOWESTALARMPRIf);
   5062 
   5063     return _bcm_en_oam_read_clear_faults(unit, group_index, en_group_faults,
   5064         MA_STATEm, (uint32 *) &ma_state_entry, &group_info->faults,
   5065         &group_info->persistent_faults, group_info->clear_persistent_faults);
   5066 }
   5067 
   5068 /*
   5069  * Function:
   5070  *      bcm_en_oam_group_get
   5071  * Purpose:
   5072  *      Get an OAM group object
   5073  * Parameters:
   5074  *      unit - (IN) Unit number.
   5075  *      group - (IN) The ID of the group object to get
   5076  *      group_info - (OUT) Pointer to an OAM group structure to receive the data
   5077  * Returns:
   5078  *      BCM_E_XXX
   5079  * Notes:
   5080  */
   5081 int 
   5082 bcm_en_oam_group_get(
   5083     int unit, 
   5084     bcm_oam_group_t group, 
   5085     bcm_oam_group_info_t *group_info)
   5086 {
   5087     _bcm_oam_info_t *oam_info_p;
   5088     _bcm_oam_group_t *group_p;
   5089 #if defined(BCM_KATANA_SUPPORT)  && defined(INCLUDE_BHH)
   5090     bhh_sdk_msg_ctrl_sess_get_t msg;
   5091     uint8 *buffer, *buffer_ptr;
   5092     uint16 buffer_len, reply_len;
   5093     int sess_id = 0;
   5094     _bcm_oam_endpoint_t *endpoint_p;
   5095     int endpoint_index;
   5096 #endif
   5097 
   5098     SET_OAM_INFO;
   5099 
   5100     CHECK_INIT;
   5101 
   5102     VALIDATE_GROUP_INDEX(group);
   5103 
   5104     SET_GROUP(group);
   5105 
   5106     if (!group_p->in_use)
   5107     {
   5108         return BCM_E_NOT_FOUND;
   5109     }
   5110 
   5111     BCM_IF_ERROR_RETURN(_bcm_en_oam_get_group(unit, group, group_p, group_info));
   5112 
   5113 #if defined(BCM_KATANA_SUPPORT)  && defined(INCLUDE_BHH)
   5114     if ((soc_feature(unit, soc_feature_bhh)) &&
   5115         !(oam_info_p->ukernel_not_ready)) {
   5116     /* Get the endpoint info of the group */
   5117       for (endpoint_index = 0; endpoint_index < oam_info_p->endpoint_count;
   5118             ++endpoint_index) {
   5119            SET_ENDPOINT(endpoint_index);
   5120 
   5121         if ((endpoint_p->in_use && endpoint_p->group_index == group) &&
   5122             ((endpoint_p->type == bcmOAMEndpointTypeBHHMPLS) ||
   5123             (endpoint_p->type == bcmOAMEndpointTypeBHHMPLSVccv))) {
   5124 
   5125             sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(oam_info_p, endpoint_index);
   5126 
   5127             BCM_IF_ERROR_RETURN
   5128                 (_bcm_en_oam_bhh_msg_send_receive(unit,
   5129                                                   MOS_MSG_SUBCLASS_BHH_SESS_GET,
   5130                                                   sess_id, 0,
   5131                                                   MOS_MSG_SUBCLASS_BHH_SESS_GET_REPLY,
   5132                                                   &reply_len));
   5133 
   5134             /* Pack control message data into DMA buffer */
   5135             buffer     = oam_info_p->dma_buffer;
   5136             buffer_ptr = bhh_sdk_msg_ctrl_sess_get_unpack(buffer, &msg);
   5137             buffer_len = buffer_ptr - buffer;
   5138             if (reply_len != buffer_len) {
   5139                 return BCM_E_INTERNAL;
   5140             } else {
   5141                 if(msg.fault_flags & BHH_BTE_EVENT_CCM_TIMEOUT){
   5142                     group_info->faults |= BCM_OAM_BHH_FAULT_CCM_TIMEOUT;
   5143                 }
   5144                 if(msg.fault_flags & BHH_BTE_EVENT_CCM_RDI){
   5145                     group_info->faults |= BCM_OAM_BHH_FAULT_CCM_RDI;
   5146                 }
   5147                 if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_LEVEL){
   5148                     group_info->faults |=
   5149                                  BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEG_LEVEL;
   5150                 }
   5151                 if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_ID){
   5152                     group_info->faults |=
   5153                                  BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEG_ID;
   5154                 }
   5155                 if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_MEP_ID){
   5156                     group_info->faults |=
   5157                                  BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEP_ID;
   5158                 }
   5159                 if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_PERIOD){
   5160                     group_info->faults |=
   5161                                  BCM_OAM_BHH_FAULT_CCM_UNKNOWN_PERIOD;
   5162                 }
   5163                 if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_PRIORITY){
   5164                     group_info->faults |=
   5165                                  BCM_OAM_BHH_FAULT_CCM_UNKNOWN_PRIORITY;
   5166                 }
   5167                 if(msg.fault_flags & BHH_BTE_EVENT_CSF_LOS) {
   5168                     group_info->faults |= BCM_OAM_ENDPOINT_BHH_FAULT_CSF_LOS;
   5169                 }
   5170                 if(msg.fault_flags & BHH_BTE_EVENT_CSF_FDI) {
   5171                     group_info->faults |= BCM_OAM_ENDPOINT_BHH_FAULT_CSF_FDI;
   5172                 }
   5173                 if(msg.fault_flags & BHH_BTE_EVENT_CSF_RDI) {
   5174                     group_info->faults |= BCM_OAM_ENDPOINT_BHH_FAULT_CSF_RDI;
   5175                 }
   5176             }
   5177         }
   5178      }
   5179   }
   5180 #endif /* BCM_KATANA_SUPPORT && INCLUDE_BHH */
   5181   return BCM_E_NONE;
   5182 }
   5183 
   5184 static int _bcm_en_oam_destroy_group(int unit, int group_index,
   5185     _bcm_oam_group_t *group_p)
   5186 {
   5187     maid_reduction_entry_t maid_reduction_entry;
   5188     ma_state_entry_t ma_state_entry;
   5189 
   5190     /* Remove all associated endpoints */
   5191     BCM_IF_ERROR_RETURN(bcm_en_oam_endpoint_destroy_all(unit, group_index));
   5192 
   5193     /* MAID_REDUCTION entry */
   5194 
   5195     soc_MAID_REDUCTIONm_field32_set(unit, &maid_reduction_entry, VALIDf, 0);
   5196 
   5197     SOC_IF_ERROR_RETURN(WRITE_MAID_REDUCTIONm(unit, MEM_BLOCK_ALL,
   5198         group_index, &maid_reduction_entry));
   5199 
   5200     /* MA_STATE entry */
   5201 
   5202     soc_MA_STATEm_field32_set(unit, &ma_state_entry, VALIDf, 0);
   5203 
   5204     SOC_IF_ERROR_RETURN(WRITE_MA_STATEm(unit, MEM_BLOCK_ALL, group_index,
   5205         &ma_state_entry));
   5206 
   5207     group_p->in_use = 0;
   5208 
   5209 #ifdef BCM_WARM_BOOT_SUPPORT
   5210     SOC_CONTROL_LOCK(unit);
   5211     SOC_CONTROL(unit)->scache_dirty = 1;
   5212     SOC_CONTROL_UNLOCK(unit);
   5213 #endif
   5214 
   5215     return BCM_E_NONE;
   5216 }
   5217 
   5218 /*
   5219  * Function:
   5220  *      bcm_en_oam_group_destroy
   5221  * Purpose:
   5222  *      Destroy an OAM group object.  All OAM endpoints associated
   5223  *      with the group will also be destroyed.
   5224  * Parameters:
   5225  *      unit - (IN) Unit number.
   5226  *      group - (IN) The ID of the OAM group object to destroy
   5227  * Returns:
   5228  *      BCM_E_XXX
   5229  * Notes:
   5230  */
   5231 int 
   5232 bcm_en_oam_group_destroy(
   5233     int unit, 
   5234     bcm_oam_group_t group)
   5235 {
   5236     _bcm_oam_info_t *oam_info_p;
   5237     _bcm_oam_group_t *group_p;
   5238 
   5239     SET_OAM_INFO;
   5240 
   5241     CHECK_INIT;
   5242 
   5243     VALIDATE_GROUP_INDEX(group);
   5244 
   5245     SET_GROUP(group);
   5246 
   5247     if (!group_p->in_use)
   5248     {
   5249         return BCM_E_NOT_FOUND;
   5250     }
   5251 
   5252     return _bcm_en_oam_destroy_group(unit, group, group_p);
   5253 }
   5254 
   5255 /*
   5256  * Function:
   5257  *      bcm_en_oam_group_destroy_all
   5258  * Purpose:
   5259  *      Destroy all OAM group objects.  All OAM endpoints will also be
   5260  *      destroyed.
   5261  * Parameters:
   5262  *      unit - (IN) Unit number.
   5263  * Returns:
   5264  *      BCM_E_XXX
   5265  * Notes:
   5266  */
   5267 int 
   5268 bcm_en_oam_group_destroy_all(
   5269     int unit)
   5270 {
   5271     _bcm_oam_info_t *oam_info_p;
   5272     _bcm_oam_group_t *group_p;
   5273     int group_index;
   5274 
   5275     SET_OAM_INFO;
   5276 
   5277     CHECK_INIT;
   5278 
   5279     for (group_index = 0; group_index < oam_info_p->group_count;
   5280         ++group_index)
   5281     {
   5282         SET_GROUP(group_index);
   5283 
   5284         if (group_p->in_use)
   5285         {
   5286             BCM_IF_ERROR_RETURN(_bcm_en_oam_destroy_group(unit, group_index,
   5287                 group_p));
   5288         }
   5289     }
   5290 
   5291     return BCM_E_NONE;
   5292 }
   5293 
   5294 /*
   5295  * Function:
   5296  *      bcm_en_oam_group_traverse
   5297  * Purpose:
   5298  *      Traverse the entire set of OAM groups, calling a specified
   5299  *      callback for each one
   5300  * Parameters:
   5301  *      unit - (IN) Unit number.
   5302  *      cb - (IN) A pointer to the callback function to call for each OAM group
   5303  *      user_data - (IN) Pointer to user data to supply in the callback
   5304  * Returns:
   5305  *      BCM_E_XXX
   5306  * Notes:
   5307  */
   5308 int 
   5309 bcm_en_oam_group_traverse(
   5310     int unit, 
   5311     bcm_oam_group_traverse_cb cb, 
   5312     void *user_data)
   5313 {
   5314     _bcm_oam_info_t *oam_info_p;
   5315     _bcm_oam_group_t *group_p;
   5316     int group_index;
   5317     bcm_oam_group_info_t group_info;
   5318 
   5319     SET_OAM_INFO;
   5320 
   5321     CHECK_INIT;
   5322 
   5323     if (cb == NULL)
   5324     {
   5325         return BCM_E_PARAM;
   5326     }
   5327 
   5328     for (group_index = 0; group_index < oam_info_p->group_count;
   5329         ++group_index)
   5330     {
   5331         SET_GROUP(group_index);
   5332 
   5333         if (group_p->in_use)
   5334         {
   5335             bcm_oam_group_info_t_init(&group_info);
   5336 
   5337             BCM_IF_ERROR_RETURN(_bcm_en_oam_get_group(unit, group_index,
   5338                 group_p, &group_info));
   5339 
   5340             BCM_IF_ERROR_RETURN(cb(unit, &group_info, user_data));
   5341         }
   5342     }
   5343 
   5344     return BCM_E_NONE;
   5345 }
   5346 
   5347 static int _bcm_en_oam_find_free_endpoint(SHR_BITDCL *endpoints,
   5348     int endpoint_count, int increment, int offset)
   5349 {
   5350     int endpoint_index;
   5351 
   5352     for (endpoint_index = 0; endpoint_index < endpoint_count;
   5353         endpoint_index += increment)
   5354     {
   5355         if (!SHR_BITGET(endpoints, endpoint_index + offset))
   5356         {
   5357             break;
   5358         }
   5359     }
   5360 
   5361     if (endpoint_index >= endpoint_count)
   5362     {
   5363         endpoint_index = -1;
   5364     }
   5365 
   5366     return endpoint_index + offset;
   5367 }
   5368 
   5369 static int _bcm_en_oam_quantize_ccm_period(int period)
   5370 {
   5371     int quantized_period;
   5372 
   5373     if (period == 0)
   5374     {
   5375         quantized_period = 0;
   5376     }
   5377     else
   5378     {
   5379         /* Find closest supported period */
   5380 
   5381         for (quantized_period = 1;
   5382             en_ccm_periods[quantized_period] !=
   5383                 _BCM_OAM_ENDPOINT_CCM_PERIOD_UNDEFINED; ++quantized_period)
   5384         {
   5385             if ((uint32)period < en_ccm_periods[quantized_period])
   5386             {
   5387                 break;
   5388             }
   5389         }
   5390 
   5391         if (quantized_period > 1)
   5392         {
   5393             if (en_ccm_periods[quantized_period] ==
   5394                 _BCM_OAM_ENDPOINT_CCM_PERIOD_UNDEFINED)
   5395             {
   5396                 /* Use the highest defined value */
   5397 
   5398                 --quantized_period;
   5399             }
   5400             else
   5401             {
   5402                 if (period - en_ccm_periods[quantized_period - 1] <
   5403                     en_ccm_periods[quantized_period] - period)
   5404                 {
   5405                     /* Closer to the lower value */
   5406 
   5407                     --quantized_period;
   5408                 }
   5409             }
   5410         }
   5411     }
   5412 
   5413     return quantized_period;
   5414 }
   5415 
   5416 static void _bcm_en_oam_make_rmep_key(int unit,
   5417     l3_entry_ipv4_unicast_entry_t *l3_key_p, uint16 name, int level, bcm_vlan_t vlan,
   5418     uint32 sglp)
   5419 {
   5420     sal_memset(l3_key_p, 0, sizeof(l3_entry_ipv4_unicast_entry_t));
   5421 
   5422     soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, l3_key_p, RMEP__MEPIDf, name);
   5423     soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, l3_key_p, RMEP__MDLf, level);
   5424     soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, l3_key_p, RMEP__VIDf, vlan);
   5425     soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, l3_key_p, RMEP__SGLPf, sglp);
   5426     soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, l3_key_p, KEY_TYPEf,
   5427         TR_L3_HASH_KEY_TYPE_RMEP);
   5428 }
   5429 
   5430 static int _bcm_en_oam_delete_rmep(int unit, _bcm_oam_endpoint_t *endpoint_p)
   5431 {
   5432     _bcm_oam_info_t *oam_info_p;
   5433     l3_entry_ipv4_unicast_entry_t l3_key;
   5434     rmep_entry_t rmep_entry;
   5435     ma_state_entry_t ma_state_entry;
   5436     int some_rmep_ccm_defect_counter = 0;
   5437     int current_some_rmep_ccm_defect = 0;
   5438     int some_rdi_defect_counter = 0;
   5439     int current_some_rdi_defect = 0;
   5440     int cur_rmep_ccm_defect = 0;
   5441     int cur_rmep_last_rdi = 0;
   5442     int rv = BCM_E_NONE;
   5443     int endpoint_index;
   5444 
   5445 
   5446     SET_OAM_INFO;
   5447 
   5448     sal_memset(&ma_state_entry, 0, sizeof(ma_state_entry_t));
   5449     SOC_IF_ERROR_RETURN(READ_MA_STATEm(unit, MEM_BLOCK_ANY,
   5450                                         endpoint_p->group_index,
   5451                                         &ma_state_entry));
   5452 
   5453     sal_memset(&rmep_entry, 0, sizeof(rmep_entry_t));
   5454     SOC_IF_ERROR_RETURN(READ_RMEPm(unit, MEM_BLOCK_ANY, endpoint_p->remote_index,
   5455                                     &rmep_entry));
   5456     cur_rmep_ccm_defect = soc_RMEPm_field32_get(unit, &rmep_entry,
   5457                                                 CURRENT_RMEP_CCM_DEFECTf);
   5458     cur_rmep_last_rdi = soc_RMEPm_field32_get(unit, &rmep_entry,
   5459                                                 CURRENT_RMEP_LAST_RDIf);
   5460 
   5461     if (cur_rmep_ccm_defect || cur_rmep_last_rdi) {
   5462         some_rmep_ccm_defect_counter = soc_MA_STATEm_field32_get(unit,
   5463                                                                 &ma_state_entry,
   5464                                                                 SOME_RMEP_CCM_DEFECT_COUNTERf);
   5465         current_some_rmep_ccm_defect = soc_MA_STATEm_field32_get(unit,
   5466                                                                 &ma_state_entry,
   5467                                                                 CURRENT_SOME_RMEP_CCM_DEFECTf);
   5468 
   5469         if (cur_rmep_ccm_defect && some_rmep_ccm_defect_counter > 0) {
   5470             --some_rmep_ccm_defect_counter;
   5471             soc_MA_STATEm_field32_set(unit, &ma_state_entry,
   5472                                         SOME_RMEP_CCM_DEFECT_COUNTERf,
   5473                                         some_rmep_ccm_defect_counter);
   5474 
   5475             if (some_rmep_ccm_defect_counter == 0) {
   5476                 current_some_rmep_ccm_defect = 0;
   5477                 soc_MA_STATEm_field32_set(unit, &ma_state_entry,
   5478                                         CURRENT_SOME_RMEP_CCM_DEFECTf,
   5479                                         current_some_rmep_ccm_defect);
   5480             }
   5481         }
   5482         some_rdi_defect_counter = soc_MA_STATEm_field32_get(unit,
   5483                                                         &ma_state_entry,
   5484                                                         SOME_RDI_DEFECT_COUNTERf);
   5485         current_some_rdi_defect = soc_MA_STATEm_field32_get(unit,
   5486                                                         &ma_state_entry,
   5487                                                         CURRENT_SOME_RDI_DEFECTf);
   5488         if (cur_rmep_last_rdi && some_rdi_defect_counter > 0) {
   5489             --some_rdi_defect_counter;
   5490             soc_MA_STATEm_field32_set(unit, &ma_state_entry,
   5491                                         SOME_RDI_DEFECT_COUNTERf,
   5492                                         some_rdi_defect_counter);
   5493             if (some_rdi_defect_counter == 0) {
   5494                 current_some_rdi_defect = 0;
   5495                 soc_MA_STATEm_field32_set(unit, &ma_state_entry,
   5496                                             CURRENT_SOME_RDI_DEFECTf,
   5497                                             current_some_rdi_defect);
   5498             }
   5499         }
   5500         SOC_IF_ERROR_RETURN(WRITE_MA_STATEm(unit, MEM_BLOCK_ALL,
   5501                                             endpoint_p->group_index,
   5502                                             &ma_state_entry));
   5503     }
   5504 
   5505     /* RMEP entry */
   5506     SOC_IF_ERROR_RETURN(soc_mem_field32_modify(unit, RMEPm, 
   5507                                         endpoint_p->remote_index, VALIDf, 0));
   5508 
   5509     /* L3 entry */
   5510     if (endpoint_p->vp != 0) {
   5511         _bcm_en_oam_make_rmep_key(unit, &l3_key, endpoint_p->name,
   5512             endpoint_p->level, 0, endpoint_p->vp);
   5513     } else {
   5514         _bcm_en_oam_make_rmep_key(unit, &l3_key, endpoint_p->name,
   5515             endpoint_p->level, endpoint_p->vlan, endpoint_p->glp);
   5516     }
   5517     
   5518     rv = soc_mem_delete(unit, L3_ENTRY_IPV4_UNICASTm,
   5519                         MEM_BLOCK_ALL, &l3_key);
   5520     if ((BCM_FAILURE(rv)) && (rv != BCM_E_NOT_FOUND)) {
   5521         /* The L3 entry may have got cleared as part of L3 init during a rc,
   5522          * ignore BCM_E_NOT_FOUND error.
   5523          */
   5524         return rv;
   5525     }
   5526 
   5527     /* Local control block */
   5528 
   5529     SHR_BITCLR(oam_info_p->remote_endpoints_in_use, endpoint_p->remote_index);
   5530 
   5531     for (endpoint_index = 0; endpoint_index < oam_info_p->remote_endpoint_count;
   5532          endpoint_index++)
   5533     {
   5534         if (SHR_BITGET(oam_info_p->remote_endpoints_in_use, endpoint_index))
   5535         {
   5536             break;
   5537         }
   5538     }
   5539 
   5540     /* None of endpoint is in use reset all CCM_DEFECT */
   5541     if (endpoint_index == oam_info_p->remote_endpoint_count)
   5542     {
   5543         soc_MA_STATEm_field32_set
   5544             (unit, &ma_state_entry, CURRENT_XCON_CCM_DEFECTf,
   5545              0);
   5546         soc_MA_STATEm_field32_set
   5547             (unit, &ma_state_entry, CURRENT_ERROR_CCM_DEFECTf,
   5548              0);
   5549         soc_MA_STATEm_field32_set
   5550             (unit, &ma_state_entry, STICKY_ERROR_CCM_DEFECTf,
   5551              0);
   5552         soc_MA_STATEm_field32_set
   5553             (unit, &ma_state_entry, ERROR_CCM_DEFECT_TIMESTAMPf,
   5554              0);
   5555         soc_MA_STATEm_field32_set
   5556             (unit, &ma_state_entry, ERROR_CCM_DEFECT_RECEIVE_CCMf,
   5557              0);
   5558         SOC_IF_ERROR_RETURN(WRITE_MA_STATEm(unit, MEM_BLOCK_ALL,
   5559                     endpoint_p->group_index,
   5560                     &ma_state_entry));
   5561     }
   5562 
   5563     oam_info_p->remote_endpoints[endpoint_p->remote_index] =
   5564         BCM_OAM_ENDPOINT_INVALID;
   5565 
   5566     return BCM_E_NONE;
   5567 }
   5568 
   5569 static int _bcm_en_oam_find_lmep(int unit, bcm_vlan_t vlan, uint32 sglp,
   5570     int *index_p, l3_entry_ipv4_unicast_entry_t *l3_entry_p)
   5571 {
   5572     l3_entry_ipv4_unicast_entry_t l3_key;
   5573     sal_memset(&l3_key, 0, sizeof(l3_entry_ipv4_unicast_entry_t));
   5574 
   5575     soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, &l3_key, LMEP__VIDf, vlan);
   5576 
   5577     soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, &l3_key, LMEP__SGLPf, sglp);
   5578 
   5579     soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, &l3_key, KEY_TYPEf,
   5580         TR_L3_HASH_KEY_TYPE_LMEP);
   5581 
   5582     return soc_mem_search(unit, L3_ENTRY_IPV4_UNICASTm, MEM_BLOCK_ANY,
   5583         index_p, &l3_key, l3_entry_p, 0);
   5584 }
   5585 
   5586 /*
   5587  * Function:
   5588  *      _bcm_en_oam_lm_search
   5589  * Purpose:
   5590  *      Find how may LM endpoints have been created with the same port and VLAN
   5591  * Parameters:
   5592  *      unit - (IN) Unit number.
   5593  *      current_endpoint_p - (IN) Pointer to an OAM endpoint structure
   5594  *      add - (IN) 1 = create,  0 = destroy
   5595  *      mdl_index - (OUT) Pointer to a sorted endpoint index
   5596  * Returns:
   5597  *      Number of endpoints that need to recreate FP entries
   5598  * Notes:
   5599  */
   5600 static int _bcm_en_oam_lm_search(
   5601 int unit, _bcm_oam_endpoint_t *current_endpoint_p, int add, int *mdl_index) 
   5602 {
   5603     int i, j, k, max_index = 0;
   5604     int level[LEVEL_COUNT];
   5605     _bcm_oam_info_t *oam_info_p;
   5606     _bcm_oam_endpoint_t *endpoint_p = NULL;
   5607 
   5608     if (!current_endpoint_p) {
   5609         return 0;
   5610     }
   5611 
   5612     for (i = 0; i < LEVEL_COUNT; i++) {
   5613         mdl_index[i] = -1;
   5614         level[i] = LEVEL_COUNT;
   5615     }
   5616 
   5617     SET_OAM_INFO;
   5618 
   5619     for (i = 0; i < oam_info_p->endpoint_count; i++) {
   5620 
   5621         SET_ENDPOINT(i);
   5622 
   5623         if ((endpoint_p == current_endpoint_p) && (add == 0)) {
   5624             /* Skip current endpoint in destroy case */
   5625             continue;
   5626         }
   5627 
   5628         if ((endpoint_p->in_use || (add != 0)) &&
   5629            (endpoint_p->glp == current_endpoint_p->glp) &&
   5630            (endpoint_p->vlan == current_endpoint_p->vlan) &&
   5631            (endpoint_p->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT)) {
   5632             /* Different MDL LM endpoints found. Save index in MDL order */
   5633             for (j = 0; j < LEVEL_COUNT && mdl_index[j] != -1; j++) {
   5634                 if (endpoint_p->level < level[j]) {
   5635                     for (k = max_index; k > j; k--) {
   5636                         if (mdl_index[k-1] != -1) {
   5637                             mdl_index[k] = mdl_index[k-1];
   5638                             level[k] = level[k-1];
   5639                         }
   5640                     }
   5641                     mdl_index[j] = i;
   5642                     level[j] = endpoint_p->level;
   5643                     break;
   5644                 } else if ((j == (max_index-1)) && (j < MAX_ENDPOINT_LEVEL)) {
   5645                     mdl_index[j+1] = i;
   5646                     level[j+1] = endpoint_p->level;
   5647                     break;
   5648                 }
   5649             }
   5650             /* Use the same LM counter index */
   5651             if ((endpoint_p != current_endpoint_p) && (add != 0)) {
   5652                 current_endpoint_p->lm_counter_index = endpoint_p->lm_counter_index;
   5653                 current_endpoint_p->pri_map_index = endpoint_p->pri_map_index;
   5654             }
   5655 
   5656             /* Save first element for destroy case */
   5657             if (max_index == 0) {
   5658                 mdl_index[0] = i;
   5659                 level[0] = endpoint_p->level;
   5660             }
   5661             max_index++;
   5662             /* Destory entry and reinstall later */
   5663             if (endpoint_p != current_endpoint_p) {
   5664                 _bcm_en_oam_uninstall_fp(unit, endpoint_p);
   5665             }
   5666         }
   5667     }
   5668 
   5669     return max_index;
   5670 }
   5671 
   5672 static int _bcm_en_oam_delete_lmep(int unit,
   5673     _bcm_oam_endpoint_t *endpoint_p)
   5674 {
   5675     _bcm_oam_info_t *oam_info_p;
   5676     _bcm_oam_endpoint_t *current_endpoint_p;
   5677     int i, j, l3_index, num_lm, mdl_index[LEVEL_COUNT];
   5678     l3_entry_ipv4_unicast_entry_t l3_entry;
   5679     uint32 level_bitmap;
   5680     int result = SOC_E_NONE;
   5681     lmep_entry_t lmep_entry;
   5682 
   5683     SET_OAM_INFO;
   5684 
   5685     if (endpoint_p->local_tx_enabled)
   5686     {
   5687         /* LMEP entry */
   5688 
   5689         sal_memset(&lmep_entry, 0, sizeof(lmep_entry_t)); 
   5690         WRITE_LMEPm(unit, MEM_BLOCK_ALL,
   5691          endpoint_p->local_tx_index, &lmep_entry); 
   5692 
   5693         /* Local control block */
   5694 
   5695         SHR_BITCLR(oam_info_p->local_tx_endpoints_in_use,
   5696             endpoint_p->local_tx_index);
   5697     }
   5698 
   5699     if (endpoint_p->local_rx_enabled)
   5700     {
   5701         /* MA_INDEX entry doesn't need to be touched */
   5702 
   5703         /* L3 entry */
   5704 
   5705         L3_LOCK(unit);
   5706 
   5707         if (BCM_SUCCESS(_bcm_en_oam_find_lmep(unit, endpoint_p->vlan,
   5708             endpoint_p->glp, &l3_index, &l3_entry)) || 
   5709             BCM_SUCCESS(_bcm_en_oam_find_lmep(unit, 0,
   5710             endpoint_p->vp, &l3_index, &l3_entry)))
   5711         {
   5712             level_bitmap = soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit,
   5713                 &l3_entry, LMEP__MDL_BITMAPf);
   5714 
   5715             level_bitmap &= ~(1 << endpoint_p->level);
   5716 
   5717             if (level_bitmap != 0)
   5718             {
   5719                 /* Still endpoints here at other levels */
   5720 
   5721                 result = soc_mem_field32_modify(unit, L3_ENTRY_IPV4_UNICASTm,
   5722                     l3_index, LMEP__MDL_BITMAPf, level_bitmap);
   5723             }
   5724             else
   5725             {
   5726                 /* No endpoints left here at any level */
   5727 
   5728                 result = soc_mem_field32_modify(unit, L3_ENTRY_IPV4_UNICASTm,
   5729                     l3_index, VALIDf, 0);
   5730             }
   5731         }
   5732 
   5733         L3_UNLOCK(unit);
   5734 
   5735         if ((BCM_FAILURE(result)) && (result != BCM_E_NOT_FOUND)) {
   5736             /* The L3 entry may have got cleared as part of L3 init during a rc,
   5737              * ignore BCM_E_NOT_FOUND error.
   5738              */
   5739             return result;
   5740         }
   5741 
   5742         /* Local control block */
   5743         SHR_BITCLR(oam_info_p->local_rx_endpoints_in_use,
   5744             endpoint_p->local_rx_index);
   5745 
   5746 #if defined(BCM_KATANA_SUPPORT)
   5747         if (SOC_IS_KATANAX(unit)) {
   5748             result = soc_profile_mem_delete(unit, oam_opcode_profile[unit],
   5749                                             endpoint_p->opcode_profile_index);
   5750             endpoint_p->opcode_profile_index = 0;
   5751         }
   5752 #endif /* BCM_KATANA_SUPPORT */
   5753         
   5754         _bcm_en_oam_uninstall_vfp(unit, endpoint_p);
   5755         _bcm_en_oam_uninstall_fp(unit, endpoint_p);
   5756 
   5757         if (endpoint_p->lm_counter_index != BCM_OAM_LM_COUNTER_INDEX_INVALID) {
   5758             num_lm = _bcm_en_oam_lm_search(unit, endpoint_p, 0, mdl_index);
   5759             if (num_lm == 0) {
   5760                 SHR_BITCLR(oam_info_p->lm_counter_in_use,
   5761                     endpoint_p->lm_counter_index);
   5762                 SOC_IF_ERROR_RETURN(
   5763                     soc_profile_mem_delete(unit, ing_pri_map_profile[unit],
   5764                     endpoint_p->pri_map_index*BCM_OAM_INTPRI_MAX));
   5765             } else {
   5766                 for (i = 0; i < num_lm; i++) {
   5767                     current_endpoint_p = oam_info_p->endpoints + mdl_index[i];
   5768                        BCM_IF_ERROR_RETURN(
   5769                            _bcm_en_oam_install_fp(unit, (i == (num_lm-1)) ? 0 : 1, current_endpoint_p));
   5770                     BCM_IF_ERROR_RETURN(
   5771                         bcm_esw_field_entry_install(unit, current_endpoint_p->fp_entry_tx));
   5772                     BCM_IF_ERROR_RETURN(
   5773                         bcm_esw_field_entry_install(unit, current_endpoint_p->fp_entry_rx));
   5774                     for (j = 0; j < BCM_SWITCH_TRUNK_MAX_PORTCNT; j++) {
   5775                         if (current_endpoint_p->fp_entry_trunk[j]) {
   5776                             BCM_IF_ERROR_RETURN(
   5777                                 bcm_esw_field_entry_install(unit, current_endpoint_p->fp_entry_trunk[j]));
   5778                         }
   5779                     }
   5780                 }
   5781             }
   5782             endpoint_p->lm_counter_index = BCM_OAM_LM_COUNTER_INDEX_INVALID;
   5783             endpoint_p->pri_map_index = 0;
   5784         }
   5785     }
   5786     return result;
   5787 }
   5788 
   5789 #if defined(BCM_KATANA_SUPPORT)
   5790 static int _bcm_kt_set_oam_opcode_profile_entry(int unit,
   5791     uint32 flags, uint32 *entry)
   5792 {
   5793     uint32 i, opcode;
   5794 
   5795     for (i=0; i<31; i++) {
   5796 
   5797         opcode = flags & (1 << i);
   5798 
   5799         switch (opcode) {
   5800             case BCM_OAM_OPCODE_CCM_IN_HW:
   5801                 soc_OAM_OPCODE_CONTROL_PROFILEm_field32_set(unit, entry, CCM_PROCESS_IN_HWf, 1);
   5802                 break;
   5803 
   5804             case BCM_OAM_OPCODE_CCM_COPY_TO_CPU:
   5805                 soc_OAM_OPCODE_CONTROL_PROFILEm_field32_set(unit, entry, CCM_COPYTO_CPUf, 1);
   5806                 break;
   5807 
   5808             case BCM_OAM_OPCODE_CCM_DROP:
   5809                 soc_OAM_OPCODE_CONTROL_PROFILEm_field32_set(unit, entry, CCM_DROPf, 1);
   5810                 break;
   5811 
   5812             case BCM_OAM_OPCODE_LBM_IN_HW:
   5813                 soc_OAM_OPCODE_CONTROL_PROFILEm_field32_set(unit, entry, LBM_PROCESS_IN_HWf, 1);
   5814                 break;
   5815 
   5816             case BCM_OAM_OPCODE_LBM_UC_COPY_TO_CPU:
   5817                 soc_OAM_OPCODE_CONTROL_PROFILEm_field32_set(unit, entry, LBM_UC_COPYTO_CPUf, 1);
   5818                 break;
   5819             case BCM_OAM_OPCODE_LBM_UC_DROP:
   5820                 soc_OAM_OPCODE_CONTROL_PROFILEm_field32_set(unit, entry, LBM_UC_DROPf, 1);
   5821                 break;
   5822 
   5823             case BCM_OAM_OPCODE_LBM_MC_COPY_TO_CPU:
   5824                 soc_OAM_OPCODE_CONTROL_PROFILEm_field32_set(unit, entry, LBM_MC_COPYTO_CPUf, 1);
   5825                 break;
   5826 
   5827             case BCM_OAM_OPCODE_LBM_MC_DROP:
   5828                 soc_OAM_OPCODE_CONTROL_PROFILEm_field32_set(unit, entry, LBM_MC_DROPf, 1);
   5829                 break;
   5830 
   5831             case BCM_OAM_OPCODE_LBR_COPY_TO_CPU:
   5832                 soc_OAM_OPCODE_CONTROL_PROFILEm_field32_set(unit, entry, LBR_COPYTO_CPUf, 1);
   5833                 break;
   5834 
   5835             case BCM_OAM_OPCODE_LBR_DROP:
   5836                 soc_OAM_OPCODE_CONTROL_PROFILEm_field32_set(unit, entry, LBR_DROPf, 1);
   5837                 break;
   5838 
   5839             case BCM_OAM_OPCODE_LTM_COPY_TO_CPU:
   5840                 soc_OAM_OPCODE_CONTROL_PROFILEm_field32_set(unit, entry, LTM_COPYTO_CPUf, 1);
   5841                 break;
   5842 
   5843             case BCM_OAM_OPCODE_LTM_DROP:
   5844                 soc_OAM_OPCODE_CONTROL_PROFILEm_field32_set(unit, entry, LTM_DROPf, 1);
   5845                 break;
   5846             case BCM_OAM_OPCODE_LTR_COPY_TO_CPU:
   5847                 soc_OAM_OPCODE_CONTROL_PROFILEm_field32_set(unit, entry, LTR_COPYTO_CPUf, 1);
   5848                 break;
   5849 
   5850             case BCM_OAM_OPCODE_LTR_DROP:
   5851                 soc_OAM_OPCODE_CONTROL_PROFILEm_field32_set(unit, entry, LTR_DROPf, 1);
   5852                 break;
   5853 
   5854             case BCM_OAM_OPCODE_LMEP_PKT_FWD:
   5855                 soc_OAM_OPCODE_CONTROL_PROFILEm_field32_set(unit, entry, FWD_LMEP_PKTf, 1);
   5856                 break;
   5857 
   5858             case BCM_OAM_OPCODE_OTHER_COPY_TO_CPU:
   5859                 soc_OAM_OPCODE_CONTROL_PROFILEm_field32_set(unit, entry, OTHER_OPCODE_COPYTO_CPUf, 1);
   5860                 break;
   5861 
   5862             case BCM_OAM_OPCODE_OTHER_DROP:
   5863                 soc_OAM_OPCODE_CONTROL_PROFILEm_field32_set(unit, entry, OTHER_OPCODE_DROPf, 1);
   5864                 break;
   5865 
   5866             default:
   5867                 break;
   5868         }
   5869     }
   5870 
   5871     return BCM_E_NONE;
   5872 }
   5873 
   5874 static int _bcm_kt_get_default_oam_opcode_profile_entry(int unit,
   5875                                         uint32 *entry)
   5876 {
   5877     uint32 opcode_flags;
   5878 
   5879     opcode_flags =  BCM_OAM_OPCODE_CCM_COPY_TO_CPU |
   5880                     BCM_OAM_OPCODE_CCM_DROP |
   5881                     BCM_OAM_OPCODE_LBM_UC_COPY_TO_CPU |
   5882                     BCM_OAM_OPCODE_LBM_UC_DROP |
   5883                     BCM_OAM_OPCODE_LBM_MC_COPY_TO_CPU |
   5884                     BCM_OAM_OPCODE_LBM_MC_DROP |
   5885                     BCM_OAM_OPCODE_LBR_COPY_TO_CPU |
   5886                     BCM_OAM_OPCODE_LBR_DROP |
   5887                     BCM_OAM_OPCODE_LTM_COPY_TO_CPU |
   5888                     BCM_OAM_OPCODE_LTM_DROP |
   5889                     BCM_OAM_OPCODE_LTR_COPY_TO_CPU |
   5890                     BCM_OAM_OPCODE_LTR_DROP |
   5891                     BCM_OAM_OPCODE_OTHER_COPY_TO_CPU |
   5892                     BCM_OAM_OPCODE_OTHER_DROP;
   5893 
   5894     _bcm_kt_set_oam_opcode_profile_entry(unit, opcode_flags, entry);
   5895 
   5896     return BCM_E_NONE;
   5897 }
   5898 
   5899 #endif /* BCM_KATANA_SUPPORT */
   5900 
   5901 /*
   5902  * Function:
   5903  *      _bcm_en_oam_destroy_endpoint
   5904  * Purpose:
   5905  *      Destroy an OAM endpoint object
   5906  * Parameters:
   5907  *      unit - (IN) Unit number.
   5908  *      endpoint_p - (IN) Pointer to an OAM endpoint structure
   5909  * Returns:
   5910  *      BCM_E_XXX
   5911  * Notes:
   5912  */
   5913 static int _bcm_en_oam_destroy_endpoint(int unit,
   5914 					_bcm_oam_endpoint_t *endpoint_p)
   5915 {
   5916 #if defined(BCM_KATANA_SUPPORT) && defined(INCLUDE_BHH)
   5917     _bcm_oam_info_t *oam_info_p;
   5918     uint16 reply_len;
   5919     int sess_id = 0;
   5920 
   5921     SET_OAM_INFO;
   5922 #endif
   5923 
   5924     if (endpoint_p->type == bcmOAMEndpointTypeEthernet) 
   5925     {
   5926 	if (endpoint_p->is_remote)
   5927 	{
   5928 	    BCM_IF_ERROR_RETURN(_bcm_en_oam_delete_rmep(unit, endpoint_p));
   5929 	}
   5930 	else
   5931 	{
   5932 	    BCM_IF_ERROR_RETURN(_bcm_en_oam_delete_lmep(unit, endpoint_p));
   5933 	}
   5934     } 
   5935     /*
   5936      * BHH specific
   5937      */
   5938     else if (soc_feature(unit, soc_feature_bhh) && 
   5939         ((endpoint_p->type == bcmOAMEndpointTypeBHHMPLS) ||
   5940         (endpoint_p->type == bcmOAMEndpointTypeBHHMPLSVccv)))
   5941     {
   5942 #if defined(BCM_KATANA_SUPPORT) && defined(INCLUDE_BHH)
   5943 	if (endpoint_p->is_remote) {
   5944 	    /* 
   5945 	     * BHH uses same index for local and remote.  So, delete always goes through
   5946          * local endpoint destory
   5947 	     */
   5948          return BCM_E_NONE;
   5949 	} else {
   5950         sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(oam_info_p, endpoint_p->bhh_endpoint_index);
   5951 	    /* 
   5952 	     * Delete BHH Session in HW 
   5953 	     */
   5954 	    BCM_IF_ERROR_RETURN
   5955 		(_bcm_en_oam_bhh_session_hw_delete(unit, endpoint_p));
   5956 
   5957 	    /* 
   5958 	     * Send BHH Session Delete message to uC 
   5959 	     */
   5960 	    BCM_IF_ERROR_RETURN
   5961 		(_bcm_en_oam_bhh_msg_send_receive(unit,
   5962 						  MOS_MSG_SUBCLASS_BHH_SESS_DELETE,
   5963 						  sess_id, 0,
   5964 						  MOS_MSG_SUBCLASS_BHH_SESS_DELETE_REPLY,
   5965 						  &reply_len));
   5966 
   5967 	    if (reply_len != 0) {
   5968 		return BCM_E_INTERNAL;
   5969 	    }
   5970 	}
   5971 
   5972 	endpoint_p->bhh_endpoint_index = -1;
   5973 #else 
   5974     return (BCM_E_UNAVAIL);
   5975 #endif
   5976     }
   5977     else {
   5978         return (BCM_E_PARAM);
   5979     }
   5980 
   5981     sal_memset(endpoint_p,0,sizeof(_bcm_oam_endpoint_t));
   5982     endpoint_p->in_use = 0;
   5983     endpoint_p->lm_counter_index = BCM_OAM_LM_COUNTER_INDEX_INVALID;
   5984 
   5985     return BCM_E_NONE;
   5986 }
   5987 
   5988 /*
   5989  * Function:
   5990  *     _bcm_en_oam_mepid_validate
   5991  * Purpose:
   5992  *     Validate an endpoint MEP id.
   5993  * Parameters:
   5994  *     unit      - (IN) BCM device number
   5995  *     ep_info_p - (IN) Pointer to endpoint information.
   5996  * Retruns:
   5997  *     BCM_E_XXX
   5998  */
   5999 STATIC int
   6000 _bcm_en_oam_mepid_validate(int unit,
   6001                             bcm_oam_endpoint_info_t *endpoint_info)
   6002 {
   6003     _bcm_oam_info_t *oam_info_p;
   6004     _bcm_oam_endpoint_t *endpoint_p;
   6005     int endpoint_index;
   6006 
   6007     SET_OAM_INFO;
   6008 
   6009     if (endpoint_info->flags & BCM_OAM_ENDPOINT_REPLACE) {
   6010         return BCM_E_NONE;
   6011     }
   6012 
   6013     for (endpoint_index = 0; endpoint_index < oam_info_p->endpoint_count;
   6014          ++endpoint_index) {
   6015         SET_ENDPOINT(endpoint_index);
   6016         if (endpoint_p->in_use &&
   6017             endpoint_p->group_index == endpoint_info->group) {
   6018             if (endpoint_p->name == endpoint_info->name) {
   6019                 return BCM_E_PARAM;
   6020           }
   6021         }
   6022     }
   6023     return BCM_E_NONE;
   6024 }
   6025 
   6026 /*
   6027  * Function:
   6028  *      _bcm_en_oam_create_endpoint
   6029  * Purpose:
   6030  *      Create or replace an OAM endpoint object
   6031  * Parameters:
   6032  *      unit - (IN) Unit number.
   6033  *      endpoint_info - (IN/OUT) Pointer to an OAM endpoint structure
   6034  * Returns:
   6035  *      BCM_E_XXX
   6036  * Notes:
   6037  */
   6038 static int 
   6039 _bcm_en_oam_create_endpoint(
   6040     int unit, 
   6041     bcm_oam_endpoint_info_t *endpoint_info,
   6042     _bcm_oam_endpoint_t **created_endpoint_p,
   6043     int *num_lm, int *mdl_index)
   6044 {
   6045     _bcm_oam_info_t *oam_info_p;
   6046     _bcm_oam_group_t *group_p;
   6047     _bcm_oam_endpoint_t *endpoint_p, *current_endpoint_p;
   6048     int i, replace, mdl_set = 0, replace_l3_entry = 0;
   6049     int is_remote, is_local;
   6050     int local_tx_enabled = 0;
   6051     int local_rx_enabled = 0;
   6052     int endpoint_index = 0;
   6053     bcm_module_t module_id = -1;
   6054     bcm_port_t port_id = -1;
   6055     bcm_trunk_t trunk_id = BCM_TRUNK_INVALID;
   6056     int local_id = -1;
   6057     uint32 vp = 0;
   6058     rmep_entry_t rmep_entry;
   6059     lmep_entry_t lmep_entry;
   6060     lmep_1_entry_t lmep1_entry;
   6061     ma_index_entry_t ma_index_entry;
   6062     l3_entry_ipv4_unicast_entry_t l3_entry, l3_key;
   6063     int quantization_index;
   6064     int l3_index;
   6065     uint32 level_bitmap, mem_entries[BCM_OAM_INTPRI_MAX], temp_index;
   6066     int result = 0;
   6067     void *entries[1];
   6068     uint32 oam_current_time;
   6069 #if defined(BCM_KATANA_SUPPORT)
   6070     uint32 opcode_entry = 0;
   6071 #if defined(INCLUDE_BHH)
   6072     bhh_sdk_msg_ctrl_sess_set_t msg_sess;
   6073     bhh_sdk_msg_ctrl_rmep_create_t msg_rmep_create;
   6074     uint8 *buffer, *buffer_ptr;
   6075     uint16 buffer_len, reply_len;
   6076     int encap = 0;
   6077     uint32 session_flags;
   6078     uint8 group_sw_rdi = 0;
   6079 #endif /* INCLUDE_BHH */
   6080 #endif /* BCM_KATANA_SUPPORT */
   6081     int rv = BCM_E_NONE;
   6082     uint32 src_glp = _BCM_OAM_INVALID_INDEX;
   6083     uint32 dst_glp = _BCM_OAM_INVALID_INDEX;
   6084     bcm_trunk_member_t *member_array = NULL;
   6085     int member_count;
   6086     bcm_gport_t member_gport;
   6087     bcm_trunk_t tgid_out;
   6088     int id_out;
   6089 #if defined(BCM_KATANA_SUPPORT)  && defined(INCLUDE_BHH)
   6090     int eth_oam_endpoint_count = 0;
   6091 #endif
   6092     int endpoint_start_index = 0;
   6093     int endpoint_end_index = 0;
   6094 
   6095     SET_OAM_INFO;
   6096 
   6097     CHECK_INIT;
   6098 
   6099     VALIDATE_GROUP_INDEX(endpoint_info->group);
   6100 
   6101     if (endpoint_info->level > MAX_ENDPOINT_LEVEL)
   6102     {
   6103         /* Exceeds supported MDL level 0 - 7. */
   6104         return BCM_E_PARAM;
   6105     }
   6106 
   6107     /* Supported MEPID Name range is 1 - 8191, Skipping range check for MIP */
   6108     if (((endpoint_info->name < _BCM_OAM_EP_NAME_MIN)
   6109          || (endpoint_info->name > _BCM_OAM_EP_NAME_MAX)) &&
   6110          !(endpoint_info->flags & BCM_OAM_ENDPOINT_INTERMEDIATE)) {
   6111         LOG_ERROR(BSL_LS_BCM_OAM,
   6112                  (BSL_META_U(unit,
   6113                              "OAM Error: MEP Name should be in the range(%d-%d).\n"),
   6114                   _BCM_OAM_EP_NAME_MIN, _BCM_OAM_EP_NAME_MAX));
   6115        return (BCM_E_PARAM);
   6116     }
   6117 
   6118     /* Endpoint MIP's are not created with non-zero ccm period */
   6119     if ((endpoint_info->flags & BCM_OAM_ENDPOINT_INTERMEDIATE) &&
   6120         (endpoint_info->ccm_period != BCM_OAM_ENDPOINT_CCM_PERIOD_DISABLED)) {
   6121          return (BCM_E_PARAM);
   6122     }
   6123 
   6124     if (endpoint_info->flags & UNSUPPORTED_ENDPOINT_FLAGS)
   6125     {
   6126         return BCM_E_UNAVAIL;
   6127     }
   6128 
   6129     if (endpoint_info->type != bcmOAMEndpointTypeEthernet)
   6130     {
   6131 #if defined(BCM_ENDURO_SUPPORT)
   6132         if (SOC_IS_ENDURO(unit))
   6133         {
   6134             /* Device supports Ethernet OAM only. */
   6135             return BCM_E_UNAVAIL;
   6136         }
   6137 #endif
   6138 #if defined(BCM_KATANA_SUPPORT)  && defined(INCLUDE_BHH)
   6139         if ((endpoint_info->type != bcmOAMEndpointTypeBHHMPLS) &&
   6140             (endpoint_info->type != bcmOAMEndpointTypeBHHMPLSVccv))
   6141 #endif
   6142         {
   6143             return BCM_E_UNAVAIL;
   6144         }
   6145 #if defined(BCM_KATANA_SUPPORT)  && defined(INCLUDE_BHH)
   6146         if((endpoint_info->type == bcmOAMEndpointTypeBHHMPLS) ||
   6147            (endpoint_info->type == bcmOAMEndpointTypeBHHMPLSVccv))
   6148             {
   6149                 if (oam_info_p->ukernel_not_ready == 1) {
   6150                     LOG_ERROR(BSL_LS_BCM_OAM,
   6151                               (BSL_META_U(unit,
   6152                                           "OAM(unit %d) Error: BTE(ukernel) "
   6153                                           "not ready.\n"), unit));
   6154                     return (BCM_E_INIT);
   6155                 }
   6156             }
   6157         if ((endpoint_info->type == bcmOAMEndpointTypeBHHMPLSVccv) && 
   6158             (endpoint_info->vccv_type > bcmOamBhhVccvTtl))
   6159         {
   6160             LOG_ERROR(BSL_LS_BCM_OAM,
   6161                     (BSL_META_U(unit,
   6162                                 "BHH Error: vccv type %d not supported (EP=%d)\n"),
   6163                      endpoint_info->vccv_type, endpoint_info->id));
   6164             return (BCM_E_PARAM);
   6165         }
   6166 #endif
   6167     } 
   6168 
   6169     replace = ((endpoint_info->flags & BCM_OAM_ENDPOINT_REPLACE) != 0);
   6170 
   6171     if (endpoint_info->flags & BCM_OAM_ENDPOINT_REMOTE)
   6172     {
   6173         if (endpoint_info->flags &
   6174             (BCM_OAM_ENDPOINT_CCM_RX | BCM_OAM_ENDPOINT_LOOPBACK |
   6175 	     BCM_OAM_ENDPOINT_DELAY_MEASUREMENT | BCM_OAM_ENDPOINT_LINKTRACE |
   6176 	     BCM_OAM_ENDPOINT_LOSS_MEASUREMENT | 
   6177 	     BCM_OAM_ENDPOINT_PORT_STATE_TX | 
   6178 	     BCM_OAM_ENDPOINT_INTERFACE_STATE_TX ))
   6179         {
   6180             /* Specified flags aren't valid for RMEPs */
   6181 
   6182             return BCM_E_PARAM;
   6183         }
   6184 
   6185         is_remote = 1;
   6186     }
   6187     else
   6188     {
   6189         /* Local */
   6190         is_remote = 0;
   6191 
   6192         local_tx_enabled = 
   6193             (endpoint_info->ccm_period != BCM_OAM_ENDPOINT_CCM_PERIOD_DISABLED);
   6194 
   6195         local_rx_enabled = ((endpoint_info->flags &
   6196 			     (BCM_OAM_ENDPOINT_CCM_RX | BCM_OAM_ENDPOINT_LOOPBACK |
   6197 			      BCM_OAM_ENDPOINT_DELAY_MEASUREMENT |
   6198 			      BCM_OAM_ENDPOINT_LOSS_MEASUREMENT |
   6199 			      BCM_OAM_ENDPOINT_LINKTRACE)) != 0);
   6200     }
   6201 
   6202     if (soc_feature(unit, soc_feature_bhh)) {
   6203 #if defined(BCM_KATANA_SUPPORT)  && defined(INCLUDE_BHH)
   6204     eth_oam_endpoint_count = oam_info_p->remote_endpoint_count +
   6205         oam_info_p->local_tx_endpoint_count + oam_info_p->local_rx_endpoint_count;
   6206 #endif
   6207     }
   6208 
   6209     if (endpoint_info->flags & BCM_OAM_ENDPOINT_WITH_ID)
   6210     {
   6211         endpoint_index = endpoint_info->id;
   6212 
   6213         if (soc_feature(unit, soc_feature_bhh)) {
   6214 #if defined(BCM_KATANA_SUPPORT)  && defined(INCLUDE_BHH)
   6215         if ((endpoint_info->type == bcmOAMEndpointTypeEthernet) &&
   6216             (endpoint_index >= eth_oam_endpoint_count))
   6217         {
   6218             return BCM_E_PARAM;
   6219         }
   6220         else if (((endpoint_info->type == bcmOAMEndpointTypeBHHMPLS) ||
   6221                   (endpoint_info->type == bcmOAMEndpointTypeBHHMPLSVccv)) &&
   6222                  (endpoint_index < eth_oam_endpoint_count))
   6223         {
   6224             return BCM_E_PARAM;
   6225         }
   6226 #endif
   6227         }
   6228 
   6229         VALIDATE_ENDPOINT_INDEX(endpoint_index);
   6230 
   6231         if (replace && (!oam_info_p->endpoints[endpoint_index].in_use))
   6232         {
   6233             return BCM_E_NOT_FOUND;
   6234         }
   6235         else if (!replace && (oam_info_p->endpoints[endpoint_index].in_use))
   6236         {
   6237             return BCM_E_EXISTS;
   6238         }
   6239     }
   6240     else
   6241     {
   6242         if (replace)
   6243         {
   6244             /* Replace specified with no ID */
   6245 
   6246             return BCM_E_PARAM;
   6247         }
   6248 
   6249         endpoint_start_index = 0;
   6250         endpoint_end_index = oam_info_p->endpoint_count;
   6251 
   6252         if (soc_feature(unit, soc_feature_bhh)) {
   6253 #if defined(BCM_KATANA_SUPPORT)  && defined(INCLUDE_BHH)
   6254         if(endpoint_info->type == bcmOAMEndpointTypeEthernet)
   6255         {
   6256             endpoint_start_index = 0;
   6257             endpoint_end_index = eth_oam_endpoint_count;
   6258         }
   6259         else
   6260         {
   6261             endpoint_start_index = eth_oam_endpoint_count;
   6262             endpoint_end_index = oam_info_p->endpoint_count;
   6263         }
   6264 #endif
   6265         }
   6266 
   6267         if (soc_feature(unit, soc_feature_bhh)) {
   6268 #if defined(BCM_KATANA_SUPPORT)  && defined(INCLUDE_BHH)
   6269         /* BHH uses local and remote same index */
   6270         if((endpoint_info->type != bcmOAMEndpointTypeEthernet) &&
   6271             (endpoint_info->flags & BCM_OAM_ENDPOINT_REMOTE))
   6272         {
   6273             endpoint_index = endpoint_info->local_id;
   6274         }
   6275 #endif
   6276         }
   6277 
   6278         /*
   6279          * Non-remote BHH EP.  Get new ID 
   6280          */
   6281         if(!endpoint_index) {
   6282             for (endpoint_index = endpoint_start_index; endpoint_index < endpoint_end_index;
   6283 	            ++endpoint_index)
   6284             {
   6285                 if (!oam_info_p->endpoints[endpoint_index].in_use)
   6286                 {
   6287                     break;
   6288                 }
   6289             }
   6290 
   6291             if (endpoint_index >= oam_info_p->endpoint_count)
   6292             {
   6293                 return BCM_E_FULL;
   6294             }
   6295         
   6296             endpoint_info->id = endpoint_index;
   6297 
   6298         }
   6299     }
   6300 
   6301     SET_ENDPOINT(endpoint_index);
   6302     *created_endpoint_p = endpoint_p;
   6303     SET_GROUP(endpoint_info->group);
   6304 
   6305     if (!group_p->in_use)
   6306     {
   6307         /* Associating to a nonexistent group */
   6308 
   6309         return BCM_E_PARAM;
   6310     }
   6311 
   6312     /*
   6313      * As per IEEE 802.1ag specifications,the MEP ID
   6314      * should be unique within an OAM group.
   6315      */
   6316     if(_bcm_en_oam_mepid_validate(unit, endpoint_info)) {
   6317         LOG_ERROR(BSL_LS_BCM_OAM,
   6318                   (BSL_META_U(unit,
   6319                               "OAM Error: MEPID:%x passed is not unique in group %x\n"),
   6320                    endpoint_info->name, endpoint_info->group));
   6321 
   6322         return (BCM_E_EXISTS);
   6323     }
   6324 
   6325     /* Get Trunk ID or (Modid + Port) value from Gport */
   6326     BCM_IF_ERROR_RETURN
   6327         (_bcm_esw_gport_resolve(unit, endpoint_info->gport, &module_id,
   6328                                 &port_id, &trunk_id, &local_id));
   6329 
   6330     /* 
   6331      * If Gport is Trunk type, _bcm_esw_gport_resolve() 
   6332      * sets trunk_id. Using Trunk ID, get Dst Modid and Port value.
   6333      */
   6334     if (BCM_GPORT_IS_TRUNK(endpoint_info->gport) &&
   6335         (BCM_TRUNK_INVALID == trunk_id)) {
   6336         /* Has to be a valid Trunk. */
   6337         return (BCM_E_PARAM);
   6338     }
   6339 
   6340     if (BCM_TRUNK_INVALID != trunk_id) {
   6341 
   6342         /* 
   6343          * CCM Tx is enabled on a trunk member port.
   6344          * trunk_index value is required to derive the Modid and Port info.
   6345          */
   6346         if (1 == local_tx_enabled
   6347             && _BCM_OAM_INVALID_INDEX == endpoint_info->trunk_index) {
   6348             /* Invalid Trunk member index passed. */
   6349             return (BCM_E_PORT);
   6350         }
   6351 
   6352         /* Get Trunk Info for the Trunk ID. */
   6353         BCM_IF_ERROR_RETURN
   6354             (bcm_esw_trunk_get(unit, trunk_id, NULL, 0, NULL, &member_count));
   6355         if (0 == member_count) {
   6356             /* No members have been added to the trunk group yet */
   6357             return BCM_E_PARAM;
   6358         }
   6359         member_array = sal_alloc(sizeof(bcm_trunk_member_t) * member_count,
   6360                 "trunk member array");
   6361         if (NULL == member_array) {
   6362             return BCM_E_MEMORY;
   6363         }
   6364         rv = bcm_esw_trunk_get(unit, trunk_id, NULL,
   6365                 member_count, member_array, &member_count);
   6366         if (BCM_FAILURE(rv)) {
   6367             sal_free(member_array);
   6368             return rv;
   6369         }
   6370 
   6371         /* Get the Modid and Port value using Trunk Index value. */
   6372         if (endpoint_info->trunk_index >= member_count) {
   6373             sal_free(member_array);
   6374             return BCM_E_PARAM;
   6375         }
   6376         member_gport = member_array[endpoint_info->trunk_index].gport;
   6377         sal_free(member_array);
   6378         BCM_IF_ERROR_RETURN
   6379             (_bcm_esw_gport_resolve(unit, member_gport, &module_id, &port_id,
   6380                                     &tgid_out, &id_out));
   6381         if ((-1 != tgid_out) || (-1 != id_out)) {
   6382             return BCM_E_PARAM;
   6383         }
   6384 
   6385         /* Calculate the SGLP and DGLP values to program the MEP */
   6386         src_glp = ((1 << SOC_TRUNK_BIT_POS(unit)) | trunk_id);
   6387         dst_glp = (module_id << SOC_MODID_BIT_POS(unit)) | port_id;
   6388     }
   6389 
   6390     /* 
   6391      * Application can resolve the trunk and pass the desginated
   6392      * port as Gport value. Check if the Gport belongs to a trunk.
   6393      */
   6394     if ((BCM_TRUNK_INVALID == trunk_id)
   6395         && (BCM_GPORT_IS_MODPORT(endpoint_info->gport)
   6396         || BCM_GPORT_IS_LOCAL(endpoint_info->gport))) {
   6397 
   6398         /* When Gport is ModPort or Port type, _bcm_esw_gport_resolve()
   6399          * returns Modid and Port value. Use these values to make the DGLP
   6400          * value.
   6401          */
   6402         dst_glp = ((module_id << SOC_MODID_BIT_POS(unit)) | port_id);
   6403 
   6404         /* Use the Modid, Port value and determine if the port
   6405          * belongs to a Trunk.
   6406          */
   6407         rv = bcm_esw_trunk_find(unit, module_id, port_id, &trunk_id);
   6408         if (BCM_SUCCESS(rv)) {
   6409             /* 
   6410              * Port is member of a valid trunk.
   6411              * Now create the SGLP value from Trunk ID.
   6412              */
   6413             src_glp = (1 << SOC_TRUNK_BIT_POS(unit)) | trunk_id;
   6414         } else {
   6415             /* Port not a member of trunk. DGLP and SGLP are the same. */
   6416             src_glp = dst_glp;
   6417         }
   6418     }
   6419 
   6420     if (BCM_GPORT_IS_MIM_PORT(endpoint_info->gport) ||
   6421         BCM_GPORT_IS_MPLS_PORT(endpoint_info->gport)) {
   6422         vp = local_id;
   6423         src_glp = dst_glp = ((module_id << SOC_MODID_BIT_POS(unit)) | port_id);
   6424 
   6425         BCM_IF_ERROR_RETURN
   6426             (_bcm_esw_modid_is_local(unit, module_id, &is_local));
   6427         if (is_local) {
   6428             src_glp = dst_glp = ((module_id << SOC_MODID_BIT_POS(unit)) | port_id);
   6429         } else {
   6430             return BCM_E_PARAM;
   6431         }
   6432     }
   6433 
   6434     /* 
   6435      * At this point, both src_glp and dst_glp should be valid.
   6436      * Gport types other than TRUNK, MODPORT or LOCAL are not valid.
   6437      */
   6438     if (_BCM_OAM_INVALID_INDEX == src_glp
   6439         || _BCM_OAM_INVALID_INDEX == dst_glp) {
   6440         return (BCM_E_PORT);
   6441     }
   6442 
   6443     quantization_index =
   6444         _bcm_en_oam_quantize_ccm_period(endpoint_info->ccm_period);
   6445 
   6446  
   6447     /*
   6448      * Ethernet
   6449      */
   6450     if (endpoint_info->type == bcmOAMEndpointTypeEthernet)
   6451     {  
   6452         endpoint_p->type = endpoint_info->type;
   6453 	if (is_remote)
   6454 	{
   6455            if (replace && !endpoint_p->is_remote) {
   6456                    /* Replacing Local to Remote, Delete existing LMEP */
   6457                    BCM_IF_ERROR_RETURN(_bcm_en_oam_delete_lmep(unit, endpoint_p));
   6458            }
   6459 
   6460            if ( !(replace) || (replace && !endpoint_p->is_remote) ) {
   6461                /* Creating new Remote. Hence create new RMEP entry.
   6462                   Else if replace operation, reuse existing RMEP */
   6463                endpoint_p->remote_index = _bcm_en_oam_find_free_endpoint(
   6464                        oam_info_p->remote_endpoints_in_use,
   6465                        oam_info_p->remote_endpoint_count, 1, 0);
   6466                if (endpoint_p->remote_index < 0) {
   6467                    return BCM_E_FULL;
   6468                }
   6469 
   6470                /* RMEP entry */
   6471 
   6472                sal_memset(&rmep_entry, 0, sizeof(rmep_entry_t));
   6473 
   6474                soc_RMEPm_field32_set(unit, &rmep_entry, MAID_INDEXf,
   6475                        endpoint_info->group);
   6476 
   6477                /*
   6478                 * The following steps are necessary to enable CCM timeout events
   6479                 * without having received any CCMs.
   6480                 */
   6481                soc_RMEPm_field32_set(unit, &rmep_entry, RMEP_TIMESTAMP_VALIDf, 1);
   6482                BCM_IF_ERROR_RETURN(READ_OAM_CURRENT_TIMEr(unit, &oam_current_time));
   6483                soc_RMEPm_field32_set(unit, &rmep_entry, RMEP_TIMESTAMPf,
   6484                        oam_current_time);
   6485                soc_RMEPm_field32_set(unit, &rmep_entry, RMEP_RECEIVED_CCMf,
   6486                        quantization_index);
   6487 
   6488                /* End of timeout setup */
   6489 
   6490                soc_RMEPm_field32_set(unit, &rmep_entry, VALIDf, 1);
   6491 
   6492                SOC_IF_ERROR_RETURN(WRITE_RMEPm(unit, MEM_BLOCK_ALL,
   6493                            endpoint_p->remote_index, &rmep_entry));
   6494            }
   6495 
   6496            /* L3 entry */
   6497            if (replace && endpoint_p->is_remote) {
   6498                if (vp != 0) {
   6499                    _bcm_en_oam_make_rmep_key(unit, &l3_key, endpoint_p->name,
   6500                            endpoint_p->level, 0, endpoint_p->vp);
   6501                } else {
   6502                    _bcm_en_oam_make_rmep_key(unit, &l3_key, endpoint_p->name,
   6503                            endpoint_p->level, endpoint_p->vlan, endpoint_p->glp);
   6504                }
   6505                rv = soc_mem_search(unit, L3_ENTRY_IPV4_UNICASTm, MEM_BLOCK_ANY,
   6506                        &l3_index, &l3_key, &l3_entry, 0);
   6507                /* See if key not changed. */
   6508                if ((endpoint_info->name == endpoint_p->name) &&
   6509                        (endpoint_info->level == endpoint_p->level) &&
   6510                        (((endpoint_info->vlan == endpoint_p->vlan) &&
   6511                          (src_glp == endpoint_p->glp)) || (vp == endpoint_p->vp))) {
   6512                    if (BCM_E_NONE == rv) {
   6513                        /* Replace current entry */
   6514                        replace_l3_entry = 1;
   6515                    }
   6516                } else {
   6517                    /* Delete replaced L3 RMEP. */
   6518                    SOC_IF_ERROR_RETURN(soc_mem_delete(unit, L3_ENTRY_IPV4_UNICASTm,
   6519                                MEM_BLOCK_ALL, &l3_key));
   6520                }
   6521            }
   6522            sal_memset(&l3_entry, 0, sizeof(l3_entry_ipv4_unicast_entry_t));
   6523 
   6524            soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, &l3_entry, RMEP__CCMf,
   6525                    quantization_index);
   6526 
   6527            soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, &l3_entry, RMEP__RMEP_PTRf,
   6528                    endpoint_p->remote_index);
   6529 
   6530            soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, &l3_entry, RMEP__MEPIDf,
   6531                    endpoint_info->name);
   6532 
   6533            soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, &l3_entry, RMEP__MDLf,
   6534                    endpoint_info->level);
   6535 
   6536            if (vp) {
   6537 #if defined(BCM_KATANA_SUPPORT)
   6538                if (SOC_IS_KATANAX(unit)) {
   6539                    if(endpoint_info->flags & BCM_OAM_ENDPOINT_PBB_TE) {
   6540                        soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, &l3_entry,
   6541                                RMEP__ENTRY_IS_SVPf,
   6542                                1);
   6543                    }
   6544                }
   6545 #endif /* BCM_KATANA_SUPPORT */
   6546                soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, &l3_entry, RMEP__VIDf, 0);
   6547                soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, &l3_entry, RMEP__SGLPf, vp);
   6548            } else {
   6549                soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, &l3_entry, RMEP__VIDf,
   6550                        endpoint_info->vlan);
   6551                soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, &l3_entry, RMEP__SGLPf, src_glp);
   6552            }
   6553 
   6554            soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, &l3_entry, KEY_TYPEf,
   6555                    TR_L3_HASH_KEY_TYPE_RMEP);
   6556 
   6557            soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, &l3_entry, VALIDf, 1);
   6558 
   6559            if (replace_l3_entry) {
   6560                SOC_IF_ERROR_RETURN(
   6561                    soc_mem_write(unit, L3_ENTRY_IPV4_UNICASTm, MEM_BLOCK_ALL,
   6562                                  l3_index, &l3_entry));
   6563            } else {
   6564                SOC_IF_ERROR_RETURN(
   6565                        soc_mem_insert(unit, L3_ENTRY_IPV4_UNICASTm, MEM_BLOCK_ALL, &l3_entry));
   6566            }
   6567 
   6568 	    /* Local control block */
   6569 
   6570 	    SHR_BITSET(oam_info_p->remote_endpoints_in_use,
   6571 		       endpoint_p->remote_index);
   6572 
   6573 	    oam_info_p->remote_endpoints[endpoint_p->remote_index] =
   6574 		endpoint_index;
   6575 	}
   6576 	else
   6577 	{
   6578 
   6579         if (replace && endpoint_p->is_remote) {
   6580             /* Delete original RMEP. */
   6581             BCM_IF_ERROR_RETURN(_bcm_en_oam_delete_rmep(unit, endpoint_p));
   6582         }
   6583 
   6584         if (replace && endpoint_p->local_rx_enabled) {
   6585             /* Delete replaced L3 LMEP and keep LMEP entry. */
   6586             result = endpoint_p->local_tx_enabled;
   6587             BCM_IF_ERROR_RETURN(_bcm_en_oam_delete_lmep(unit, endpoint_p));
   6588             endpoint_p->local_tx_enabled = result;
   6589         }
   6590 
   6591 	    if (local_tx_enabled)
   6592 	    {
   6593 		uint32 reversed_maid[BCM_OAM_GROUP_NAME_LENGTH / 4];
   6594 		int word_index;
   6595 
   6596 		if (!(replace && endpoint_p->local_tx_enabled)) {
   6597 		    endpoint_p->local_tx_index =
   6598 			_bcm_en_oam_find_free_endpoint(oam_info_p->
   6599 						       local_tx_endpoints_in_use,
   6600 						       oam_info_p->local_tx_endpoint_count, 1, 0);
   6601 
   6602 		    if (endpoint_p->local_tx_index < 0)
   6603 		    {
   6604 			return BCM_E_FULL;
   6605 		    }
   6606 		}
   6607 
   6608 		/* LMEP entry */
   6609 
   6610 		sal_memset(&lmep_entry, 0, sizeof(lmep_entry_t));
   6611 		soc_LMEPm_field32_set(unit, &lmep_entry, MAID_INDEXf,
   6612 				      endpoint_info->group);
   6613 
   6614 		soc_LMEPm_mac_addr_set(unit, &lmep_entry, SAf,
   6615 				       endpoint_info->src_mac_address);
   6616 
   6617 		soc_LMEPm_field32_set(unit, &lmep_entry, MDLf, endpoint_info->level);
   6618 		soc_LMEPm_field32_set(unit, &lmep_entry, MEPIDf, endpoint_info->name);
   6619 
   6620 		soc_LMEPm_field32_set(unit, &lmep_entry, PRIORITYf,
   6621 				      endpoint_info->pkt_pri);
   6622 
   6623 		soc_LMEPm_field32_set(unit, &lmep_entry, VLAN_IDf, endpoint_info->vlan);
   6624 		soc_LMEPm_field32_set(unit, &lmep_entry, CCMf, quantization_index);
   6625 
   6626 		soc_LMEPm_field32_set(unit, &lmep_entry, DESTf, dst_glp);
   6627 
   6628 		soc_LMEPm_field32_set(unit, &lmep_entry, MH_OPCODEf,
   6629 				      BCM_HG_OPCODE_UC);
   6630             
   6631 		soc_LMEPm_field32_set(unit, &lmep_entry, INT_PRIf,
   6632 				      endpoint_info->int_pri);
   6633 
   6634 		if (endpoint_info->flags & BCM_OAM_ENDPOINT_PORT_STATE_UPDATE) {
   6635 		    if (endpoint_info->port_state > BCM_OAM_PORT_TLV_UP) {
   6636 			return BCM_E_PARAM;
   6637 		    }
   6638 		    soc_LMEPm_field32_set(unit, &lmep_entry, PORT_TLVf,
   6639 					  (endpoint_info->port_state == BCM_OAM_PORT_TLV_UP) ? 1 : 0);
   6640 		}
   6641 
   6642 		if (endpoint_info->flags & BCM_OAM_ENDPOINT_INTERFACE_STATE_UPDATE) {
   6643 		    if (SOC_IS_ENDURO(unit)) {
   6644 			if (endpoint_info->interface_state > BCM_OAM_INTERFACE_TLV_DOWN) {
   6645 			    return BCM_E_PARAM;
   6646 			}
   6647 			soc_LMEPm_field32_set(unit, &lmep_entry, INTERFACE_TLVf,
   6648 					      (endpoint_info->interface_state == BCM_OAM_INTERFACE_TLV_UP) ? 1 : 0);
   6649 		    } else {
   6650 			if (endpoint_info->interface_state > BCM_OAM_INTERFACE_TLV_LLDOWN) {
   6651 			    return BCM_E_PARAM;
   6652 			}
   6653 			soc_LMEPm_field32_set(unit, &lmep_entry, INTERFACE_TLVf,
   6654 					      endpoint_info->interface_state);
   6655 		    }
   6656 		}
   6657 
   6658 		if ((endpoint_info->flags & BCM_OAM_ENDPOINT_PORT_STATE_TX) ||
   6659 		    (endpoint_info->flags & BCM_OAM_ENDPOINT_INTERFACE_STATE_TX)) {
   6660 		    soc_LMEPm_field32_set(unit, &lmep_entry, INSERT_TLVf, 1);
   6661 		}
   6662 
   6663 		/* Word-reverse the MAID bytes for the hardware */
   6664 
   6665 		for (word_index = 0;
   6666 		     word_index < (BCM_OAM_GROUP_NAME_LENGTH / 4);
   6667 		     ++word_index)
   6668 		{
   6669 		    reversed_maid[word_index] =
   6670 			   bcm_htonl(((uint32 *) group_p->name)
   6671                         [((BCM_OAM_GROUP_NAME_LENGTH / 4) - 1) - word_index]);
   6672 		}
   6673 
   6674 		soc_LMEPm_field_set(unit, &lmep_entry, MAIDf, reversed_maid);
   6675 
   6676 		SOC_IF_ERROR_RETURN(WRITE_LMEPm(unit, MEM_BLOCK_ALL,
   6677 						endpoint_p->local_tx_index, &lmep_entry));
   6678 
   6679 		/* LMEP_1 entry */
   6680 
   6681 		sal_memset(&lmep1_entry, 0, sizeof(lmep_1_entry_t));
   6682 
   6683 		soc_LMEP_1m_mac_addr_set(unit, &lmep1_entry, MACDAf,
   6684 					 endpoint_info->dst_mac_address);
   6685 
   6686 		SOC_IF_ERROR_RETURN(WRITE_LMEP_1m(unit, MEM_BLOCK_ALL,
   6687 						  endpoint_p->local_tx_index, &lmep1_entry));
   6688             
   6689 		/* Local control block */
   6690 
   6691 		SHR_BITSET(oam_info_p->local_tx_endpoints_in_use,
   6692 			   endpoint_p->local_tx_index);
   6693 	    }
   6694 
   6695 	    if (local_rx_enabled)
   6696 	    {
   6697 
   6698 		/* L3 entry */
   6699 		L3_LOCK(unit);
   6700 
   6701 		if (BCM_SUCCESS(_bcm_en_oam_find_lmep(unit, endpoint_info->vlan,
   6702 						      src_glp, &l3_index, &l3_entry)) ||
   6703 		    BCM_SUCCESS(_bcm_en_oam_find_lmep(unit, 0,
   6704 						      vp, &l3_index, &l3_entry)))
   6705 		{
   6706 		    rv = BCM_E_NONE;
   6707 		    /*
   6708 		     * If there is a  MATCH, check if this MD level is available at this
   6709 		     * index. If it's already occupied, report resource error.
   6710 		     * Else this MD level is available at this index.
   6711 		     */
   6712 
   6713 		    level_bitmap = soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit,
   6714 									  &l3_entry, LMEP__MDL_BITMAPf);
   6715 
   6716 		    level_bitmap &= (1 << endpoint_info->level);
   6717 
   6718 		    if (!level_bitmap) {
   6719 			endpoint_p->local_rx_index =
   6720 			    ((soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, &l3_entry,
   6721 								     LMEP__MA_BASE_PTRf) << 3) | endpoint_info->level);
   6722 			level_bitmap = soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit,
   6723 									      &l3_entry, LMEP__MDL_BITMAPf);
   6724 			level_bitmap |= (1 << endpoint_info->level);
   6725 			rv = soc_mem_field32_modify(unit, L3_ENTRY_IPV4_UNICASTm,
   6726 						    l3_index, LMEP__MDL_BITMAPf, level_bitmap);
   6727 		    } else {
   6728 			rv = BCM_E_RESOURCE;
   6729 		    }
   6730 		} else {
   6731 		    rv = BCM_E_NONE;
   6732 		    /*
   6733 		     * If Entry is NOT found, select a new MA_INDEX for this MDL.
   6734 		     */
   6735 
   6736 		    for (i = 0; i < oam_info_p->local_rx_endpoint_count; i += 8)
   6737 		    {
   6738 			SHR_BITTEST_RANGE(oam_info_p->local_rx_endpoints_in_use, 
   6739 					  i, 8, mdl_set);
   6740 			if (0 == mdl_set) {
   6741 			    break;
   6742 			}
   6743 		    }
   6744 		    if (i >= oam_info_p->local_rx_endpoint_count) {
   6745 			rv = BCM_E_FULL;
   6746 		    } else {
   6747 			endpoint_p->local_rx_index = (i + endpoint_info->level);
   6748 
   6749 		    sal_memset(&l3_entry, 0, sizeof(l3_entry_ipv4_unicast_entry_t));
   6750 
   6751 		    soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, &l3_entry,
   6752 							   LMEP__MDL_BITMAPf, 1 << endpoint_info->level);
   6753 
   6754 		    soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, &l3_entry,
   6755 							   LMEP__MA_BASE_PTRf,
   6756 							   endpoint_p->local_rx_index >> LEVEL_BIT_COUNT);
   6757                 
   6758 		    SET_LMEP_FIELD(unit, LMEP__DM_ENABLEf, endpoint_info->flags,
   6759 				   BCM_OAM_ENDPOINT_DELAY_MEASUREMENT);
   6760 		    SET_LMEP_FIELD(unit, LMEP__CCM_ENABLEf, endpoint_info->flags,
   6761 				   BCM_OAM_ENDPOINT_CCM_RX);
   6762 		    SET_LMEP_FIELD(unit, LMEP__LB_ENABLEf, endpoint_info->flags,
   6763 				   BCM_OAM_ENDPOINT_LOOPBACK);
   6764 		    SET_LMEP_FIELD(unit, LMEP__LT_ENABLEf, endpoint_info->flags,
   6765 				   BCM_OAM_ENDPOINT_LINKTRACE);
   6766 		    if (vp) {
   6767 			soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, &l3_entry, LMEP__VIDf,
   6768 							       0);
   6769 
   6770 			soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, &l3_entry, LMEP__SGLPf,
   6771 							       vp);
   6772 		    } else {
   6773 			soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, &l3_entry, LMEP__VIDf,
   6774 							       endpoint_info->vlan);
   6775 
   6776 			soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, &l3_entry, LMEP__SGLPf,
   6777 							       src_glp);
   6778 		    }
   6779 		    soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, &l3_entry, KEY_TYPEf,
   6780 							   TR_L3_HASH_KEY_TYPE_LMEP);
   6781 
   6782 		    soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, &l3_entry, VALIDf, 1);
   6783 
   6784 		    rv = soc_mem_insert(unit, L3_ENTRY_IPV4_UNICASTm,
   6785 					MEM_BLOCK_ALL, &l3_entry);
   6786 		    }
   6787 		}
   6788 
   6789 		L3_UNLOCK(unit);
   6790 
   6791 		if (rv != BCM_E_NONE && local_tx_enabled)
   6792 		{
   6793 		    /*
   6794 		     * Clean LMEP TX configuration.
   6795 		     */
   6796 		    sal_memset(&lmep_entry, 0, sizeof(lmep_entry_t));
   6797 		    SOC_IF_ERROR_RETURN(WRITE_LMEPm(unit, MEM_BLOCK_ALL,
   6798 						    endpoint_p->local_tx_index, &lmep_entry));
   6799 		    /*
   6800 		     *  Local control block
   6801 		     */
   6802 		    SHR_BITCLR(oam_info_p->local_tx_endpoints_in_use,
   6803 			       endpoint_p->local_tx_index);
   6804 
   6805 		    return rv;
   6806 		}
   6807 
   6808 #if defined(BCM_KATANA_SUPPORT)
   6809 		if (SOC_IS_KATANAX(unit)) {
   6810 		    if (endpoint_info->opcode_flags) {
   6811 			SOC_IF_ERROR_RETURN
   6812 			    (_bcm_kt_set_oam_opcode_profile_entry(unit,
   6813 								  endpoint_info->opcode_flags,
   6814 								  &opcode_entry));
   6815 		    } else {
   6816 			SOC_IF_ERROR_RETURN
   6817 			    (_bcm_kt_get_default_oam_opcode_profile_entry(unit,
   6818 									  &opcode_entry));
   6819 		    }
   6820 		    soc_mem_lock(unit, OAM_OPCODE_CONTROL_PROFILEm);
   6821 		    entries[0] = &opcode_entry;
   6822 		    SOC_IF_ERROR_RETURN
   6823 			(soc_profile_mem_add(unit, oam_opcode_profile[unit],
   6824 					     (void *) &entries, 1, &temp_index));
   6825 		    endpoint_p->opcode_profile_index = temp_index;
   6826 		    soc_mem_unlock(unit, OAM_OPCODE_CONTROL_PROFILEm);
   6827 		}
   6828 #endif /* BCM_KATANA_SUPPORT */
   6829 
   6830 		/* MA_INDEX entry */
   6831 
   6832 		sal_memset(&ma_index_entry, 0, sizeof(ma_index_entry));
   6833 
   6834 		soc_MA_INDEXm_field32_set(unit, &ma_index_entry, MA_PTRf,
   6835 					  endpoint_info->group);
   6836 #if defined(BCM_KATANA_SUPPORT)
   6837 		if (SOC_IS_KATANAX(unit)) {
   6838 		    soc_MA_INDEXm_field32_set(unit, &ma_index_entry,
   6839 					      OAM_OPCODE_CONTROL_PROFILE_PTRf,
   6840 					      endpoint_p->opcode_profile_index);
   6841 		    if (endpoint_info->opcode_flags & BCM_OAM_OPCODE_CCM_COPY_TO_CPU) {
   6842 			soc_MA_INDEXm_field32_set(unit,&ma_index_entry,
   6843 						  CPU_QUEUE_NUMf,
   6844 						  endpoint_info->cpu_qid);
   6845 		    }
   6846 		}
   6847 #endif /* BCM_KATANA_SUPPORT */
   6848 
   6849 		SOC_IF_ERROR_RETURN(WRITE_MA_INDEXm(unit, MEM_BLOCK_ALL,
   6850 						    endpoint_p->local_rx_index, &ma_index_entry));
   6851 
   6852 		SHR_BITSET(oam_info_p->local_rx_endpoints_in_use,
   6853 			   endpoint_p->local_rx_index);
   6854 	    } /* local_rx */
   6855 	}
   6856 	/* Local control block */
   6857 
   6858 	endpoint_p->is_remote = is_remote;
   6859 	endpoint_p->local_tx_enabled = local_tx_enabled;
   6860 	endpoint_p->local_rx_enabled = local_rx_enabled;
   6861 	endpoint_p->group_index = endpoint_info->group;
   6862 	endpoint_p->name = endpoint_info->name;
   6863 	endpoint_p->level = endpoint_info->level;
   6864 	endpoint_p->vlan = endpoint_info->vlan;
   6865 	endpoint_p->vp = vp;
   6866 	endpoint_p->glp = src_glp;
   6867 	endpoint_p->flags = endpoint_info->flags;
   6868 #if defined(BCM_KATANA_SUPPORT)
   6869 	endpoint_p->opcode_flags = endpoint_info->opcode_flags;
   6870 #endif /* BCM_KATANA_SUPPORT */
   6871 
   6872 	if (local_rx_enabled) {
   6873 	    if (endpoint_info->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT) {
   6874 		*num_lm = _bcm_en_oam_lm_search(unit, endpoint_p, 1, mdl_index);
   6875 		if (*num_lm == 1) {
   6876 		    /* Assign LM counter index for the first LM endpoint */
   6877 		    endpoint_p->lm_counter_index =
   6878 			_bcm_en_oam_find_free_endpoint(oam_info_p->lm_counter_in_use,
   6879 						       oam_info_p->lm_counter_count, BCM_OAM_LM_COUNTER_OFFSET, 0);
   6880 
   6881 		    if (endpoint_p->lm_counter_index < 0) {
   6882 			return BCM_E_FULL;
   6883 		    }
   6884         
   6885 		    SHR_BITSET(oam_info_p->lm_counter_in_use, 
   6886 			       endpoint_p->lm_counter_index);
   6887                     
   6888 		    /* Assign Pri Mapping pointer */
   6889 		    for (i = 0; i < BCM_OAM_INTPRI_MAX ; i++) {
   6890 			mem_entries[i] = endpoint_info->pri_map[i];
   6891 			if (SOC_MEM_FIELD_VALID(unit, ING_SERVICE_PRI_MAPm, OFFSET_VALIDf)) {
   6892 			    soc_mem_field32_set(unit, ING_SERVICE_PRI_MAPm, &mem_entries[i],
   6893 						OFFSET_VALIDf, 1);
   6894 			}
   6895 		    }
   6896 		    soc_mem_lock(unit, ING_SERVICE_PRI_MAPm);
   6897                 
   6898 		    entries[0] = &mem_entries;
   6899 		    SOC_IF_ERROR_RETURN
   6900 			(soc_profile_mem_add(unit, ing_pri_map_profile[unit],
   6901 					     (void *) &entries, BCM_OAM_INTPRI_MAX, &temp_index));
   6902 		    endpoint_p->pri_map_index = temp_index/BCM_OAM_INTPRI_MAX;
   6903 		    soc_mem_unlock(unit, ING_SERVICE_PRI_MAPm);
   6904 		    BCM_IF_ERROR_RETURN(
   6905 			_bcm_en_oam_install_fp(unit, 0, endpoint_p));
   6906 		} else {
   6907 		    for (i = 0; i < *num_lm; i++) {
   6908 			current_endpoint_p = oam_info_p->endpoints + mdl_index[i];
   6909 			BCM_IF_ERROR_RETURN(
   6910 			    _bcm_en_oam_install_fp(unit,
   6911 						   (i == (*num_lm-1)) ? 0 : 1, current_endpoint_p));
   6912 		    }
   6913 		}
   6914 	    }
   6915 
   6916 	    if ((endpoint_info->flags & BCM_OAM_ENDPOINT_DELAY_MEASUREMENT) &&
   6917 		!(endpoint_info->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT)) {
   6918 		BCM_IF_ERROR_RETURN(
   6919 		    _bcm_en_oam_install_fp(unit, 0, endpoint_p));
   6920 	    }
   6921 
   6922 	    if (endpoint_info->flags & BCM_OAM_ENDPOINT_PBB_TE) {
   6923 		/* Install VFP */
   6924 		BCM_IF_ERROR_RETURN(
   6925 		    _bcm_en_oam_install_vfp(unit, endpoint_index, endpoint_info));
   6926 	    }
   6927 	}
   6928     } 
   6929     /*
   6930      * BHH Specific
   6931      */ 
   6932     else if (soc_feature(unit, soc_feature_bhh) && 
   6933         ((endpoint_info->type == bcmOAMEndpointTypeBHHMPLS) || 
   6934          (endpoint_info->type == bcmOAMEndpointTypeBHHMPLSVccv))) {
   6935 #if defined(BCM_KATANA_SUPPORT)  && defined(INCLUDE_BHH)
   6936 
   6937 	/*
   6938 	 * The uKernel is not provisioned until both endpoints (local and remote)
   6939 	 * are provisioned in the host.
   6940 	 */
   6941 	if (is_remote) {
   6942 	    /*
   6943 	     * Find the local endpoint. If it can't be found then abort.
   6944 	     */
   6945 	    VALIDATE_ENDPOINT_INDEX(endpoint_info->local_id);
   6946 
   6947 	    if (!oam_info_p->endpoints[endpoint_info->local_id].in_use) {
   6948 		return BCM_E_NOT_FOUND;
   6949 	    } else if (oam_info_p->endpoints[endpoint_info->local_id].flags & BCM_OAM_ENDPOINT_REMOTE) {
   6950 		return BCM_E_EXISTS;
   6951 	    }
   6952 
   6953 	    /*
   6954 	     * Now that both ends are provisioned the uKernel can be 
   6955 	     * configured.
   6956 	     */
   6957 	    msg_rmep_create.sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(oam_info_p, 
   6958                                                         endpoint_info->local_id);
   6959 	    msg_rmep_create.flags = 0;
   6960 	    msg_rmep_create.enable = 1;
   6961 	    msg_rmep_create.remote_mep_id = endpoint_info->name;
   6962 
   6963             msg_rmep_create.period = en_ccm_periods[quantization_index];
   6964 
   6965 	    /* Pack control message data into DMA buffer */
   6966 	    buffer     = oam_info_p->dma_buffer;
   6967 	    buffer_ptr = bhh_sdk_msg_ctrl_rmep_create_pack(buffer, &msg_rmep_create);
   6968 	    buffer_len = buffer_ptr - buffer;
   6969 
   6970 	    /* Send BHH Session Update message to uC */
   6971 	    BCM_IF_ERROR_RETURN
   6972 		(_bcm_en_oam_bhh_msg_send_receive(unit,
   6973 					      MOS_MSG_SUBCLASS_BHH_RMEP_CREATE,
   6974 					      buffer_len, 0,
   6975 					      MOS_MSG_SUBCLASS_BHH_RMEP_CREATE_REPLY,
   6976 					      &reply_len));
   6977 	    if (reply_len != 0) {
   6978 		return BCM_E_INTERNAL;
   6979 	    }
   6980 
   6981 	} else {
   6982 
   6983         endpoint_p->type = endpoint_info->type;
   6984         endpoint_p->name = endpoint_info->name;
   6985         endpoint_p->level = endpoint_info->level;
   6986         endpoint_p->vccv_type = endpoint_info->vccv_type;
   6987         endpoint_p->group_index = endpoint_info->group;
   6988         endpoint_p->vlan = endpoint_info->vlan;
   6989         endpoint_p->vlan_pri = endpoint_info->pkt_pri;
   6990         endpoint_p->inner_vlan_pri = endpoint_info->inner_pkt_pri;
   6991         endpoint_p->vpn  = endpoint_info->vpn;
   6992         endpoint_p->vp = vp;
   6993         endpoint_p->glp = src_glp;
   6994         endpoint_p->egress_if = endpoint_info->intf_id;
   6995         endpoint_p->cpu_qid   = endpoint_info->cpu_qid;
   6996         endpoint_p->label     = endpoint_info->mpls_label;
   6997         endpoint_p->gport     = endpoint_info->gport;
   6998         endpoint_p->trunk_index = endpoint_info->trunk_index;
   6999         endpoint_p->flags     = endpoint_info->flags;
   7000         endpoint_p->local_tx_enabled = 0;
   7001         endpoint_p->local_rx_enabled = 0;
   7002         endpoint_p->egr_label = endpoint_info->egress_label.label;
   7003         endpoint_p->egr_label_exp = endpoint_info->egress_label.exp;
   7004         endpoint_p->egr_label_ttl = endpoint_info->egress_label.ttl;
   7005 
   7006 	    /* Get local port used for TX BFD packet */
   7007 	    BCM_IF_ERROR_RETURN
   7008 		(_bcm_esw_modid_is_local(unit, module_id, &is_local));
   7009 	    if (!is_local) {    /* HG port */
   7010 		BCM_IF_ERROR_RETURN
   7011 		    (bcm_esw_stk_modport_get(unit, module_id, &port_id));
   7012 	    }
   7013 
   7014 
   7015 	    /* Create or Update */
   7016 	    session_flags = (replace) ? 0 : SHR_BHH_SESS_SET_F_CREATE;
   7017 
   7018 	    /* Set Endpoint config entry */
   7019 	    endpoint_p->bhh_endpoint_index = endpoint_index;
   7020 
   7021 
   7022 	    /* Set Encapsulation in HW */
   7023 	    if (!replace || (endpoint_info->flags & BCM_BHH_ENDPOINT_ENCAP_SET)) {
   7024 		BCM_IF_ERROR_RETURN
   7025 		    (_bcm_en_oam_bhh_encap_hw_set(unit, endpoint_p, module_id,
   7026 						  port_id, is_local, endpoint_info->int_pri));
   7027 		encap = 1;
   7028 	    }
   7029 
   7030 
   7031         /* Set control message data */
   7032         sal_memset(&msg_sess, 0, sizeof(msg_sess));
   7033 
   7034         /*
   7035          * Set the BHH encapsulation data
   7036          *
   7037          * The function _bcm_en_oam_bhh_encap_create() is called first
   7038          * since this sets some fields in 'endpoint_p' which are
   7039          * used in the message.
   7040          */
   7041         if (encap) {
   7042             BCM_IF_ERROR_RETURN
   7043                 (_bcm_en_oam_bhh_encap_create(unit,
   7044                                               port_id,
   7045                                               endpoint_p,
   7046                                               msg_sess.encap_data,
   7047                                               &msg_sess.encap_type,
   7048                                               &msg_sess.encap_length));
   7049         }
   7050 
   7051         /*
   7052          * Endpoint can be one of: CCM, LB, LM or DM. The default is CCM,
   7053          * all others modes must be specified via a config flag.
   7054  */
   7055         if (endpoint_info->flags & BCM_OAM_ENDPOINT_LOOPBACK)
   7056             session_flags |= SHR_BHH_SESS_SET_F_LB;
   7057         else if (endpoint_info->flags & BCM_OAM_ENDPOINT_DELAY_MEASUREMENT)
   7058             session_flags |= SHR_BHH_SESS_SET_F_DM;
   7059         else if (endpoint_info->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT)
   7060             session_flags |= SHR_BHH_SESS_SET_F_LM;
   7061         else
   7062             session_flags |= SHR_BHH_SESS_SET_F_CCM;
   7063 
   7064         if (endpoint_info->flags & BCM_OAM_ENDPOINT_INTERMEDIATE)
   7065             session_flags |= SHR_BHH_SESS_SET_F_MIP;
   7066 
   7067         _bcm_en_oam_get_group_sw_rdi (unit, endpoint_info->group,
   7068                 &group_sw_rdi);
   7069         if (group_sw_rdi) {
   7070             session_flags |= SHR_BHH_SESS_SET_F_RDI;
   7071         }
   7072         msg_sess.sess_id =
   7073             BCM_OAM_BHH_GET_UKERNEL_EP(oam_info_p,
   7074                     endpoint_p->bhh_endpoint_index);
   7075         msg_sess.flags   = session_flags;
   7076 
   7077         if (endpoint_p->level > _BCM_OAM_BHH_MEL_MAX)
   7078             return BCM_E_PARAM;
   7079 
   7080         msg_sess.mel     = endpoint_p->level;
   7081         msg_sess.mep_id  = endpoint_p->name;
   7082         sal_memcpy(msg_sess.meg_id, group_p->name, BCM_OAM_GROUP_NAME_LENGTH);
   7083 
   7084         msg_sess.period = en_ccm_periods[quantization_index];
   7085 
   7086 	    msg_sess.if_num  = endpoint_info->intf_id;
   7087 	    msg_sess.tx_port = port_id;
   7088         if (BCM_TRUNK_INVALID == trunk_id) {
   7089             msg_sess.rx_port = port_id;
   7090         } else {
   7091             msg_sess.rx_port = trunk_id;
   7092             msg_sess.trunk_valid = 1;
   7093         }
   7094 	    msg_sess.tx_cos  = endpoint_info->int_pri;
   7095 	    msg_sess.tx_pri  = endpoint_info->pkt_pri;
   7096 	    msg_sess.tx_qnum = SOC_INFO(unit).port_cosq_base[port_id] + endpoint_info->int_pri;
   7097 
   7098         msg_sess.mpls_label = endpoint_info->mpls_label;
   7099 
   7100         switch (endpoint_p->type) {
   7101         case bcmOAMEndpointTypeBHHMPLS:
   7102             msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_LSP;
   7103             msg_sess.priority   = endpoint_info->mpls_exp;
   7104             break;
   7105 
   7106         case bcmOAMEndpointTypeBHHMPLSVccv:
   7107             switch(endpoint_p->vccv_type) {
   7108 
   7109             case bcmOamBhhVccvChannelAch:
   7110                 msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_PW_VCCV_1;
   7111                 msg_sess.priority   = endpoint_info->mpls_exp;
   7112                 break;
   7113 
   7114             case bcmOamBhhVccvRouterAlert:
   7115                 msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_PW_VCCV_2;
   7116                 msg_sess.priority   = endpoint_info->mpls_exp;
   7117                 break;
   7118 
   7119             case bcmOamBhhVccvTtl:
   7120                 msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_PW_VCCV_3;
   7121                 msg_sess.priority   = endpoint_info->mpls_exp;
   7122                 break;
   7123 
   7124             case bcmOamBhhVccvGal13:
   7125                 msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_PW_VCCV_4;
   7126                 msg_sess.priority   = endpoint_info->mpls_exp;
   7127                 break;
   7128 
   7129             default:
   7130                 return BCM_E_PARAM;
   7131                 break;
   7132             }
   7133             break;
   7134 
   7135         case bcmOAMEndpointTypeBhhSection:
   7136             msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_PORT_SECTION;
   7137             msg_sess.priority   = 0;
   7138             break;
   7139         case bcmOAMEndpointTypeBhhSectionInnervlan:
   7140             msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_PORT_SECTION_INNERVLAN;
   7141             msg_sess.priority   = endpoint_info->inner_pkt_pri;
   7142             break;
   7143         case bcmOAMEndpointTypeBhhSectionOuterVlan:
   7144             msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_PORT_SECTION_OUTERVLAN;
   7145             msg_sess.priority   = endpoint_info->pkt_pri;
   7146             break;
   7147         case bcmOAMEndpointTypeBhhSectionOuterPlusInnerVlan:
   7148             msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_PORT_SECTION_OUTER_PLUS_INNERVLAN;
   7149             msg_sess.priority   = endpoint_info->pkt_pri;
   7150             break;
   7151 
   7152         default:
   7153             return BCM_E_PARAM;
   7154         }
   7155 
   7156         /* Pack control message data into DMA buffer */
   7157         buffer     = oam_info_p->dma_buffer;
   7158         buffer_ptr = bhh_sdk_msg_ctrl_sess_set_pack(buffer, &msg_sess);
   7159         buffer_len = buffer_ptr - buffer;
   7160 
   7161         /* Send BHH Session Update message to uC */
   7162         BCM_IF_ERROR_RETURN
   7163             (_bcm_en_oam_bhh_msg_send_receive(unit,
   7164                                               MOS_MSG_SUBCLASS_BHH_SESS_SET,
   7165                                               buffer_len, 0,
   7166                                               MOS_MSG_SUBCLASS_BHH_SESS_SET_REPLY,
   7167                                               &reply_len));
   7168         if (reply_len != 0) {
   7169             return BCM_E_INTERNAL;
   7170         }
   7171 	} /* is_remote */
   7172 #else
   7173     return (BCM_E_UNAVAIL);
   7174 #endif /* defined(BCM_KATANA_SUPPORT)  && defined(INCLUDE_BHH) */
   7175     }
   7176     else {
   7177         return (BCM_E_PARAM);
   7178     }
   7179 
   7180     endpoint_p->in_use = 1;
   7181 
   7182 #ifdef BCM_WARM_BOOT_SUPPORT
   7183     SOC_CONTROL_LOCK(unit);
   7184     SOC_CONTROL(unit)->scache_dirty = 1;
   7185     SOC_CONTROL_UNLOCK(unit);
   7186 #endif
   7187 
   7188     return BCM_E_NONE;
   7189 }
   7190 
   7191 int 
   7192 bcm_en_oam_endpoint_create(
   7193     int unit, 
   7194     bcm_oam_endpoint_info_t *endpoint_info)
   7195 {
   7196     int i, j, rv, num_lm = 0, mdl_index[LEVEL_COUNT];
   7197     _bcm_oam_info_t *oam_info_p;
   7198     _bcm_oam_endpoint_t *created_endpoint_p = NULL, *current_endpoint_p;
   7199 
   7200     rv = _bcm_en_oam_create_endpoint(unit, endpoint_info, &created_endpoint_p,
   7201                                      &num_lm, mdl_index);
   7202 
   7203     if (BCM_SUCCESS(rv) && (created_endpoint_p != NULL)) {
   7204         if (endpoint_info->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT) {
   7205             if (num_lm == 1) {
   7206                 BCM_IF_ERROR_RETURN(
   7207                     bcm_esw_field_entry_install(unit, created_endpoint_p->fp_entry_tx));
   7208                 BCM_IF_ERROR_RETURN(
   7209                     bcm_esw_field_entry_install(unit, created_endpoint_p->fp_entry_rx));
   7210                 for (j = 0; j < BCM_SWITCH_TRUNK_MAX_PORTCNT; j++) {
   7211                     if (created_endpoint_p->fp_entry_trunk[j]) {
   7212                         BCM_IF_ERROR_RETURN(
   7213                             bcm_esw_field_entry_install(unit, created_endpoint_p->fp_entry_trunk[j]));
   7214                     }
   7215                 }
   7216             } else {
   7217                 SET_OAM_INFO;
   7218                 for (i = 0; i < num_lm; i++) {
   7219                     current_endpoint_p = oam_info_p->endpoints + mdl_index[i];
   7220                     BCM_IF_ERROR_RETURN(
   7221                         bcm_esw_field_entry_install(unit, current_endpoint_p->fp_entry_tx));
   7222                     BCM_IF_ERROR_RETURN(
   7223                         bcm_esw_field_entry_install(unit, current_endpoint_p->fp_entry_rx));
   7224                     for (j = 0; j < BCM_SWITCH_TRUNK_MAX_PORTCNT; j++) {
   7225                         if (current_endpoint_p->fp_entry_trunk[j]) {
   7226                             BCM_IF_ERROR_RETURN(
   7227                                 bcm_esw_field_entry_install(unit, current_endpoint_p->fp_entry_trunk[j]));
   7228                         }
   7229                     }
   7230                 }
   7231             }
   7232         }
   7233 
   7234         if ((endpoint_info->flags & BCM_OAM_ENDPOINT_DELAY_MEASUREMENT) &&
   7235             !(endpoint_info->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT)) {
   7236             if (created_endpoint_p->fp_entry_tx) {
   7237                 BCM_IF_ERROR_RETURN(
   7238                 bcm_esw_field_entry_install(unit, created_endpoint_p->fp_entry_tx));
   7239             }
   7240             if (created_endpoint_p->fp_entry_rx) {
   7241                 BCM_IF_ERROR_RETURN(
   7242                 bcm_esw_field_entry_install(unit, created_endpoint_p->fp_entry_rx));
   7243             }
   7244             for (j = 0; j < BCM_SWITCH_TRUNK_MAX_PORTCNT; j++) {
   7245                 if (created_endpoint_p->fp_entry_trunk[j]) {
   7246                         BCM_IF_ERROR_RETURN(
   7247                             bcm_esw_field_entry_install(unit, created_endpoint_p->fp_entry_trunk[j]));
   7248                 }
   7249             }
   7250         }
   7251 
   7252         if (endpoint_info->flags & BCM_OAM_ENDPOINT_PBB_TE) {
   7253             BCM_IF_ERROR_RETURN(
   7254                 bcm_esw_field_entry_install(unit, created_endpoint_p->vfp_entry));
   7255     
   7256         }
   7257     }
   7258 
   7259     return rv;
   7260 }
   7261 
   7262 static int _bcm_en_oam_get_endpoint(int unit, _bcm_oam_info_t *oam_info_p, int endpoint_index,
   7263     _bcm_oam_endpoint_t *endpoint_p, bcm_oam_endpoint_info_t *endpoint_info)
   7264 {
   7265     rmep_entry_t rmep_entry;
   7266     lmep_entry_t lmep_entry;
   7267     l3_entry_ipv4_unicast_entry_t l3_key;
   7268     l3_entry_ipv4_unicast_entry_t l3_entry;
   7269     int l3_index;
   7270     int quantization_index = 0;
   7271     bcm_module_t module_id;
   7272     bcm_port_t port_id;
   7273     uint32 param0, param1;
   7274     ing_service_pri_map_entry_t primap_entry;
   7275     bcm_field_entry_t fp_entry;
   7276     int i, rv = BCM_E_NONE;
   7277 #if defined(BCM_KATANA_SUPPORT)  && defined(INCLUDE_BHH)
   7278     bhh_sdk_msg_ctrl_sess_get_t msg;
   7279     uint8 *buffer, *buffer_ptr;
   7280     uint16 buffer_len, reply_len;
   7281     int sess_id = 0;
   7282     bcm_l3_egress_t l3_egress;
   7283     bcm_l3_intf_t l3_intf;
   7284 #endif
   7285 
   7286     endpoint_info->id = endpoint_index;
   7287     endpoint_info->group = endpoint_p->group_index;
   7288     endpoint_info->name = endpoint_p->name;
   7289     endpoint_info->level = endpoint_p->level;
   7290     endpoint_info->vlan = endpoint_p->vlan;
   7291     endpoint_info->type = endpoint_p->type;
   7292     endpoint_info->flags = endpoint_p->flags;
   7293     endpoint_info->trunk_index = endpoint_p->trunk_index;
   7294 #if defined(BCM_KATANA_SUPPORT)
   7295     endpoint_info->opcode_flags = endpoint_p->opcode_flags;
   7296 #endif
   7297 
   7298     if (endpoint_p->type == bcmOAMEndpointTypeEthernet)  {
   7299     if (endpoint_p->is_remote)
   7300     {
   7301         endpoint_info->flags |= BCM_OAM_ENDPOINT_REMOTE;
   7302 
   7303         /* RMEP entry */
   7304 
   7305         SOC_IF_ERROR_RETURN(READ_RMEPm(unit, MEM_BLOCK_ANY,
   7306                                         endpoint_p->remote_index,
   7307                                         &rmep_entry));
   7308 
   7309         /* Get endpoint faults and clear presistent faults if Clear is SET */
   7310         BCM_IF_ERROR_RETURN(_bcm_en_oam_read_clear_faults(unit,
   7311                                                             endpoint_p->remote_index,
   7312                                                             en_endpoint_faults,
   7313                                                             RMEPm,
   7314                                                             (uint32 *) &rmep_entry,
   7315                                                             &endpoint_info->faults,
   7316                                                             &endpoint_info->persistent_faults,
   7317                                                             endpoint_info->clear_persistent_faults));
   7318         
   7319         if (endpoint_info->flags2 & BCM_OAM_ENDPOINT_FLAGS2_GET_FAULTS_ONLY) {
   7320             endpoint_info->flags2 &= ~BCM_OAM_ENDPOINT_FLAGS2_GET_FAULTS_ONLY;
   7321             return BCM_E_NONE;
   7322         }
   7323         /* L3 entry */
   7324         if (endpoint_p->vp != 0) {
   7325             _bcm_en_oam_make_rmep_key(unit, &l3_key, endpoint_p->name,
   7326                 endpoint_p->level, 0, endpoint_p->vp);
   7327         } else {
   7328             _bcm_en_oam_make_rmep_key(unit, &l3_key, endpoint_p->name,
   7329                 endpoint_p->level, endpoint_p->vlan, endpoint_p->glp);
   7330         }
   7331 
   7332         if (BCM_FAILURE(soc_mem_search(unit, L3_ENTRY_IPV4_UNICASTm, MEM_BLOCK_ANY,
   7333             &l3_index, &l3_key, &l3_entry, 0)))
   7334         {
   7335             return BCM_E_INTERNAL;
   7336         }
   7337 
   7338         quantization_index = soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, &l3_entry,
   7339             RMEP__CCMf);
   7340     }
   7341     else
   7342     {
   7343         /* Endpoint is local */
   7344 
   7345         if (endpoint_p->local_tx_enabled)
   7346         {
   7347             /* LMEP entry */
   7348 
   7349             SOC_IF_ERROR_RETURN(READ_LMEPm(unit, MEM_BLOCK_ANY,
   7350                 endpoint_p->local_tx_index, &lmep_entry));
   7351 
   7352             soc_LMEPm_mac_addr_get(unit, &lmep_entry, SAf,
   7353                 endpoint_info->src_mac_address);
   7354 
   7355             endpoint_info->pkt_pri = soc_LMEPm_field32_get(unit, &lmep_entry,
   7356                 PRIORITYf);
   7357 
   7358             endpoint_info->int_pri = soc_LMEPm_field32_get(unit, &lmep_entry,
   7359                 INT_PRIf);
   7360 
   7361             quantization_index = soc_LMEPm_field32_get(unit, &lmep_entry,
   7362                 CCMf);
   7363 
   7364             endpoint_info->port_state = 
   7365                 soc_LMEPm_field32_get(unit, &lmep_entry, PORT_TLVf) ? 
   7366                 BCM_OAM_PORT_TLV_UP : BCM_OAM_PORT_TLV_BLOCKED;
   7367 
   7368             if (SOC_IS_ENDURO(unit)) {
   7369                 endpoint_info->interface_state = 
   7370                     soc_LMEPm_field32_get(unit, &lmep_entry, INTERFACE_TLVf) ? 
   7371                     BCM_OAM_INTERFACE_TLV_UP : BCM_OAM_INTERFACE_TLV_DOWN;
   7372             } else {
   7373                 endpoint_info->interface_state = 
   7374                     soc_LMEPm_field32_get(unit, &lmep_entry, INTERFACE_TLVf);
   7375             }
   7376 
   7377             if (soc_LMEPm_field32_get(unit, &lmep_entry, INSERT_TLVf)) {
   7378                 endpoint_info->flags |= (BCM_OAM_ENDPOINT_PORT_STATE_TX |
   7379                                          BCM_OAM_ENDPOINT_INTERFACE_STATE_TX);
   7380             }
   7381         }
   7382 
   7383         if (endpoint_p->local_rx_enabled)
   7384         {
   7385             /* L3 entry */
   7386             if (endpoint_p->vp != 0) {
   7387                 if (BCM_FAILURE(_bcm_en_oam_find_lmep(unit, 0,
   7388                        endpoint_p->vp, &l3_index, &l3_entry))) {
   7389                     return BCM_E_INTERNAL;
   7390                 }
   7391             } else if (BCM_FAILURE(_bcm_en_oam_find_lmep(unit, endpoint_p->vlan,
   7392                 endpoint_p->glp, &l3_index, &l3_entry))) {
   7393                 return BCM_E_INTERNAL;
   7394             }
   7395 
   7396             GET_LMEP_FIELD(unit, LMEP__DM_ENABLEf, BCM_OAM_ENDPOINT_DELAY_MEASUREMENT);
   7397             GET_LMEP_FIELD(unit, LMEP__CCM_ENABLEf, BCM_OAM_ENDPOINT_CCM_RX);
   7398             GET_LMEP_FIELD(unit, LMEP__LB_ENABLEf, BCM_OAM_ENDPOINT_LOOPBACK);
   7399             GET_LMEP_FIELD(unit, LMEP__LT_ENABLEf, BCM_OAM_ENDPOINT_LINKTRACE);
   7400 
   7401             if (endpoint_p->fp_entry_tx != 0) {
   7402                 fp_entry = endpoint_p->fp_entry_tx;
   7403             } else {
   7404                 fp_entry = endpoint_p->fp_entry_rx;
   7405             }
   7406 
   7407             if (fp_entry != 0) {
   7408                 rv = bcm_esw_field_action_get(unit, fp_entry, 
   7409                                           bcmFieldActionOamLmEnable, 
   7410                                           &param0, &param1);
   7411                 if (BCM_SUCCESS(rv)) {
   7412                     if (param0 != 0) {
   7413                         endpoint_info->flags |= BCM_OAM_ENDPOINT_LOSS_MEASUREMENT;
   7414                     }
   7415                 }
   7416                 
   7417                 rv = bcm_esw_field_action_get(unit, fp_entry, 
   7418                                           bcmFieldActionOamUpMep, 
   7419                                           &param0, &param1);
   7420                 if (BCM_SUCCESS(rv)) {
   7421                     if (param0 != 0) {
   7422                         endpoint_info->flags |= BCM_OAM_ENDPOINT_UP_FACING;
   7423                     }
   7424                 }
   7425 
   7426                 rv = bcm_esw_field_action_get(unit, fp_entry, 
   7427                                           bcmFieldActionOamServicePriMappingPtr, 
   7428                                           &param0, &param1);
   7429                 if (BCM_SUCCESS(rv)) {
   7430                     for(i = 0; i < BCM_OAM_INTPRI_MAX; i++) {
   7431                         SOC_IF_ERROR_RETURN(READ_ING_SERVICE_PRI_MAPm(unit, 
   7432                                             MEM_BLOCK_ANY,
   7433                                             param0*BCM_OAM_INTPRI_MAX+i,
   7434                                             &primap_entry));
   7435                         endpoint_info->pri_map[i] = 
   7436                          (uint8)soc_ING_SERVICE_PRI_MAPm_field32_get(unit, &primap_entry, OFFSETf);
   7437                     }
   7438                     endpoint_info->pri_map_id = endpoint_p->pri_map_index;
   7439                 }
   7440             }
   7441 
   7442             if (endpoint_p->vfp_entry != 0) {
   7443                 endpoint_info->flags |= BCM_OAM_ENDPOINT_PBB_TE;
   7444             }
   7445         }
   7446     }
   7447     endpoint_info->ccm_period = en_ccm_periods[quantization_index];
   7448     }
   7449 
   7450 #if defined(INCLUDE_L3)
   7451     if (endpoint_p->vp != 0) {
   7452         if (_bcm_vp_used_get(unit, endpoint_p->vp, _bcmVpTypeMim)) {
   7453             BCM_GPORT_MIM_PORT_ID_SET(endpoint_info->gport, endpoint_p->vp);
   7454         } else {
   7455             BCM_GPORT_MPLS_PORT_ID_SET(endpoint_info->gport, endpoint_p->vp);
   7456         }
   7457     } else
   7458 #endif /* INCLUDE_L3 */
   7459     {
   7460         if (endpoint_p->glp & (1 << SOC_TRUNK_BIT_POS(unit)))
   7461         {
   7462             /* Trunk */
   7463 
   7464             BCM_GPORT_TRUNK_SET(endpoint_info->gport, endpoint_p->glp & 0x7F);
   7465         }
   7466         else
   7467         {
   7468             module_id = (endpoint_p->glp & SOC_MODID_MASK(unit)) >>
   7469                                                       SOC_MODID_BIT_POS(unit);
   7470             port_id = (endpoint_p->glp & SOC_PORT_ADDR_MAX(unit));
   7471 
   7472             if (module_id != 0)
   7473             {
   7474                 /* Modport */
   7475 
   7476                 BCM_GPORT_MODPORT_SET(endpoint_info->gport, module_id,
   7477                     port_id);
   7478             }
   7479             else
   7480             {
   7481                 /* Local port */
   7482 
   7483                 BCM_IF_ERROR_RETURN(bcm_esw_port_gport_get(unit, port_id,
   7484                     &(endpoint_info->gport)));
   7485             }
   7486         }
   7487     }
   7488 
   7489     if (soc_feature(unit, soc_feature_bhh) &&
   7490         ((endpoint_p->type == bcmOAMEndpointTypeBHHMPLS) ||
   7491          (endpoint_p->type == bcmOAMEndpointTypeBHHMPLSVccv))) {
   7492 #if defined(BCM_KATANA_SUPPORT)  && defined(INCLUDE_BHH)
   7493 
   7494     sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(oam_info_p, endpoint_index);
   7495 
   7496 	BCM_IF_ERROR_RETURN
   7497 	    (_bcm_en_oam_bhh_msg_send_receive(unit,
   7498 					      MOS_MSG_SUBCLASS_BHH_SESS_GET,
   7499 					      sess_id, 0,
   7500 					      MOS_MSG_SUBCLASS_BHH_SESS_GET_REPLY,
   7501 					      &reply_len));
   7502 
   7503 	/* Pack control message data into DMA buffer */
   7504 	buffer     = oam_info_p->dma_buffer;
   7505 	buffer_ptr = bhh_sdk_msg_ctrl_sess_get_unpack(buffer, &msg);
   7506 	buffer_len = buffer_ptr - buffer;
   7507 	if (reply_len != buffer_len) {
   7508 	    return BCM_E_INTERNAL;
   7509     } else {
   7510         endpoint_info->int_pri = msg.tx_cos;
   7511         endpoint_info->pkt_pri = msg.tx_pri;
   7512         endpoint_info->mpls_exp = msg.priority;
   7513 
   7514         if(endpoint_info->flags & BCM_OAM_ENDPOINT_REMOTE){
   7515             endpoint_info->name       = msg.remote_mep_id;
   7516             endpoint_info->ccm_period = msg.remote_period;
   7517         } else {
   7518             endpoint_info->name       = msg.mep_id;
   7519             endpoint_info->ccm_period = msg.local_period;
   7520         }
   7521 
   7522         if(msg.fault_flags & BHH_BTE_EVENT_CCM_TIMEOUT){
   7523             endpoint_info->faults |= BCM_OAM_BHH_FAULT_CCM_TIMEOUT;
   7524         }
   7525         if(msg.fault_flags & BHH_BTE_EVENT_CCM_RDI){
   7526             endpoint_info->faults |= BCM_OAM_BHH_FAULT_CCM_RDI;
   7527         }
   7528         if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_LEVEL){
   7529             endpoint_info->faults |=
   7530                 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEG_LEVEL;
   7531         }
   7532         if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_ID){
   7533             endpoint_info->faults |=
   7534                 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEG_ID;
   7535         }
   7536         if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_MEP_ID){
   7537             endpoint_info->faults |=
   7538                 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEP_ID;
   7539         }
   7540         if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_PERIOD){
   7541             endpoint_info->faults |=
   7542                 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_PERIOD;
   7543         }
   7544         if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_PRIORITY){
   7545             endpoint_info->faults |=
   7546                 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_PRIORITY;
   7547         }
   7548         if(msg.fault_flags & BHH_BTE_EVENT_CSF_LOS) {
   7549             endpoint_info->faults |= BCM_OAM_ENDPOINT_BHH_FAULT_CSF_LOS;
   7550         }
   7551         if(msg.fault_flags & BHH_BTE_EVENT_CSF_FDI) {
   7552             endpoint_info->faults |= BCM_OAM_ENDPOINT_BHH_FAULT_CSF_FDI;
   7553         }
   7554         if(msg.fault_flags & BHH_BTE_EVENT_CSF_RDI) {
   7555             endpoint_info->faults |= BCM_OAM_ENDPOINT_BHH_FAULT_CSF_RDI;
   7556         }
   7557     }
   7558 
   7559 	endpoint_info->intf_id    = endpoint_p->egress_if;
   7560 	endpoint_info->cpu_qid    =  endpoint_p->cpu_qid;
   7561 	endpoint_info->mpls_label = endpoint_p->label;
   7562 	endpoint_info->gport      = endpoint_p->gport;
   7563 	endpoint_info->vpn        = endpoint_p->vpn;
   7564 	endpoint_info->vccv_type  = endpoint_p->vccv_type;
   7565 
   7566 	/*
   7567 	 * Get MAC address
   7568 	 */
   7569 	bcm_l3_egress_t_init(&l3_egress);
   7570 	bcm_l3_intf_t_init(&l3_intf);
   7571 
   7572 	if (BCM_FAILURE
   7573 	    (bcm_esw_l3_egress_get(unit, endpoint_p->egress_if, &l3_egress))) {
   7574 	    return BCM_E_INTERNAL;
   7575 	}
   7576 
   7577 	l3_intf.l3a_intf_id = l3_egress.intf;
   7578 	if (BCM_FAILURE(bcm_esw_l3_intf_get(unit, &l3_intf))) {
   7579 	    return BCM_E_INTERNAL;
   7580 	}
   7581 
   7582 	sal_memcpy(endpoint_info->src_mac_address, l3_intf.l3a_mac_addr, _BHH_MAC_ADDR_LENGTH);
   7583 #else
   7584     return BCM_E_UNAVAIL;
   7585 #endif
   7586     }
   7587 
   7588     return BCM_E_NONE;
   7589 }
   7590 
   7591 /*
   7592  * Function:
   7593  *      _bcm_en_bhh_endpoint_faults_multi_get
   7594  * Purpose:
   7595  *      Function to get faults for multiple BHH endpoints
   7596  *      in a single call.
   7597  * Parameters:
   7598  *      unit                (IN) BCM device number
   7599  *      flags               (IN) Flags is kept unused as of now.
   7600  *                                This is for any future enhancement
   7601  *      max_endpoints       (IN) Number of max endpoint for the protocol
   7602  *      faults              (OUT) Pointer to faults for all endpoints
   7603  *      endpoint_count      (OUT) Pointer to Number of valid endpoints with faults,
   7604  *                                filled by get API.
   7605  *
   7606  * Returns:
   7607  *      BCM_E_NONE          No error
   7608  *      BCM_E_XXXX          Error
   7609  */
   7610 #if defined(BCM_KATANA_SUPPORT) && defined (INCLUDE_BHH)
   7611 static int _bcm_en_bhh_endpoint_faults_multi_get(
   7612            int unit,
   7613            uint32 flags,
   7614            uint32 max_endpoints,
   7615            bcm_oam_endpoint_fault_t *faults,
   7616            uint32 *endpoint_count)
   7617 {
   7618     int rv = BCM_E_NONE;
   7619     bcm_oam_endpoint_fault_t *faults_temp = faults;
   7620     uint8 *buffer;
   7621     uint16 reply_len;
   7622     uint32 sess_count;
   7623     uint32 ep_id;
   7624     uint32 ep_count = 0;
   7625     uint32 faults_bitmap;
   7626 
   7627      _bcm_oam_info_t *oam_info_p;
   7628     _bcm_oam_endpoint_t *endpoint_p;
   7629 
   7630     SET_OAM_INFO;
   7631 
   7632     CHECK_INIT;
   7633 
   7634     if(max_endpoints != oam_info_p->bhh_endpoint_count) {
   7635         rv = BCM_E_PARAM;
   7636         return (rv);
   7637     }
   7638     sal_memset(faults, 0, ((sizeof(bcm_oam_endpoint_fault_t))*max_endpoints));
   7639 
   7640     rv = _bcm_en_oam_bhh_msg_send_receive(unit,
   7641             MOS_MSG_SUBCLASS_BHH_FAULTS_MULTI_GET,
   7642             0, 0,
   7643             MOS_MSG_SUBCLASS_BHH_FAULTS_MULTI_GET_REPLY,
   7644             &reply_len);
   7645 
   7646     if (BCM_FAILURE(rv)) {
   7647         LOG_ERROR(BSL_LS_BCM_OAM,
   7648                 (BSL_META_U(unit,
   7649                             "OAM(unit %d) Error: BHH uKernel msg failed for"
   7650                             "faults multi get %s.\n"), unit,
   7651                  bcm_errmsg(rv)));
   7652         return (rv);
   7653     }
   7654 
   7655     if(reply_len != (oam_info_p->bhh_endpoint_count * sizeof(uint32))) {
   7656         rv = BCM_E_INTERNAL;
   7657         return (rv);
   7658     }
   7659     /* Unpack control message data into DMA buffer */
   7660     buffer = oam_info_p->dma_buffer;
   7661     for(sess_count = 0;sess_count < oam_info_p->bhh_endpoint_count;sess_count++) {
   7662         ep_id = BCM_OAM_BHH_GET_SDK_EP(oam_info_p, sess_count);
   7663 
   7664         VALIDATE_ENDPOINT_INDEX(ep_id);
   7665 
   7666         SET_ENDPOINT(ep_id);
   7667 
   7668         /* If endpoint not in use, ignore and continue for next session_id).
   7669          * If session is running in hostCPU, skip and Go to ep_id.*/
   7670         if(!(endpoint_p->in_use)) {
   7671            continue;
   7672         }
   7673 
   7674          _SHR_UNPACK_U32(buffer, faults_bitmap);
   7675 
   7676         faults_temp->endpoint_id = ep_id;
   7677 
   7678         if(faults_bitmap & BHH_BTE_EVENT_CCM_TIMEOUT){
   7679             faults_temp->faults |= BCM_OAM_BHH_FAULT_CCM_TIMEOUT;
   7680         }
   7681         if(faults_bitmap & BHH_BTE_EVENT_CCM_RDI){
   7682             faults_temp->faults |= BCM_OAM_BHH_FAULT_CCM_RDI;
   7683         }
   7684         if(faults_bitmap & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_LEVEL){
   7685             faults_temp->faults |=
   7686                 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEG_LEVEL;
   7687         }
   7688         if(faults_bitmap & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_ID){
   7689             faults_temp->faults |=
   7690                 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEG_ID;
   7691         }
   7692         if(faults_bitmap & BHH_BTE_EVENT_CCM_UNKNOWN_MEP_ID){
   7693             faults_temp->faults |=
   7694                 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEP_ID;
   7695         }
   7696         if(faults_bitmap & BHH_BTE_EVENT_CCM_UNKNOWN_PERIOD){
   7697             faults_temp->faults |=
   7698                 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_PERIOD;
   7699         }
   7700         if(faults_bitmap & BHH_BTE_EVENT_CCM_UNKNOWN_PRIORITY){
   7701             faults_temp->faults |=
   7702                 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_PRIORITY;
   7703         }
   7704         ep_count++;
   7705         faults_temp++;
   7706 
   7707     }
   7708 
   7709     *endpoint_count = ep_count;
   7710     return (rv);
   7711 
   7712 }
   7713 
   7714 /*
   7715  * Function:
   7716  *      _bcm_en_oam_bhh_appl_callback
   7717  * Purpose:
   7718  *      Update FW BHH appl state
   7719  * Parameters:
   7720  *      unit  - (IN) Unit number.
   7721  *      uC    - (IN) core number.
   7722  *      stage - (IN) core reset stage.
   7723  *      user_data - (IN) data pointer.
   7724  * Returns:
   7725  *      BCM_E_XXX
   7726  * Notes:
   7727  */
   7728 
   7729 int _bcm_en_oam_bhh_appl_callback(int unit,
   7730                                     int uC,
   7731                                     soc_cmic_uc_shutdown_stage_t stage,
   7732                                     void *user_data) {
   7733      _bcm_oam_info_t *oam_info_p;
   7734 
   7735     SET_OAM_INFO;
   7736     BCM_IF_ERROR_RETURN(bcm_esw_oam_lock(unit));
   7737     oam_info_p->ukernel_not_ready = 1;
   7738     return bcm_esw_oam_unlock(unit);
   7739 
   7740 }
   7741 
   7742 #endif
   7743 
   7744 /* Function:
   7745  *      bcm_en_oam_endpoint_faults_multi_get
   7746  * Purpose:
   7747  *      Function to get faults for multiple endpoints per protocl
   7748  *      in a single call.
   7749  * Parameters:
   7750  *      unit                (IN) BCM device number
   7751  *      flags               (IN) Flags is kept unused as of now.
   7752  *                               This is for any future enhancement
   7753  *      endpoint_protocol   (IN) Protocol type of the endpoints to retrieve faults
   7754  *      max_endpoints       (IN) Number of max endpoint for the protocol
   7755  *      faults              (OUT) Pointer to faults for all endpoints
   7756  *      endpoint_count      (OUT) Pointer to Number of valid endpoints with faults,
   7757  *                                by get API.
   7758  *
   7759  * Returns:
   7760  *      BCM_E_NONE          No error
   7761  *      BCM_E_XXXX          Error
   7762  */
   7763 int bcm_en_oam_endpoint_faults_multi_get(
   7764         int unit,
   7765         uint32 flags,
   7766         bcm_oam_protocol_type_t endpoint_protocol,
   7767         uint32 max_endpoints,
   7768         bcm_oam_endpoint_fault_t *faults,
   7769         uint32 *endpoint_count)
   7770 
   7771 {
   7772     int rv = BCM_E_NONE;
   7773 
   7774     if(!faults) {
   7775         rv = BCM_E_PARAM;
   7776         return (rv);
   7777     }
   7778 
   7779     switch(endpoint_protocol) {
   7780 
   7781 #if defined(BCM_KATANA_SUPPORT) && defined(INCLUDE_BHH)
   7782         case bcmOamProtocolBhh:
   7783             *endpoint_count = 0;
   7784             rv = _bcm_en_bhh_endpoint_faults_multi_get(
   7785                     unit,
   7786                     flags,
   7787                     max_endpoints,
   7788                     faults,
   7789                     endpoint_count);
   7790         break;
   7791 #endif
   7792         default:
   7793             rv = BCM_E_UNAVAIL;
   7794             break;
   7795     }
   7796 
   7797     return rv;
   7798 
   7799 }
   7800 
   7801 /*
   7802  * Function:
   7803  *      bcm_en_oam_endpoint_get
   7804  * Purpose:
   7805  *      Get an OAM endpoint object
   7806  * Parameters:
   7807  *      unit - (IN) Unit number.
   7808  *      endpoint - (IN) The ID of the endpoint object to get
   7809  *      endpoint_info - (OUT) Pointer to an OAM endpoint structure to receive the data
   7810  * Returns:
   7811  *      BCM_E_XXX
   7812  * Notes:
   7813  */
   7814 int 
   7815 bcm_en_oam_endpoint_get(
   7816     int unit, 
   7817     bcm_oam_endpoint_t endpoint, 
   7818     bcm_oam_endpoint_info_t *endpoint_info)
   7819 {
   7820     _bcm_oam_info_t *oam_info_p;
   7821     _bcm_oam_endpoint_t *endpoint_p;
   7822 
   7823     SET_OAM_INFO;
   7824 
   7825     CHECK_INIT;
   7826 
   7827     VALIDATE_ENDPOINT_INDEX(endpoint);
   7828 
   7829     SET_ENDPOINT(endpoint);
   7830 
   7831     if (!endpoint_p->in_use)
   7832     {
   7833         return BCM_E_NOT_FOUND;
   7834     }
   7835 
   7836     return _bcm_en_oam_get_endpoint(unit, oam_info_p, endpoint, endpoint_p,
   7837         endpoint_info);
   7838 }
   7839 
   7840 /*
   7841  * Function:
   7842  *      bcm_en_oam_endpoint_destroy
   7843  * Purpose:
   7844  *      Destroy an OAM endpoint object
   7845  * Parameters:
   7846  *      unit - (IN) Unit number.
   7847  *      endpoint - (IN) The ID of the OAM endpoint object to destroy
   7848  * Returns:
   7849  *      BCM_E_XXX
   7850  * Notes:
   7851  */
   7852 int 
   7853 bcm_en_oam_endpoint_destroy(
   7854     int unit, 
   7855     bcm_oam_endpoint_t endpoint)
   7856 {
   7857     _bcm_oam_info_t *oam_info_p;
   7858     _bcm_oam_endpoint_t *endpoint_p;
   7859 
   7860     SET_OAM_INFO;
   7861 
   7862     CHECK_INIT;
   7863 
   7864     VALIDATE_ENDPOINT_INDEX(endpoint);
   7865 
   7866     SET_ENDPOINT(endpoint);
   7867 
   7868     if (!endpoint_p->in_use)
   7869     {
   7870         return BCM_E_NOT_FOUND;
   7871     }
   7872 
   7873     return _bcm_en_oam_destroy_endpoint(unit, endpoint_p);
   7874 }
   7875 
   7876 /*
   7877  * Function:
   7878  *      bcm_en_oam_endpoint_destroy_all
   7879  * Purpose:
   7880  *      Destroy all OAM endpoint objects associated with a given OAM
   7881  *      group
   7882  * Parameters:
   7883  *      unit - (IN) Unit number.
   7884  *      group - (IN) The OAM group whose endpoints should be destroyed
   7885  * Returns:
   7886  *      BCM_E_XXX
   7887  * Notes:
   7888  */
   7889 int 
   7890 bcm_en_oam_endpoint_destroy_all(
   7891     int unit, 
   7892     bcm_oam_group_t group)
   7893 {
   7894     _bcm_oam_info_t *oam_info_p;
   7895     _bcm_oam_endpoint_t *endpoint_p;
   7896     int endpoint_index;
   7897 
   7898     SET_OAM_INFO;
   7899 
   7900     CHECK_INIT;
   7901 
   7902     VALIDATE_GROUP_INDEX(group);
   7903 
   7904     if(!oam_info_p->groups[group].in_use)
   7905     {
   7906         LOG_CLI((BSL_META_U(unit,
   7907             "OAM(unit %d) Error: Group ID=%d does not exist.\n"), unit, group));
   7908         return BCM_E_NOT_FOUND;
   7909     }
   7910 
   7911     for (endpoint_index = 0; endpoint_index < oam_info_p->endpoint_count;
   7912 	 ++endpoint_index)
   7913     {
   7914         SET_ENDPOINT(endpoint_index);
   7915 
   7916         if (endpoint_p->in_use && endpoint_p->group_index == group)
   7917         {
   7918             BCM_IF_ERROR_RETURN(_bcm_en_oam_destroy_endpoint(unit,
   7919                 endpoint_p));
   7920         }
   7921     }
   7922 
   7923     return BCM_E_NONE;
   7924 }
   7925 
   7926 /*
   7927  * Function:
   7928  *      bcm_en_oam_endpoint_traverse
   7929  * Purpose:
   7930  *      Traverse the set of OAM endpoints associated with the
   7931  *      specified group, calling a specified callback for each one
   7932  * Parameters:
   7933  *      unit - (IN) Unit number.
   7934  *      group - (IN) The OAM group whose endpoints should be traversed
   7935  *      cb - (IN) A pointer to the callback function to call for each OAM endpoint in the specified group
   7936  *      user_data - (IN) Pointer to user data to supply in the callback
   7937  * Returns:
   7938  *      BCM_E_XXX
   7939  * Notes:
   7940  */
   7941 int 
   7942 bcm_en_oam_endpoint_traverse(
   7943     int unit, 
   7944     bcm_oam_group_t group, 
   7945     bcm_oam_endpoint_traverse_cb cb, 
   7946     void *user_data)
   7947 {
   7948     _bcm_oam_info_t *oam_info_p;
   7949     _bcm_oam_endpoint_t *endpoint_p;
   7950     int endpoint_index;
   7951     bcm_oam_endpoint_info_t endpoint_info;
   7952 
   7953     SET_OAM_INFO;
   7954 
   7955     CHECK_INIT;
   7956 
   7957     VALIDATE_GROUP_INDEX(group);
   7958 
   7959     if (cb == NULL)
   7960     {
   7961         return BCM_E_PARAM;
   7962     }
   7963 
   7964     for (endpoint_index = 0; endpoint_index < oam_info_p->endpoint_count;
   7965         ++endpoint_index)
   7966     {
   7967         SET_ENDPOINT(endpoint_index);
   7968 
   7969         if (endpoint_p->in_use && endpoint_p->group_index == group)
   7970         {
   7971             bcm_oam_endpoint_info_t_init(&endpoint_info);
   7972             BCM_IF_ERROR_RETURN(_bcm_en_oam_get_endpoint(unit,
   7973 		oam_info_p, endpoint_index, endpoint_p, &endpoint_info));
   7974             BCM_IF_ERROR_RETURN(cb(unit, &endpoint_info, user_data));
   7975         }
   7976     }
   7977 
   7978     return BCM_E_NONE;
   7979 }
   7980 
   7981 /*
   7982  * Function:
   7983  *      bcm_en_oam_event_register
   7984  * Purpose:
   7985  *      Register a callback for handling OAM events
   7986  * Parameters:
   7987  *      unit - (IN) Unit number.
   7988  *      event_types - (IN) The set of OAM events for which the specified callback should be called
   7989  *      cb - (IN) A pointer to the callback function to call for the specified OAM events
   7990  *      user_data - (IN) Pointer to user data to supply in the callback
   7991  * Returns:
   7992  *      BCM_E_XXX
   7993  * Notes:
   7994  */
   7995 int 
   7996 bcm_en_oam_event_register(
   7997     int unit, 
   7998     bcm_oam_event_types_t event_types, 
   7999     bcm_oam_event_cb cb, 
   8000     void *user_data)
   8001 {
   8002     _bcm_oam_info_t *oam_info_p;
   8003     uint32 result;
   8004     _bcm_oam_event_handler_t *event_handler_p;
   8005     _bcm_oam_event_handler_t *previous_p = NULL;
   8006     bcm_oam_event_type_t event_type;
   8007     uint32 interrupt_control_register_value;
   8008     int update_interrupt_control = 0;
   8009 
   8010     SET_OAM_INFO;
   8011 
   8012     CHECK_INIT;
   8013 
   8014     if (cb == NULL)
   8015     {
   8016         return BCM_E_PARAM;
   8017     }
   8018 
   8019     SHR_BITTEST_RANGE(event_types.w, 0, bcmOAMEventCount, result);
   8020 
   8021     if (result == 0)
   8022     {
   8023         return BCM_E_PARAM;
   8024     }
   8025 
   8026     for (event_handler_p = oam_info_p->event_handler_list_p;
   8027         event_handler_p != NULL;
   8028         event_handler_p = event_handler_p->next_p)
   8029     {
   8030         if (event_handler_p->cb == cb)
   8031         {
   8032             break;
   8033         }
   8034 
   8035         previous_p = event_handler_p;
   8036     }
   8037 
   8038     if (event_handler_p == NULL)
   8039     {
   8040         /* This handler hasn't been registered yet */
   8041 
   8042         event_handler_p = sal_alloc(sizeof(_bcm_oam_event_handler_t),
   8043             "OAM event handler");
   8044 
   8045         if (event_handler_p == NULL)
   8046         {
   8047             return BCM_E_MEMORY;
   8048         }
   8049 
   8050         event_handler_p->next_p = NULL;
   8051         event_handler_p->cb = cb;
   8052 
   8053         SHR_BITCLR_RANGE(event_handler_p->event_types.w, 0, bcmOAMEventCount);
   8054 
   8055         if (previous_p != NULL)
   8056         {
   8057             previous_p->next_p = event_handler_p;
   8058         }
   8059         else
   8060         {
   8061             oam_info_p->event_handler_list_p = event_handler_p;
   8062         }
   8063     }
   8064 
   8065     SOC_IF_ERROR_RETURN(READ_CCM_INTERRUPT_CONTROLr(unit,
   8066         &interrupt_control_register_value));
   8067 
   8068     for (event_type = 0; event_type < bcmOAMEventCount; ++event_type)
   8069     {
   8070         if (SHR_BITGET(event_types.w, event_type))
   8071         {
   8072             if (soc_feature(unit, soc_feature_bhh)) {
   8073 #if defined(BCM_KATANA_SUPPORT)  && defined(INCLUDE_BHH)
   8074 	    /*
   8075 	     * BHH events are generated by the uKernel
   8076 	     */     if ((event_type == bcmOAMEventBHHLBTimeout) ||
   8077                     (event_type == bcmOAMEventBHHLBDiscoveryUpdate) ||
   8078                     (event_type == bcmOAMEventBHHCCMTimeout) ||
   8079                     (event_type == bcmOAMEventBHHCCMTimeoutClear) ||
   8080                     (event_type == bcmOAMEventBHHCCMState) ||
   8081                     (event_type == bcmOAMEventBHHCCMRdi) ||
   8082                     (event_type == bcmOAMEventBHHCCMUnknownMegLevel) ||
   8083                     (event_type == bcmOAMEventBHHCCMUnknownMegId) ||
   8084                     (event_type == bcmOAMEventBHHCCMUnknownMepId) ||
   8085                     (event_type == bcmOAMEventBHHCCMUnknownPeriod) ||
   8086                     (event_type == bcmOAMEventBHHCCMUnknownPriority) ||
   8087                     (event_type == bcmOAMEventBHHCCMRdiClear) ||
   8088                     (event_type == bcmOAMEventBHHCCMUnknownMegLevelClear) ||
   8089                     (event_type == bcmOAMEventBHHCCMUnknownMegIdClear) ||
   8090                     (event_type == bcmOAMEventBHHCCMUnknownMepIdClear) ||
   8091                     (event_type == bcmOAMEventBHHCCMUnknownPeriodClear) ||
   8092                     (event_type == bcmOAMEventBHHCCMUnknownPriorityClear) ||
   8093                     (event_type == bcmOAMEventCsfLos) ||
   8094                     (event_type == bcmOAMEventCsfFdi) ||
   8095                     (event_type == bcmOAMEventCsfRdi) ||
   8096                     (event_type == bcmOAMEventCsfDci)) {
   8097                     SHR_BITSET(event_handler_p->event_types.w, event_type);
   8098                     ++(oam_info_p->event_handler_count[event_type]);
   8099                     continue;
   8100                 }
   8101                 
   8102 #endif
   8103             }
   8104             if (!soc_reg_field_valid(unit, CCM_INTERRUPT_CONTROLr,
   8105                                     en_interrupt_enable_fields[event_type].field))
   8106             {
   8107                  continue;
   8108             }
   8109             if (!SHR_BITGET(event_handler_p->event_types.w, event_type))
   8110             {
   8111                 /* This handler isn't handling this event yet */
   8112                 SHR_BITSET(event_handler_p->event_types.w, event_type);
   8113 
   8114                 ++(oam_info_p->event_handler_count[event_type]);
   8115 
   8116                 if (oam_info_p->event_handler_count[event_type] == 1) {
   8117                     /* This is the first handler for this event */
   8118                     update_interrupt_control = 1;
   8119                     if (soc_reg_field_valid(unit, CCM_INTERRUPT_CONTROLr,
   8120                             en_interrupt_enable_fields[event_type].field)) {
   8121                         soc_reg_field_set(unit, CCM_INTERRUPT_CONTROLr,
   8122                         &interrupt_control_register_value,
   8123                         en_interrupt_enable_fields[event_type].field, 1);
   8124                     }
   8125                 }
   8126             }
   8127         }
   8128     }
   8129 
   8130     event_handler_p->user_data = user_data;
   8131 
   8132     /* Enable any needed interrupts not yet enabled */
   8133 
   8134     if (update_interrupt_control)
   8135     {
   8136         SOC_IF_ERROR_RETURN(WRITE_CCM_INTERRUPT_CONTROLr(unit,
   8137             interrupt_control_register_value));
   8138     }
   8139 
   8140     if (soc_feature(unit, soc_feature_bhh)) {
   8141 #if defined(BCM_KATANA_SUPPORT)  && defined(INCLUDE_BHH)
   8142         /* 
   8143          * Update BHH Events mask 
   8144          */
   8145         if (SOC_IS_KATANAX(unit)) {
   8146             return _bcm_en_oam_bhh_event_mask_set(unit);
   8147         }
   8148 #endif
   8149     }
   8150 
   8151     return BCM_E_NONE;
   8152 }
   8153 
   8154 /*
   8155  * Function:
   8156  *      bcm_en_oam_event_unregister
   8157  * Purpose:
   8158  *      Unregister a callback for handling OAM events
   8159  * Parameters:
   8160  *      unit - (IN) Unit number.
   8161  *      event_types - (IN) The set of OAM events for which the specified callback should not be called
   8162  *      cb - (IN) A pointer to the callback function to unregister from the specified OAM events
   8163  * Returns:
   8164  *      BCM_E_XXX
   8165  * Notes:
   8166  */
   8167 int 
   8168 bcm_en_oam_event_unregister(
   8169     int unit, 
   8170     bcm_oam_event_types_t event_types, 
   8171     bcm_oam_event_cb cb)
   8172 {
   8173      _bcm_oam_info_t *oam_info_p;
   8174     uint32 result;
   8175     _bcm_oam_event_handler_t *event_handler_p;
   8176     _bcm_oam_event_handler_t *previous_p = NULL;
   8177     bcm_oam_event_type_t event_type;
   8178     uint32 interrupt_control_register_value;
   8179     int update_interrupt_control = 0;
   8180 
   8181     SET_OAM_INFO;
   8182 
   8183     CHECK_INIT;
   8184 
   8185     if (cb == NULL)
   8186     {
   8187         return BCM_E_PARAM;
   8188     }
   8189 
   8190     SHR_BITTEST_RANGE(event_types.w, 0, bcmOAMEventCount, result);
   8191 
   8192     if (result == 0)
   8193     {
   8194         return BCM_E_PARAM;
   8195     }
   8196 
   8197     for (event_handler_p = oam_info_p->event_handler_list_p;
   8198         event_handler_p != NULL;
   8199         event_handler_p = event_handler_p->next_p)
   8200     {
   8201         if (event_handler_p->cb == cb)
   8202         {
   8203             break;
   8204         }
   8205 
   8206         previous_p = event_handler_p;
   8207     }
   8208 
   8209     if (event_handler_p == NULL)
   8210     {
   8211         return BCM_E_NOT_FOUND;
   8212     }
   8213 
   8214     SOC_IF_ERROR_RETURN(READ_CCM_INTERRUPT_CONTROLr(unit,
   8215         &interrupt_control_register_value));
   8216 
   8217     for (event_type = 0; event_type < bcmOAMEventCount; ++event_type)
   8218     {
   8219         if (SHR_BITGET(event_types.w, event_type))
   8220         {
   8221             if(soc_feature(unit, soc_feature_bhh)) {
   8222 #if defined(BCM_KATANA_SUPPORT)  && defined(INCLUDE_BHH)
   8223 	        /*
   8224 	         * BHH events are generated by the uKernel
   8225 	         */
   8226             if ((event_type == bcmOAMEventBHHLBTimeout) ||
   8227                 (event_type == bcmOAMEventBHHLBDiscoveryUpdate) ||
   8228                 (event_type == bcmOAMEventBHHCCMTimeout) ||
   8229                 (event_type == bcmOAMEventBHHCCMTimeoutClear) ||
   8230                 (event_type == bcmOAMEventBHHCCMState) ||
   8231                 (event_type == bcmOAMEventBHHCCMRdi) ||
   8232                 (event_type == bcmOAMEventBHHCCMUnknownMegLevel) ||
   8233                 (event_type == bcmOAMEventBHHCCMUnknownMegId) ||
   8234                 (event_type == bcmOAMEventBHHCCMUnknownMepId) ||
   8235                 (event_type == bcmOAMEventBHHCCMUnknownPeriod) ||
   8236                 (event_type == bcmOAMEventBHHCCMUnknownPriority) ||
   8237                 (event_type == bcmOAMEventBHHCCMRdiClear) ||
   8238                 (event_type == bcmOAMEventBHHCCMUnknownMegLevelClear) ||
   8239                 (event_type == bcmOAMEventBHHCCMUnknownMegIdClear) ||
   8240                 (event_type == bcmOAMEventBHHCCMUnknownMepIdClear) ||
   8241                 (event_type == bcmOAMEventBHHCCMUnknownPeriodClear) ||
   8242                 (event_type == bcmOAMEventBHHCCMUnknownPriorityClear) ||
   8243                 (event_type == bcmOAMEventCsfLos) ||
   8244                 (event_type == bcmOAMEventCsfFdi) ||
   8245                 (event_type == bcmOAMEventCsfRdi) ||
   8246                 (event_type == bcmOAMEventCsfDci)) {
   8247                     SHR_BITCLR(event_handler_p->event_types.w, event_type);
   8248                     --(oam_info_p->event_handler_count[event_type]);
   8249                     continue;
   8250             }
   8251 
   8252 #endif
   8253             }
   8254             if (!soc_reg_field_valid(unit, CCM_INTERRUPT_CONTROLr,
   8255                                     en_interrupt_enable_fields[event_type].field))
   8256             {
   8257                 continue;
   8258             }
   8259             if (oam_info_p->event_handler_count[event_type] > 0 &&
   8260                 SHR_BITGET(event_handler_p->event_types.w, event_type))
   8261             {
   8262                 /* This handler has been handling this event */
   8263 
   8264                 SHR_BITCLR(event_handler_p->event_types.w, event_type);
   8265 
   8266                 --(oam_info_p->event_handler_count[event_type]);
   8267 
   8268                 if (oam_info_p->event_handler_count[event_type] == 0)
   8269                 {
   8270                 	/* No more handlers for this event */
   8271 
   8272                     update_interrupt_control = 1;
   8273                     if (soc_reg_field_valid(unit, CCM_INTERRUPT_CONTROLr,
   8274                         en_interrupt_enable_fields[event_type].field)) {
   8275                         soc_reg_field_set(unit, CCM_INTERRUPT_CONTROLr,
   8276                         &interrupt_control_register_value,
   8277                         en_interrupt_enable_fields[event_type].field, 0);
   8278                     }
   8279                 }
   8280             }
   8281         }
   8282     }
   8283 
   8284     /* Disable any interrupts that lost their last handler */
   8285 
   8286     if (update_interrupt_control)
   8287     {
   8288         SOC_IF_ERROR_RETURN(WRITE_CCM_INTERRUPT_CONTROLr(unit,
   8289             interrupt_control_register_value));
   8290     }
   8291 
   8292     SHR_BITTEST_RANGE(event_handler_p->event_types.w, 0, bcmOAMEventCount,
   8293         result);
   8294 
   8295     if (result == 0)
   8296     {
   8297         /* No more events for this handler to handle */
   8298 
   8299         if (previous_p != NULL)
   8300         {
   8301             previous_p->next_p = event_handler_p->next_p;
   8302         }
   8303         else
   8304         {
   8305             oam_info_p->event_handler_list_p = event_handler_p->next_p;
   8306         }
   8307 
   8308         sal_free(event_handler_p);
   8309     }
   8310 
   8311     if (soc_feature(unit, soc_feature_bhh)) {
   8312 #if defined(BCM_KATANA_SUPPORT)  && defined(INCLUDE_BHH)
   8313      /* 
   8314       * Update BHH Events mask 
   8315       */
   8316     if (SOC_IS_KATANAX(unit)) {
   8317 	    return _bcm_en_oam_bhh_event_mask_set(unit);
   8318     }
   8319 #endif
   8320     }
   8321     
   8322     return BCM_E_NONE;
   8323 }
   8324 
   8325 #if defined(BCM_KATANA_SUPPORT) && defined(INCLUDE_BHH)
   8326 /*
   8327  * Function:
   8328  *     _bcm_en_oam_trunk_ports_update
   8329  * Purpose:
   8330  *     Associate or Dissociate ports from trunk in mapping table
   8331  *     maintained by BTE
   8332  * Parameters:
   8333  *     unit        - Device unit number
   8334  *     trunk_gport - Trunk Gport
   8335  *     max_ports   - Num ports being added/deleted
   8336  *     port_arr    - Array of physical port gports being added/deleted
   8337  *     add         - add == 1 indicates ports are being added
   8338  * Returns:
   8339  *     BCM_E_XXX
   8340  */
   8341 STATIC int
   8342 _bcm_en_oam_trunk_ports_update(int unit, bcm_gport_t trunk_gport, int max_ports,
   8343                                 bcm_gport_t *port_arr, uint8 add)
   8344 {
   8345     bcm_trunk_t                          trunk_id = BCM_TRUNK_INVALID;
   8346     _bcm_oam_info_t                     *oam_info_p;
   8347     bhh_sdk_msg_ctrl_trunk_map_update_t  msg;
   8348     uint8                               *buffer, *buffer_ptr;
   8349     uint16                               buffer_len, reply_len;
   8350     int                                  rv = BCM_E_NONE;
   8351     int                                  i;
   8352 
   8353     SET_OAM_INFO;
   8354 
   8355     if (oam_info_p->ukernel_not_ready) {
   8356         return BCM_E_INIT;
   8357     }
   8358 
   8359     if (!BCM_GPORT_IS_TRUNK(trunk_gport)) {
   8360         return BCM_E_PARAM;
   8361     }
   8362 
   8363     if (max_ports >= SHR_BHH_MAX_PORTS) {
   8364         return BCM_E_PARAM;
   8365     }
   8366 
   8367     if (!port_arr) {
   8368         return BCM_E_PARAM;
   8369     }
   8370 
   8371     trunk_id = BCM_GPORT_TRUNK_GET(trunk_gport);
   8372     if (trunk_id == BCM_TRUNK_INVALID) {
   8373         return BCM_E_PARAM;
   8374     }
   8375 
   8376     if (add) {
   8377         msg.trunk_id = trunk_id;
   8378     } else {
   8379         msg.trunk_id = SHR_BHH_INVALID_TRUNK_ID;
   8380     }
   8381     msg.num_ports = max_ports;
   8382     for (i = 0; i < max_ports; i++) {
   8383         if (BCM_GPORT_IS_LOCAL(port_arr[i])) {
   8384             msg.port_list[i] = BCM_GPORT_LOCAL_GET(port_arr[i]);
   8385         } else if (BCM_GPORT_IS_MODPORT(port_arr[i])) {
   8386             msg.port_list[i] = BCM_GPORT_MODPORT_PORT_GET(port_arr[i]);
   8387         } else {
   8388             return BCM_E_PARAM;
   8389         }
   8390     }
   8391 
   8392     /* Pack control message data into DMA buffer */
   8393     buffer     = oam_info_p->dma_buffer;
   8394     buffer_ptr = bhh_sdk_msg_ctrl_trunk_map_update_pack(buffer, &msg);
   8395     buffer_len = buffer_ptr - buffer;
   8396 
   8397     rv = _bcm_en_oam_bhh_msg_send_receive(
   8398                                    unit,
   8399                                    MOS_MSG_SUBCLASS_BHH_PORT_TRUNK_UPDATE,
   8400                                    buffer_len, 0,
   8401                                    MOS_MSG_SUBCLASS_BHH_PORT_TRUNK_UPDATE_REPLY,
   8402                                    &reply_len);
   8403 
   8404 
   8405     if (BCM_FAILURE(rv)) {
   8406         return (rv);
   8407     }
   8408 
   8409     return BCM_E_NONE;
   8410 }
   8411 
   8412 /*
   8413  * Function:
   8414  *     bcm_en_oam_trunk_ports_add
   8415  * Purpose:
   8416  *     Associate  ports from trunk in mapping table maintained by BTE
   8417  * Parameters:
   8418  *     unit        - Device unit number
   8419  *     trunk_gport - Trunk Gport
   8420  *     max_ports   - Num ports being added
   8421  *     port_arr    - Array of physical port gports being added
   8422  * Returns:
   8423  *     BCM_E_XXX
   8424  */
   8425 int bcm_en_oam_trunk_ports_add(int unit, bcm_gport_t trunk_gport,
   8426                                 int max_ports, bcm_gport_t *port_arr)
   8427 {
   8428     return _bcm_en_oam_trunk_ports_update(unit, trunk_gport, max_ports,
   8429                                            port_arr, 1);
   8430 }
   8431 
   8432 /*
   8433  * Function:
   8434  *     bcm_en_oam_trunk_ports_delete
   8435  * Purpose:
   8436  *     Dissociate ports from trunk in mapping table maintained by BTE
   8437  * Parameters:
   8438  *     unit        - Device unit number
   8439  *     trunk_gport - Trunk Gport
   8440  *     max_ports   - Num ports being deleted
   8441  *     port_arr    - Array of physical port gports being deleted
   8442  * Returns:
   8443  *     BCM_E_XXX
   8444  */
   8445 int bcm_en_oam_trunk_ports_delete(int unit, bcm_gport_t trunk_gport,
   8446                                    int max_ports, bcm_gport_t *port_arr)
   8447 {
   8448     return _bcm_en_oam_trunk_ports_update(unit, trunk_gport, max_ports,
   8449                                            port_arr, 0);
   8450 }
   8451 
   8452 /*
   8453  * Function:
   8454  *     bcm_en_oam_trunk_ports_get
   8455  * Purpose:
   8456  *     Get port to trunk mapping from UKERNEL
   8457  * Parameters:
   8458  *     unit          - (IN) BCM device number
   8459  *     trunk_gport   - (IN) Trunk gport
   8460  *     max_ports     - (IN) Max ports the port_arr can accomodate
   8461  *     port_arr      - (OUT) Ports in the trunk
   8462  *     port_count    - (OUT) Valid number of ports in the port_arr
   8463  *
   8464  * Returns:
   8465  *      BCM_E_XXX
   8466  */
   8467 int
   8468 bcm_en_oam_trunk_ports_get(int unit, bcm_gport_t trunk_gport, int max_ports,
   8469                             bcm_gport_t *port_arr, int *port_count)
   8470 {
   8471     bhh_sdk_msg_ctrl_trunk_map_get_t     msg;
   8472     uint8                               *buffer, *buffer_ptr;
   8473     uint16                               buffer_len, reply_len;
   8474     bcm_trunk_t                          trunk_id;
   8475     _bcm_oam_info_t                     *oam_info_p;
   8476     int                                  rv = BCM_E_NONE;
   8477     int                                  i;
   8478 
   8479     SET_OAM_INFO;
   8480 
   8481     if (!BCM_GPORT_IS_TRUNK(trunk_gport)) {
   8482         return BCM_E_PARAM;
   8483     }
   8484 
   8485     trunk_id = BCM_GPORT_TRUNK_GET(trunk_gport);
   8486     if (trunk_id == BCM_TRUNK_INVALID) {
   8487         return BCM_E_PARAM;
   8488     }
   8489 
   8490 
   8491     /* Send trunk_id in the send length variable */
   8492     rv = _bcm_en_oam_bhh_msg_send_receive(
   8493                                    unit,
   8494                                    MOS_MSG_SUBCLASS_BHH_PORT_TRUNK_GET,
   8495                                    trunk_id, 0,
   8496                                    MOS_MSG_SUBCLASS_BHH_PORT_TRUNK_GET_REPLY,
   8497                                    &reply_len);
   8498     if (BCM_FAILURE(rv)) {
   8499         return rv;
   8500     }
   8501 
   8502     sal_memset(&msg, 0, sizeof(msg));
   8503     buffer     = oam_info_p->dma_buffer;
   8504     buffer_ptr = bhh_sdk_msg_ctrl_trunk_map_get_unpack(buffer, &msg);
   8505     buffer_len = buffer_ptr - buffer;
   8506 
   8507     if (reply_len != buffer_len) {
   8508         return BCM_E_INTERNAL;
   8509     }
   8510 
   8511     *port_count = msg.num_ports;
   8512     for (i = 0; (i < *port_count) && (i < max_ports); i++) {
   8513         port_arr[i] = msg.port_list[i];
   8514     }
   8515 
   8516     return BCM_E_NONE;;
   8517 }
   8518 #endif /* BCM_KATANA_SUPPORT && INCLUDE_BHH */
   8519 
   8520 #if defined(BCM_WARM_BOOT_SUPPORT)
   8521 int _bcm_en_oam_sync(int unit)
   8522 {
   8523     _bcm_oam_info_t *oam_info_p;
   8524     _bcm_oam_group_t *group_p;
   8525     int group_index, group_count = 0;
   8526     int stable_size;
   8527     soc_scache_handle_t scache_handle;
   8528     uint8 *oam_scache, *ptr;
   8529     bcm_oam_endpoint_t epidx;
   8530     _bcm_oam_endpoint_t *endpoint_p;
   8531 
   8532     SET_OAM_INFO;
   8533 
   8534     CHECK_INIT;
   8535 
   8536     SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size));
   8537     if (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit) || (stable_size == 0)) {
   8538         return BCM_E_NONE;
   8539     }
   8540 
   8541     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_OAM, 0);
   8542     BCM_IF_ERROR_RETURN(_bcm_esw_scache_ptr_get(unit, scache_handle, 0,
   8543                                                 0, &oam_scache,
   8544                                                 BCM_WB_DEFAULT_VERSION, NULL));
   8545 
   8546     if (oam_scache == NULL)
   8547     {
   8548         return BCM_E_MEMORY;
   8549     }
   8550 
   8551     /* Store the FP groups */
   8552     sal_memcpy(oam_scache, &oam_info_p->vfp_group, sizeof(bcm_field_group_t));
   8553     oam_scache += sizeof(bcm_field_group_t);
   8554     sal_memcpy(oam_scache, &oam_info_p->fp_vp_group, sizeof(bcm_field_group_t));
   8555     oam_scache += sizeof(bcm_field_group_t);
   8556     sal_memcpy(oam_scache, &oam_info_p->fp_glp_group, sizeof(bcm_field_group_t));
   8557     oam_scache += sizeof(bcm_field_group_t);
   8558 
   8559     /* Store the OAM group names */
   8560     sal_memcpy(oam_scache, &group_count, sizeof(int));
   8561     oam_scache += sizeof(int);
   8562 
   8563     for (group_index = 0; group_index < oam_info_p->group_count;
   8564         ++group_index)
   8565     {
   8566         SET_GROUP(group_index);
   8567 
   8568         if (group_p->in_use)
   8569         {
   8570             memcpy(oam_scache, group_p->name, BCM_OAM_GROUP_NAME_LENGTH);
   8571 
   8572             oam_scache += BCM_OAM_GROUP_NAME_LENGTH;
   8573         }
   8574     }
   8575 
   8576     /* Store Endpoint IDs */
   8577     for (epidx = 0; epidx < oam_info_p->endpoint_count; epidx++) {
   8578 
   8579         SET_ENDPOINT(epidx);
   8580         if (!endpoint_p->in_use) {
   8581             continue;
   8582         }
   8583 
   8584         if (endpoint_p->flags & BCM_OAM_ENDPOINT_REMOTE) {
   8585             /* Remote Endpoint */
   8586             ptr = BCM_OAM_WB_SCACHE_V1_REMOTE_EP_ID_OFFSET(
   8587                                                        oam_scache,
   8588                                                        endpoint_p->remote_index);
   8589             sal_memcpy(ptr, &epidx, sizeof(bcm_oam_endpoint_t));
   8590         } else {
   8591             if (endpoint_p->local_tx_enabled) {
   8592                 /* Tx enabled Endpoint */
   8593                 ptr = BCM_OAM_WB_SCACHE_V1_TX_EP_ID_OFFSET(
   8594                                                      oam_scache,
   8595                                                      endpoint_p->local_tx_index);
   8596                 sal_memcpy(ptr, &epidx, sizeof(bcm_oam_endpoint_t));
   8597             }
   8598             if (endpoint_p->local_rx_enabled) {
   8599                 /* Rx enabled Endpoint */
   8600                 ptr = BCM_OAM_WB_SCACHE_V1_RX_EP_ID_OFFSET(
   8601                                                      oam_scache,
   8602                                                      endpoint_p->local_rx_index);
   8603                 sal_memcpy(ptr, &epidx, sizeof(bcm_oam_endpoint_t));
   8604             }
   8605         }
   8606     }
   8607     oam_scache += (oam_info_p->endpoint_count * sizeof(bcm_oam_endpoint_t));
   8608 
   8609     return BCM_E_NONE;
   8610 }
   8611 #endif /* BCM_WARM_BOOT_SUPPORT */
   8612 
   8613 #ifdef BCM_WARM_BOOT_SUPPORT_SW_DUMP
   8614 void
   8615 _bcm_en_oam_group_info_dump(int unit, bcm_oam_group_t group_index,
   8616                              _bcm_oam_group_t *group_p)
   8617 {
   8618     int                     rv;
   8619     bcm_oam_group_info_t    group_info;
   8620 
   8621     /* Initialize the group information structure. */
   8622     bcm_oam_group_info_t_init(&group_info);
   8623 
   8624     /* Retrieve group information and set in group_info structure. */
   8625     rv = _bcm_en_oam_get_group(unit, group_index, group_p, &group_info);
   8626     if (BCM_FAILURE(rv)) {
   8627         LOG_ERROR(BSL_LS_BCM_OAM,
   8628                   (BSL_META_U(unit,
   8629                               "OAM(unit %d) Error: _bcm_en_oam_group_info_dump"
   8630                               " (GID=%d) - %s.\n"),
   8631                               unit, group_index, bcm_errmsg(rv)));
   8632         return;
   8633     }
   8634     LOG_CLI((BSL_META_U(unit,"------------------------------------------\r\n")));
   8635     LOG_CLI((BSL_META_U(unit,"Group ID = %d details\r\n"), group_index));
   8636     LOG_CLI((BSL_META_U(unit,"Group Name =  %s\r\n"), group_info.name));
   8637     LOG_CLI((BSL_META_U(unit,"Flags =  %d\r\n"), group_info.flags));
   8638     LOG_CLI((BSL_META_U(unit,"Faults =  %d\r\n"), group_info.faults));
   8639     LOG_CLI((BSL_META_U(unit,"Persistent_faults =  %d\r\n"),
   8640                               group_info.persistent_faults));
   8641     LOG_CLI((BSL_META_U(unit,"clear_persistent_faults =  %d\r\n"),
   8642                               group_info.clear_persistent_faults));
   8643     LOG_CLI((BSL_META_U(unit,"lowest_alarm_priority =  %d\r\n"),
   8644                               group_info.lowest_alarm_priority));
   8645     LOG_CLI((BSL_META_U(unit,"------------------------------------------\r\n")));
   8646 }
   8647 
   8648 /*
   8649  * Function:
   8650  *     _bcm_oam_sw_dump
   8651  * Purpose:
   8652  *     Displays oam information maintained by software.
   8653  * Parameters:
   8654  *     unit - Device unit number
   8655  * Returns:
   8656  *     None
   8657  */
   8658 void
   8659 _bcm_en_oam_sw_dump(int unit)
   8660 {
   8661     _bcm_oam_info_t *oam_info_p;
   8662     _bcm_oam_endpoint_t *endpoint_p;
   8663     int group_idx, endpoint_idx;
   8664     _bcm_oam_group_t *group_p;
   8665     SHR_BITDCL word;
   8666     SET_OAM_INFO;
   8667 
   8668     LOG_CLI((BSL_META_U(unit,
   8669                         "\nSW Information OAM - Unit %d\n"), unit));
   8670     LOG_CLI((BSL_META_U(unit,
   8671                         "  Group Info    : \n")));
   8672 
   8673     for (group_idx = 0; group_idx < oam_info_p->group_count; group_idx++) {
   8674         SET_GROUP(group_idx);
   8675         if (group_p->in_use) {
   8676             _bcm_en_oam_group_info_dump(unit, group_idx, group_p);
   8677         }
   8678     }
   8679 
   8680     LOG_CLI((BSL_META_U(unit,
   8681                         "\n local_tx_endpoints_in_use \n")));
   8682     for (word = 0; word < _SHR_BITDCLSIZE
   8683          (oam_info_p->local_tx_endpoint_count); word++) {
   8684         LOG_CLI((BSL_META_U(unit,
   8685                             " word %d value %x "), word, 
   8686                  oam_info_p->local_tx_endpoints_in_use[word]));
   8687     }
   8688 
   8689     LOG_CLI((BSL_META_U(unit,
   8690                         "\n local_rx_endpoints_in_use \n")));
   8691     for (word = 0; word < _SHR_BITDCLSIZE
   8692          (oam_info_p->local_rx_endpoint_count); word++) {
   8693         LOG_CLI((BSL_META_U(unit,
   8694                             " word %d value %x "), word, 
   8695                  oam_info_p->local_rx_endpoints_in_use[word]));
   8696     }
   8697 
   8698     LOG_CLI((BSL_META_U(unit,
   8699                         "\n remote_endpoints_in_use \n")));
   8700     for (word = 0; word < _SHR_BITDCLSIZE
   8701          (oam_info_p->remote_endpoint_count); word++) {
   8702         LOG_CLI((BSL_META_U(unit,
   8703                             " word %d value %x "), word, 
   8704                  oam_info_p->remote_endpoints_in_use[word]));
   8705     }
   8706 
   8707     LOG_CLI((BSL_META_U(unit,
   8708                         "\n Reverse RMEP lookup \n")));
   8709     for (endpoint_idx = 0; endpoint_idx < oam_info_p->remote_endpoint_count; 
   8710          endpoint_idx++) {
   8711         if (SHR_BITGET(oam_info_p->remote_endpoints_in_use, endpoint_idx)) {
   8712             LOG_CLI((BSL_META_U(unit,
   8713                                 "RMEP %x \n"), 
   8714                      oam_info_p->remote_endpoints[endpoint_idx]));
   8715         } 
   8716     }
   8717 
   8718     LOG_CLI((BSL_META_U(unit,
   8719                         "\n lm_counter_in_use \n")));
   8720     for (word = 0; word < _SHR_BITDCLSIZE
   8721          (oam_info_p->lm_counter_count); word++) {
   8722         LOG_CLI((BSL_META_U(unit,
   8723                             " word %d value %x "), word, 
   8724                  oam_info_p->lm_counter_in_use[word]));
   8725     }
   8726 
   8727     LOG_CLI((BSL_META_U(unit,
   8728                         "\n Endpoint Information \n")));
   8729     for (endpoint_idx = 0; endpoint_idx < oam_info_p->endpoint_count; 
   8730          endpoint_idx++) {
   8731         SET_ENDPOINT(endpoint_idx);
   8732         if (!endpoint_p->in_use) {
   8733             continue;
   8734         }
   8735         LOG_CLI((BSL_META_U(unit,
   8736                             "\n Endpoint index %d\n"), endpoint_idx));
   8737         LOG_CLI((BSL_META_U(unit,
   8738                             "\t Group index %d\n"), endpoint_p->group_index));
   8739         LOG_CLI((BSL_META_U(unit,
   8740                             "\t Name %x\n"), endpoint_p->name));
   8741         LOG_CLI((BSL_META_U(unit,
   8742                             "\t Level %d\n"), endpoint_p->level));
   8743         LOG_CLI((BSL_META_U(unit,
   8744                             "\t VLAN %d\n"), endpoint_p->vlan));
   8745         LOG_CLI((BSL_META_U(unit,
   8746                             "\t GLP %x\n"), endpoint_p->glp));
   8747         LOG_CLI((BSL_META_U(unit,
   8748                             "\t local_tx_enabled %d\n"), endpoint_p->local_tx_enabled));
   8749         LOG_CLI((BSL_META_U(unit,
   8750                             "\t local_rx_enabled %d\n"), endpoint_p->local_rx_enabled));
   8751         LOG_CLI((BSL_META_U(unit,
   8752                             "\t remote_index %d\n"), endpoint_p->remote_index));
   8753         LOG_CLI((BSL_META_U(unit,
   8754                             "\t local_tx_index %d\n"), endpoint_p->local_tx_index));
   8755         LOG_CLI((BSL_META_U(unit,
   8756                             "\t local_rx_index %d\n"), endpoint_p->local_rx_index));
   8757         LOG_CLI((BSL_META_U(unit,
   8758                             "\t VP %x\n"), endpoint_p->vp));
   8759         LOG_CLI((BSL_META_U(unit,
   8760                             "\t lm_counter_index %d\n"), endpoint_p->lm_counter_index));
   8761         LOG_CLI((BSL_META_U(unit,
   8762                             "\t pri_map_index %d\n"), endpoint_p->pri_map_index));
   8763         LOG_CLI((BSL_META_U(unit,
   8764                             "\t vfp_entry %d\n"), endpoint_p->vfp_entry));
   8765         LOG_CLI((BSL_META_U(unit,
   8766                             "\t fp_entry_tx %d\n"), endpoint_p->fp_entry_tx));
   8767         LOG_CLI((BSL_META_U(unit,
   8768                             "\t fp_entry_rx %d\n"), endpoint_p->fp_entry_rx));
   8769     }
   8770     return;
   8771 }
   8772 #endif
   8773 #endif /* defined(BCM_ENDURO) */