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


      1 /* 
      2  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      3  * 
      4  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      5  *
      6  * File:
      7  *  oam.c
      8  *
      9  * Purpose:
     10  *  OAM implementation for trident2p family of devices.
     11  */
     12 
     13 #include <shared/bsl.h>
     14 
     15 #include <sal/core/libc.h>
     16 #include <soc/defs.h>
     17 #include <soc/drv.h>
     18 #include <soc/scache.h>
     19 #include <soc/profile_mem.h>
     20 #include <soc/hash.h>
     21 
     22 #include <bcm/oam.h>
     23 #include <bcm/field.h>
     24 
     25 #include <bcm_int/esw/oam.h>
     26 #include <bcm_int/esw/port.h>
     27 #include <bcm_int/esw/switch.h>
     28 #include <bcm_int/esw/virtual.h>
     29 #include <bcm_int/esw_dispatch.h>
     30 
     31 #include <soc/shared/olp_pkt.h>
     32 #include <soc/shared/olp_pack.h>
     33 #include <soc/shared/oam_pm_shared.h>
     34 
     35 #if defined(INCLUDE_CCM) || defined(INCLUDE_BHH) || defined(INCLUDE_MPLS_LM_DM)
     36 #include <bcm_int/esw/fp_oam.h>
     37 #endif
     38 
     39 #if defined(INCLUDE_BHH)
     40 #include <bcm_int/esw/bhh_sdk_pack.h>
     41 #endif
     42 
     43 #if defined(INCLUDE_MPLS_LM_DM)
     44 #include <bcm_int/esw/mpls_lm_dm.h>
     45 #include <bcm_int/esw/mpls_lm_dm_feature.h>
     46 #include <bcm_int/esw/mpls_lm_dm_sdk_msg.h>
     47 #include <bcm_int/esw/mpls_lm_dm_sdk_pack.h>
     48 #endif /* INCLUDE_MPLS_LM_DM */
     49 
     50 #if defined(INCLUDE_BHH) || defined(INCLUDE_MPLS_LM_DM)
     51 #include <bcm_int/esw/flex_ctr.h>
     52 #include <bcm_int/esw/firebolt.h>
     53 #endif /* INCLUDE_BHH || INCLUDE_MPLS_LM_DM */
     54 
     55 
     56 /* WB sequence for the different modules in OAM */
     57 #if defined(BCM_WARM_BOOT_SUPPORT)
     58 typedef enum bcm_fp_oam_wb_sequence_e {
     59     bcmFpOamWbSequenceBhh      = 0,
     60     bcmFpOamWbSequenceMplsLmDm = 1,
     61     bcmFpOamWbSequenceCount    = 2
     62 } bcm_fp_oam_wb_sequence_t;
     63 #endif
     64 
     65 
     66 /*******************************************************************************/
     67 /* OAM Hardware configuration for TD2+ & Apache Start                          */
     68 /*******************************************************************************/
     69 /* Magic port used for remote OLP over HG communication */
     70 #define _BCM_OAM_TD2P_OLP_MAGIC_PORT 0x7F
     71 
     72 #define _BCM_TD2P_OLP_HDR_TYPE_RX                1
     73 #define _BCM_TD2P_OLP_HDR_TYPE_MACSEC_ENCRYPT    2
     74 #define _BCM_TD2P_OLP_HDR_TYPE_MACSEC_DECRYPT    3
     75 
     76 /* OLP_HDR_SUBTYPE filled with one of the following values */
     77 /* Down mep subtypes */
     78 #define _BCM_TD2P_OLP_HDR_SUBTYPE_ETH_OAM_CCM             0x01
     79 #define _BCM_TD2P_OLP_HDR_SUBTYPE_ETH_OAM_LM              0x02
     80 #define _BCM_TD2P_OLP_HDR_SUBTYPE_ETH_OAM_DM              0x03
     81 #define _BCM_TD2P_OLP_HDR_SUBTYPE_ETH_OAM_OTHER_OC        0x04
     82 #define _BCM_TD2P_OLP_HDR_SUBTYPE_BHH_CCM                 0x05
     83 #define _BCM_TD2P_OLP_HDR_SUBTYPE_BHH_LM                  0x06
     84 #define _BCM_TD2P_OLP_HDR_SUBTYPE_BHH_DM                  0x07
     85 #define _BCM_TD2P_OLP_HDR_SUBTYPE_BHH_OTHER_OC            0x08
     86 #define _BCM_TD2P_OLP_HDR_SUBTYPE_BFD                     0x09
     87 #define _BCM_TD2P_OLP_HDR_SUBTYPE_MPLS_LMDM_DLM           0x0A
     88 #define _BCM_TD2P_OLP_HDR_SUBTYPE_MPLS_LMDM_DM            0x0B
     89 #define _BCM_TD2P_OLP_HDR_SUBTYPE_MPLS_LMDM_DLM_DM        0x0C
     90 #define _BCM_TD2P_OLP_HDR_SUBTYPE_MPLS_LMDM_ILM           0x0D
     91 #define _BCM_TD2P_OLP_HDR_SUBTYPE_MPLS_LMDM_ILM_DM        0x0E
     92 #define _BCM_TD2P_OLP_HDR_SUBTYPE_SAT                     0x0F
     93 #define _BCM_TD2P_OLP_HDR_SUBTYPE_OTH_ACH                 0x10
     94 
     95 /* Up mep subtypes */
     96 #define _BCM_TD2P_OLP_HDR_SUBTYPE_ETH_OAM_CCM_UP             0x11
     97 #define _BCM_TD2P_OLP_HDR_SUBTYPE_ETH_OAM_LM_UP              0x12
     98 #define _BCM_TD2P_OLP_HDR_SUBTYPE_ETH_OAM_DM_UP              0x13
     99 #define _BCM_TD2P_OLP_HDR_SUBTYPE_ETH_OAM_OTHER_OC_UP        0x14
    100 #define _BCM_TD2P_OLP_HDR_SUBTYPE_SAT_UP                     0x15
    101 
    102 #define _BCM_TD2P_OLP_HDR_SUBTYPE_MACSEC_ENCRYPT             0x00
    103 #define _BCM_TD2P_OLP_HDR_SUBTYPE_MACSEC_DECRYPT             0x01
    104 
    105 typedef struct _bcm_td2p_olp_hdr_type_mapping_s {
    106     bcm_field_olp_header_type_t     field_olp_hdr_type;
    107     uint8                           subtype;
    108 } _bcm_td2p_olp_hdr_type_mapping_t;
    109 
    110 STATIC _bcm_td2p_olp_hdr_type_mapping_t td2p_olp_hdr_type_mapping[] = {
    111 
    112     /* Field OLP header type to Subtype mapping table
    113      * Note: Do not change the order, as EGR_OLP_HEADER_TYPE_MAPPING table is
    114      *       programmed in the same order.
    115      */
    116 
    117 /* BFD */
    118 {bcmFieldOlpHeaderTypeBfdOam, _BCM_TD2P_OLP_HDR_SUBTYPE_BFD},
    119 
    120 /* ETH OAM Down MEP*/
    121 {bcmFieldOlpHeaderTypeEthOamCcm, _BCM_TD2P_OLP_HDR_SUBTYPE_ETH_OAM_CCM},
    122 {bcmFieldOlpHeaderTypeEthOamLm, _BCM_TD2P_OLP_HDR_SUBTYPE_ETH_OAM_LM},
    123 {bcmFieldOlpHeaderTypeEthOamDm, _BCM_TD2P_OLP_HDR_SUBTYPE_ETH_OAM_DM},
    124 {bcmFieldOlpHeaderTypeEthOthers, _BCM_TD2P_OLP_HDR_SUBTYPE_ETH_OAM_OTHER_OC},
    125 
    126 /* BHH */
    127 {bcmFieldOlpHeaderTypeBhhOamCcm, _BCM_TD2P_OLP_HDR_SUBTYPE_BHH_CCM},
    128 {bcmFieldOlpHeaderTypeBhhOamLm, _BCM_TD2P_OLP_HDR_SUBTYPE_BHH_LM},
    129 {bcmFieldOlpHeaderTypeBhhOamDm, _BCM_TD2P_OLP_HDR_SUBTYPE_BHH_DM},
    130 {bcmFieldOlpHeaderTypeBhhOamOthers, _BCM_TD2P_OLP_HDR_SUBTYPE_BHH_OTHER_OC},
    131 
    132 /* MPLS LM/DM */
    133 {bcmFieldOlpHeaderTypeRfc6374Dlm, _BCM_TD2P_OLP_HDR_SUBTYPE_MPLS_LMDM_DLM},
    134 {bcmFieldOlpHeaderTypeRfc6374Dm, _BCM_TD2P_OLP_HDR_SUBTYPE_MPLS_LMDM_DM},
    135 {bcmFieldOlpHeaderTypeRfc6374DlmPlusDm, _BCM_TD2P_OLP_HDR_SUBTYPE_MPLS_LMDM_DLM_DM},
    136 {bcmFieldOlpHeaderTypeRfc6374Ilm, _BCM_TD2P_OLP_HDR_SUBTYPE_MPLS_LMDM_ILM},
    137 {bcmFieldOlpHeaderTypeRfc6374IlmPlusDm, _BCM_TD2P_OLP_HDR_SUBTYPE_MPLS_LMDM_ILM_DM},
    138 
    139 /* Down SAT */
    140 {bcmFieldOlpHeaderTypeSat, _BCM_TD2P_OLP_HDR_SUBTYPE_SAT},
    141 
    142 /* Other ACH */
    143 {bcmFieldOlpHeaderTypeOtherAch, _BCM_TD2P_OLP_HDR_SUBTYPE_OTH_ACH},
    144 
    145 /* ETH-OAM Up MEP */
    146 {bcmFieldOlpHeaderTypeEthOamUpMepCcm, _BCM_TD2P_OLP_HDR_SUBTYPE_ETH_OAM_CCM_UP},
    147 {bcmFieldOlpHeaderTypeEthOamUpMepLm, _BCM_TD2P_OLP_HDR_SUBTYPE_ETH_OAM_LM_UP},
    148 {bcmFieldOlpHeaderTypeEthOamUpMepDm, _BCM_TD2P_OLP_HDR_SUBTYPE_ETH_OAM_DM_UP},
    149 {bcmFieldOlpHeaderTypeEthOamUpMepOthers, _BCM_TD2P_OLP_HDR_SUBTYPE_ETH_OAM_OTHER_OC_UP},
    150 
    151 /* Up SAT*/
    152 {bcmFieldOlpHeaderTypeUpSat, _BCM_TD2P_OLP_HDR_SUBTYPE_SAT_UP},
    153 
    154 /* Macsec */
    155 {bcmFieldOlpHeaderTypeMacSecEncrypt, _BCM_TD2P_OLP_HDR_SUBTYPE_MACSEC_ENCRYPT},
    156 {bcmFieldOlpHeaderTypeMacSecDecrypt, _BCM_TD2P_OLP_HDR_SUBTYPE_MACSEC_DECRYPT},
    157 
    158 };
    159 
    160 static uint8 td2p_olp_hdr_type_count = sizeof(td2p_olp_hdr_type_mapping) /
    161                                            sizeof(td2p_olp_hdr_type_mapping[0]);
    162 int _bcm_fp_oam_trunk_ports_update_trunk_id(int unit, bcm_trunk_t trunk_id);
    163 
    164 #if defined(INCLUDE_BHH)
    165 static int fp_oam_mpls_tp_ach_channel_type = SHR_BHH_ACH_CHANNEL_TYPE;
    166 #endif /* INCLUDE_BHH */
    167 
    168 /*
    169  * Function:
    170  *    _bcm_td2p_oam_olp_header_type_mapping_set
    171  * Purpose:
    172  *     Miscellaneous OAM configurations:
    173  *         1. Enable IFP lookup on the CPU port.
    174  * Parameters:
    175  *     unit -  (IN) BCM unit number.
    176  * Retruns:
    177  *     BCM_E_XXX
    178  */
    179 STATIC int
    180 _bcm_td2p_oam_olp_header_type_mapping_set(int unit)
    181 {
    182     int                                 index           = 0;
    183     int                                 mem_index_count = 0;
    184     egr_olp_header_type_mapping_entry_t entry;
    185 
    186     mem_index_count = soc_mem_index_count(unit, EGR_OLP_HEADER_TYPE_MAPPINGm);
    187 
    188     if (td2p_olp_hdr_type_count > mem_index_count) {
    189         return BCM_E_RESOURCE;
    190     }
    191 
    192     for (index = 0; index < td2p_olp_hdr_type_count; index++) {
    193         soc_EGR_OLP_HEADER_TYPE_MAPPINGm_field32_set(unit,
    194                                                      &entry,
    195                                                      HDR_TYPEf,
    196                                                      _BCM_TD2P_OLP_HDR_TYPE_RX);
    197 
    198 #if defined(BCM_MONTEREY_SUPPORT)
    199         if (soc_feature(unit, soc_feature_xflow_macsec)) {
    200             if (td2p_olp_hdr_type_mapping[index].field_olp_hdr_type
    201                                 == bcmFieldOlpHeaderTypeMacSecEncrypt) {
    202                 soc_EGR_OLP_HEADER_TYPE_MAPPINGm_field32_set(unit,
    203                                                             &entry,
    204                                                             HDR_TYPEf,
    205                                                             _BCM_TD2P_OLP_HDR_TYPE_MACSEC_ENCRYPT);
    206             } else if (td2p_olp_hdr_type_mapping[index].field_olp_hdr_type
    207                                 == bcmFieldOlpHeaderTypeMacSecDecrypt) {
    208                 soc_EGR_OLP_HEADER_TYPE_MAPPINGm_field32_set(unit,
    209                                                             &entry,
    210                                                             HDR_TYPEf,
    211                                                             _BCM_TD2P_OLP_HDR_TYPE_MACSEC_DECRYPT);
    212             }
    213         }
    214 #endif
    215         soc_EGR_OLP_HEADER_TYPE_MAPPINGm_field32_set(
    216                                             unit,
    217                                             &entry,
    218                                             HDR_SUBTYPEf,
    219                                             td2p_olp_hdr_type_mapping[index].subtype);
    220 
    221         SOC_IF_ERROR_RETURN(
    222                      WRITE_EGR_OLP_HEADER_TYPE_MAPPINGm(unit,  MEM_BLOCK_ALL,
    223                                                         index, &entry));
    224 #if defined (BCM_APACHE_SUPPORT) || defined(BCM_MONTEREY_SUPPORT)
    225         if (soc_feature(unit, soc_feature_ep_redirect_v2) ||
    226             soc_feature(unit, soc_feature_xflow_macsec)) {
    227             SOC_IF_ERROR_RETURN(
    228                        WRITE_EGR_OLP_HEADER_TYPE_MAPPING_1m(unit,  MEM_BLOCK_ALL,
    229                                                             index, &entry));
    230         }
    231 #endif
    232     }
    233     return BCM_E_NONE;
    234 }
    235 
    236 /*
    237  * Function:
    238  *     _bcm_td2p_oam_hg_olp_enable
    239  * Purpose:
    240  *    Enable OLP on HG ports by default
    241  * Parameters:
    242  *     unit - (IN) BCM device number
    243  * Retruns:
    244  *     BCM_E_XXX
    245  */
    246 STATIC int
    247 _bcm_td2p_oam_hg_olp_enable(int unit)
    248 {
    249     bcm_pbmp_t                     ports;
    250     bcm_port_t                     port;
    251     iarb_ing_port_table_entry_t    entry;
    252 
    253     BCM_PBMP_ASSIGN(ports, PBMP_PORT_ALL(unit));
    254 
    255     PBMP_ITER(ports, port) {
    256         if (IS_HG_PORT(unit, port)) {
    257             SOC_IF_ERROR_RETURN(soc_mem_read(unit, IARB_ING_PORT_TABLEm,
    258                                              MEM_BLOCK_ANY, port, &entry));
    259 
    260             soc_IARB_ING_PORT_TABLEm_field32_set(unit, &entry, OLP_ENABLEf, 1);
    261 
    262             SOC_IF_ERROR_RETURN(soc_mem_write(unit, IARB_ING_PORT_TABLEm,
    263                                               MEM_BLOCK_ALL, port, &entry));
    264         }
    265     }
    266     return (BCM_E_NONE);
    267 }
    268 
    269 /*
    270  * Function:
    271  *     _bcm_td2p_oam_olp_magic_port_set
    272  * Purpose:
    273  *     Set Magic port used for remote OLP over HG communication
    274  * Parameters:
    275  *     unit - (IN) BCM device number
    276  * Returns:
    277  *     BCM_E_XXX
    278  */
    279 int
    280 _bcm_td2p_oam_olp_magic_port_set(int unit)
    281 {
    282     int    modid;
    283 
    284     /* Configure modid and the magic port */
    285     BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid));
    286 
    287     SOC_IF_ERROR_RETURN(
    288           soc_reg_field32_modify(unit, IARB_OLP_CONFIG_1r,
    289                                  REG_PORT_ANY, MY_MODIDf, modid));
    290 
    291     SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit,
    292                                                IARB_OLP_CONFIG_1r,
    293                                                REG_PORT_ANY,
    294                                                MY_PORT_NUMf,
    295                                                _BCM_OAM_TD2P_OLP_MAGIC_PORT));
    296 
    297     return (BCM_E_NONE);
    298 }
    299 
    300 #if defined (BCM_APACHE_SUPPORT)
    301 /*
    302  * Function:
    303  *      _bcm_apache_oam_drop_control_fp_encode
    304  * Purpose:
    305  *      Convert a Drop Control mep_type to FP
    306  *      data and mask
    307  * Parameters:
    308  *      mep_type - (IN)  Mep type
    309  *      data     - (OUT) Data for FP qualifier
    310  *      mask     - (OUT) Mask for FP qualifier
    311  * Returns:
    312  *      BCM_E_XXX
    313  * Notes:
    314  */
    315 int
    316 _bcm_apache_oam_drop_control_fp_encode(bcm_field_oam_drop_mep_type_t mep_type,
    317                                        uint8 *data,
    318                                        uint8 *mask)
    319 {
    320 
    321     int data_pkt = FALSE;
    322     int drop_vector_mask_index;
    323 
    324     switch (mep_type) {
    325         case bcmFieldOamDropPortDownMepData:
    326         case bcmFieldOamDropPortDownMepControl:
    327             drop_vector_mask_index = 0;
    328             break;
    329 
    330         case bcmFieldOamDropInnerVlanDownMepData:
    331         case bcmFieldOamDropInnerVlanDownMepControl:
    332             drop_vector_mask_index = 1;
    333             break;
    334 
    335         case bcmFieldOamDropOuterVlanDownMepData:
    336         case bcmFieldOamDropOuterVlanDownMepControl:
    337         case bcmFieldOamDropInnerPlusOuterVlanDownMepData:
    338         case bcmFieldOamDropInnerPlusOuterVlanDownMepControl:
    339             drop_vector_mask_index = 2;
    340             break;
    341 
    342         case bcmFieldOamDropInnerVlanUpMepData:
    343             drop_vector_mask_index = 3;
    344             break;
    345 
    346         case bcmFieldOamDropOuterVlanUpMepData:
    347         case bcmFieldOamDropInnerPlusOuterVlanUpMepData:
    348             drop_vector_mask_index = 4;
    349             break;
    350 
    351         case bcmFieldOamDropSectionPortMepData:
    352         case bcmFieldOamDropSectionInnerVlanMepData:
    353         case bcmFieldOamDropSectionOuterVlanMepData:
    354         case bcmFieldOamDropSectionInnerPlusOuterVlanMepData:
    355             drop_vector_mask_index = 5;
    356             break;
    357 
    358         case bcmFieldOamDropLSPMepData:
    359         case bcmFieldOamDropPwMepData:
    360             drop_vector_mask_index = 6;
    361             break;
    362 
    363         case bcmFieldOamDropSectionPortMepControl:
    364         case bcmFieldOamDropSectionInnerVlanMepControl:
    365         case bcmFieldOamDropSectionOuterVlanMepControl:
    366         case bcmFieldOamDropSectionInnerPlusOuterVlanMepControl:
    367         case bcmFieldOamDropLSPMepControl:
    368         case bcmFieldOamDropPwMepControl:
    369             drop_vector_mask_index = 7;
    370             break;
    371 
    372         default:
    373             return BCM_E_PARAM;
    374     }
    375 
    376     switch (mep_type) {
    377         case bcmFieldOamDropPortDownMepData:
    378         case bcmFieldOamDropInnerVlanDownMepData:
    379         case bcmFieldOamDropOuterVlanDownMepData:
    380         case bcmFieldOamDropInnerPlusOuterVlanDownMepData:
    381         case bcmFieldOamDropInnerVlanUpMepData:
    382         case bcmFieldOamDropOuterVlanUpMepData:
    383         case bcmFieldOamDropInnerPlusOuterVlanUpMepData:
    384         case bcmFieldOamDropSectionPortMepData:
    385         case bcmFieldOamDropSectionInnerVlanMepData:
    386         case bcmFieldOamDropSectionOuterVlanMepData:
    387         case bcmFieldOamDropSectionInnerPlusOuterVlanMepData:
    388         case bcmFieldOamDropLSPMepData:
    389         case bcmFieldOamDropPwMepData:
    390             data_pkt = TRUE;
    391             break;
    392 
    393         default:
    394             data_pkt = FALSE;
    395             break;
    396     }
    397 
    398     if (TRUE == data_pkt) {
    399         *data = 1 << drop_vector_mask_index;
    400     } else {
    401         *data = 0;
    402     }
    403 
    404     *mask = 1 << drop_vector_mask_index;
    405 
    406     return BCM_E_NONE;
    407 }
    408 
    409 /*
    410  * Function:
    411  *   _bcm_apache_drop_vector_mask_default_set
    412  * Purpose:
    413  *     Program the DROP_VECTOR_MASKS_x with the drop reasons
    414  *     per MEP.
    415  * Parameters:
    416  *     unit -  (IN) BCM unit number.
    417  * Returns:
    418  *     BCM_E_XXX
    419  */
    420 STATIC int
    421 _bcm_apache_drop_vector_mask_default_set (int unit)
    422 {
    423     int index;
    424     drop_vector_mask_entry_t drop_vector_mask_entry;
    425     int entry_count;
    426     uint32 entry[][3] = {
    427                             {0x00003200, 0x00000000, 0x00B013F0},
    428                             {0x0000B200, 0x00000800, 0x00B013F0},
    429                             {0x0000B200, 0x00008800, 0x00F013F0},
    430                             {0x0000B201, 0x00000800, 0x0CB013F0},
    431                             {0x0000B201, 0x0000E800, 0x0CF013F0},
    432                             {0x0000F201, 0x0000E800, 0x00F017F2},
    433                             {0x0000F201, 0x0030E800, 0x03F017F2},
    434                             {0x0000F201, 0x0000E800, 0x00F017F2},
    435                         };
    436 
    437     entry_count = soc_mem_index_count(unit, DROP_VECTOR_MASKm);
    438 
    439     for (index = 0; index < entry_count; index++) {
    440         soc_DROP_VECTOR_MASKm_field_set(unit,
    441                                         &drop_vector_mask_entry,
    442                                         MASKf,
    443                                         entry[index]);
    444         SOC_IF_ERROR_RETURN(
    445                        WRITE_DROP_VECTOR_MASKm(unit,
    446                                                MEM_BLOCK_ALL,
    447                                                index,
    448                                                &drop_vector_mask_entry));
    449     }
    450     return BCM_E_NONE;
    451 }
    452 
    453 STATIC int
    454 _bcm_apache_oam_default_hw_config_set(int unit)
    455 {
    456     egr_multicast_mac_addr_entry_t egr_multicast_mac_cfg;
    457     bcm_mac_t                      mac_addr;
    458     uint64                         mac_addr_64;
    459 
    460     /* Program EGR_MULTICAST_MAC_ADDR with OAM mulicast addresses */
    461     sal_memset(&egr_multicast_mac_cfg, 0, sizeof(egr_multicast_mac_cfg));
    462 
    463     /* Set ADDR1 to class1 address: 01:80:C2:00:00:30 */
    464     mac_addr[0] = 0x01;
    465     mac_addr[1] = 0x80;
    466     mac_addr[2] = 0xC2;
    467     mac_addr[3] = 0x00;
    468     mac_addr[4] = 0x00;
    469     mac_addr[5] = 0x30;
    470     soc_EGR_MULTICAST_MAC_ADDRm_mac_addr_set(unit,
    471                                              &egr_multicast_mac_cfg,
    472                                              ADDR1f,
    473                                              mac_addr);
    474 
    475     /* Set ADDR_2 & ADDR3 to class2 address: 01:80:C2:00:00:38 */
    476     mac_addr[0] = 0x01;
    477     mac_addr[1] = 0x80;
    478     mac_addr[2] = 0xC2;
    479     mac_addr[3] = 0x00;
    480     mac_addr[4] = 0x00;
    481     mac_addr[5] = 0x38;
    482     soc_EGR_MULTICAST_MAC_ADDRm_mac_addr_set(unit,
    483                                              &egr_multicast_mac_cfg,
    484                                              ADDR2f,
    485                                              mac_addr);
    486     soc_EGR_MULTICAST_MAC_ADDRm_mac_addr_set(unit,
    487                                              &egr_multicast_mac_cfg,
    488                                              ADDR3f,
    489                                              mac_addr);
    490 
    491     SOC_IF_ERROR_RETURN(
    492                         WRITE_EGR_MULTICAST_MAC_ADDRm(unit,
    493                                                       MEM_BLOCK_ALL,
    494                                                       0,
    495                                                       &egr_multicast_mac_cfg));
    496 
    497     /* Set EGR_MULTICAST_MAC_ADDR_MASK to FF:FF:FF:FF:FF:F8 */
    498     COMPILER_64_SET(mac_addr_64, 0xFFFF, 0xFFFFFFF8);
    499     SOC_IF_ERROR_RETURN(
    500                         WRITE_EGR_MULTICAST_MAC_ADDR_MASKr(unit, mac_addr_64));
    501 
    502 
    503     /* Set EGR_LBR_OPCODE to 0x2 */
    504     SOC_IF_ERROR_RETURN(WRITE_EGR_LBR_OPCODEr(unit, 0x2));
    505 
    506     /* Set default for DROP_VECTOR_MASK[1..8] */
    507     BCM_IF_ERROR_RETURN(_bcm_apache_drop_vector_mask_default_set(unit));
    508 
    509     return BCM_E_NONE;
    510 }
    511 #endif /* BCM_APACHE_SUPPORT */
    512 
    513 
    514 /*
    515  * Function: _bcm_td2p_oam_olp_fp_hw_index_get
    516  *
    517  * Purpose:
    518  *     Get OLP_HDR_TYPE_COMPRESSED corresponding to subtype
    519  * Parameters:
    520  *     unit - (IN) BCM device number
    521  * Returns:
    522  *     BCM_E_XXX
    523  */
    524 int
    525 _bcm_td2p_oam_olp_fp_hw_index_get(int unit,
    526                                   bcm_field_olp_header_type_t olp_hdr_type,
    527                                   int *hwindex)
    528 {
    529     int index;
    530 
    531     for (index = 0; index < td2p_olp_hdr_type_count; index++) {
    532         if (td2p_olp_hdr_type_mapping[index].field_olp_hdr_type == olp_hdr_type) {
    533             *hwindex = index;
    534             return BCM_E_NONE;
    535         }
    536     }
    537 
    538     return BCM_E_NOT_FOUND;
    539 }
    540 
    541 /*
    542  * Function: _bcm_td2p_oam_olp_hw_index_olp_type_get
    543  *
    544  * Purpose:
    545  *     Get subtype corresponding to OLP_HDR_TYPE_COMPRESSED
    546  * Parameters:
    547  *     unit - (IN) BCM device number
    548  * Returns:
    549  *     BCM_E_XXX
    550  */
    551 int
    552 _bcm_td2p_oam_olp_hw_index_olp_type_get(int unit,
    553                                         int hwindex,
    554                                         bcm_field_olp_header_type_t *olp_hdr_type)
    555 {
    556     if (hwindex >= td2p_olp_hdr_type_count) {
    557         return BCM_E_PARAM;
    558     }
    559 
    560     *olp_hdr_type = td2p_olp_hdr_type_mapping[hwindex].field_olp_hdr_type;
    561 
    562     return BCM_E_NONE;
    563 }
    564 /*******************************************************************************/
    565 /* OAM Hardware configuration for TD2+ & Apache end                            */
    566 /*******************************************************************************/
    567 /*******************************************************************************/
    568 /* PM MACROs for BHH & MPLS LM/DM App start                                    */
    569 /*******************************************************************************/
    570 #if defined (INCLUDE_BHH) || defined(INCLUDE_MPLS_LM_DM)
    571 typedef struct _bcm_fp_oam_pm_profile_int_info_s {
    572     int id_status;
    573     bcm_oam_pm_profile_info_t pm_profile;
    574 }_bcm_fp_oam_pm_profile_int_info_t;
    575 typedef struct _bcm_fp_oam_pm_profile_control_s {
    576     _bcm_fp_oam_pm_profile_int_info_t profile_info[_BCM_OAM_MAX_PM_PROFILES];
    577 }_bcm_fp_oam_pm_profile_control_t;
    578 
    579 _bcm_fp_oam_pm_profile_control_t *pm_profile_control[SOC_MAX_NUM_DEVICES];
    580 
    581 #define _BCM_FP_OAM_PM_CTRL_PROFILE_IN_USE(pmc, id)          \
    582                               (pmc->profile_info[id].id_status == 1)
    583 #define _BCM_FP_OAM_PM_CTRL_PROFILE_PTR(pmc, id)             \
    584                               (&(pmc->profile_info[id].pm_profile))
    585 #define _BCM_FP_OAM_SET_PM_CTRL_PROFILE_IN_USE(pmc, id)      \
    586                               (pmc->profile_info[id].id_status = 1)
    587 #define _BCM_FP_OAM_SET_PM_CTRL_PROFILE_NOT_IN_USE(pmc, id)  \
    588                               (pmc->profile_info[id].id_status = 0)
    589 
    590 #define _BCM_FP_OAM_PM_PROFILE_REPLACE_FLAG_SET(profile) (profile->flags & \
    591                                                      BCM_OAM_PM_PROFILE_REPLACE)
    592 
    593 #define _BCM_FP_OAM_PM_PROFILE_WITH_ID_FLAG_SET(profile) (profile->flags & \
    594                                                      BCM_OAM_PM_PROFILE_WITH_ID)
    595 
    596 #define _BCM_FP_OAM_PM_PROFILE_ID_VALID(profile_id) \
    597     ((profile_id >= 0) && (profile_id < _BCM_OAM_MAX_PM_PROFILES))
    598 
    599 /* PM raw data events handling macros */
    600 #define _BCM_FP_OAM_EVENT_TYPE_PM_EVENT(event_types) \
    601                     ((SHR_BITGET(event_types.w, bcmOAMEventBHHRawData)) ||              \
    602                      (SHR_BITGET(event_types.w, bcmOAMEventMplsLmDmRawData)))
    603 
    604 #if defined (INCLUDE_BHH)
    605 #define _BCM_FP_OAM_PM_BHH_DATA_COLLECTION_MODE_ENABLED(oc) \
    606                             (oc->pm_bhh_lmdm_data_collection_mode != \
    607                                 _BCM_OAM_PM_COLLECTION_MODE_NONE)
    608 #define _BCM_FP_OAM_PM_BHH_DATA_COLLECTION_MODE_IS_RAW_DATA(oc) \
    609                             (oc->pm_bhh_lmdm_data_collection_mode == \
    610                                 _BCM_OAM_PM_COLLECTION_MODE_RAW_DATA)
    611 #define _BCM_FP_OAM_PM_BHH_DATA_COLLECTION_MODE_IS_PROCESSED(oc) \
    612                             (oc->pm_bhh_lmdm_data_collection_mode == \
    613                                 _BCM_OAM_PM_COLLECTION_MODE_PROCESSED_STATS)
    614 #else
    615 #define _BCM_FP_OAM_PM_BHH_DATA_COLLECTION_MODE_ENABLED(oc) 0
    616 #define _BCM_FP_OAM_PM_BHH_DATA_COLLECTION_MODE_IS_RAW_DATA(oc) 0
    617 #define _BCM_FP_OAM_PM_BHH_DATA_COLLECTION_MODE_IS_PROCESSED(oc) 0
    618 #endif /* INCLUDE_BHH */
    619 
    620 #if defined (INCLUDE_MPLS_LM_DM)
    621 #define _BCM_FP_OAM_PM_MPLS_LM_DM_DATA_COLLECTION_MODE_ENABLED(oc) \
    622                             (oc->pm_mpls_lm_dm_data_collection_mode != \
    623                                 _BCM_OAM_PM_COLLECTION_MODE_NONE)
    624 #define _BCM_FP_OAM_PM_MPLS_LM_DM_DATA_COLLECTION_MODE_IS_RAW_DATA(oc)\
    625                             (oc->pm_mpls_lm_dm_data_collection_mode ==\
    626                                 _BCM_OAM_PM_COLLECTION_MODE_RAW_DATA)
    627 #define _BCM_FP_OAM_PM_MPLS_LM_DM_DATA_COLLECTION_MODE_IS_PROCESSED(oc) \
    628                             (oc->pm_mpls_lm_dm_data_collection_mode ==\
    629                                 _BCM_OAM_PM_COLLECTION_MODE_PROCESSED_STATS)
    630 #else
    631 #define _BCM_FP_OAM_PM_MPLS_LM_DM_DATA_COLLECTION_MODE_ENABLED(oc)      0
    632 #define _BCM_FP_OAM_PM_MPLS_LM_DM_DATA_COLLECTION_MODE_IS_RAW_DATA(oc)  0
    633 #define _BCM_FP_OAM_PM_MPLS_LM_DM_DATA_COLLECTION_MODE_IS_PROCESSED(oc) 0
    634 #endif /* INCLUDE_MPLS_LM_DM */
    635 
    636 #define _BCM_FP_OAM_PM_BHH_EVENT_IDX         0
    637 #define _BCM_FP_OAM_PM_MPLS_LM_DM_EVENT_IDX  1
    638 
    639 #define _BCM_FP_OAM_BHH_OAM_PM_EVENT_TYPE(event_type) \
    640                                  (event_type == bcmOAMEventBHHRawData)
    641 
    642 #define PM_READ_DONE_INDEX(event_idx) \
    643                     (oc->pm_read_done_index[event_idx])
    644 #define PM_WRITE_DONE_INDEX(event_idx) \
    645                     (oc->pm_write_done_index[event_idx])
    646 #define INCREMENT_PM_WRITE_DONE_INDEX(event_idx) \
    647                (((oc->pm_write_done_index[event_idx])+1)%BCM_OAM_MAX_PM_BUFFERS)
    648 #define NUM_FREE_BUFFERS(event_idx)\
    649                     (oc->pm_num_free_raw_data_buffers[event_idx])
    650 #define SET_NUM_FREE_BUFFERS(event_idx, value)\
    651                     (oc->pm_num_free_raw_data_buffers[event_idx] = value)
    652 #define DECR_NUM_FREE_BUFFERS(event_idx) \
    653     SET_NUM_FREE_BUFFERS(event_idx, (NUM_FREE_BUFFERS(event_idx) - 1))
    654 #define INCR_NUM_FREE_BUFFERS(event_idx) \
    655     SET_NUM_FREE_BUFFERS(event_idx, (NUM_FREE_BUFFERS(event_idx) + 1))
    656 
    657 
    658 
    659 #define VALID_PM_RAW_DATA_BUFFER_READ_WRITE_INDEX(index) \
    660         (index < BCM_OAM_MAX_PM_BUFFERS)
    661 
    662 int bcm_fp_oam_pm_profile_detach(int unit, bcm_oam_endpoint_t endpoint_id,
    663                                  bcm_oam_pm_profile_t profile_id);
    664 
    665 #ifdef BCM_WARM_BOOT_SUPPORT
    666 /* Macro for PM profile information size */
    667 #define _BCM_FP_OAM_PM_PROFILE_SCACHE_SIZE \
    668         (sizeof(_bcm_fp_oam_pm_profile_int_info_t) * (_BCM_OAM_MAX_PM_PROFILES))
    669 #endif /* BCM_WARM_BOOT_SUPPORT */
    670 
    671 #endif /* INCLUDE_BHH || INCLUDE_MPLS_LM_DM */
    672 /*******************************************************************************/
    673 /* PM MACROs for BHH & MPLS LM/DM App end                                      */
    674 /*******************************************************************************/
    675 
    676 #if defined(INCLUDE_BHH)
    677 /*
    678  * Macro:
    679  *     BCM_WB_XXX
    680  * Purpose:
    681  *    OAM module scache version information.
    682  * Parameters:
    683  *    (major number, minor number)
    684  */
    685 #ifdef BCM_WARM_BOOT_SUPPORT
    686 #define BCM_BHH_WB_VERSION_1_0          SOC_SCACHE_VERSION(1,0)
    687 #define BCM_BHH_WB_VERSION_1_1          SOC_SCACHE_VERSION(1,1)
    688 #define BCM_BHH_WB_VERSION_1_2          SOC_SCACHE_VERSION(1,2)
    689 #define BCM_BHH_WB_VERSION_1_3          SOC_SCACHE_VERSION(1,3)
    690 #define BCM_WB_BHH_DEFAULT_VERSION      BCM_BHH_WB_VERSION_1_3
    691 
    692 #endif
    693 
    694 #define BHH_COSQ_INVALID          0xFFFF
    695 
    696 #define _BCM_FP_OAM_INVALID_NUM_SESSION_ENTRIES 0
    697 #define _BCM_OAM_EP_LEVEL_COUNT (1 << (_BCM_OAM_EP_LEVEL_BIT_COUNT))
    698 #define _BCM_OAM_EP_LEVEL_MAX (_BCM_OAM_EP_LEVEL_COUNT - 1)
    699 
    700 /*
    701  *  * Macro:
    702  *     _BCM_OAM_BHH_IS_VALID (internal)
    703  * Purpose:
    704  *     Check that the BHH feature is available on this unit
    705  * Parameters:
    706  *     unit - BCM device number
    707  * Notes:
    708  *     Results in return(BCM_E_UNAVAIL),
    709  */
    710 #define _BCM_OAM_BHH_IS_VALID(unit)                                          \
    711             do {                                                             \
    712                 if (!soc_feature(unit, soc_feature_bhh)) {                   \
    713                     return (BCM_E_UNAVAIL);                                  \
    714                 }                                                            \
    715             } while (0)
    716 
    717 #define BCM_OAM_BHH_GET_UKERNEL_GROUP(group) \
    718         (group - oc->bhh_base_group_id)
    719 #define BCM_OAM_BHH_GET_SDK_GROUP(group) \
    720         (group + oc->bhh_base_group_id)
    721 
    722 #define BCM_OAM_BHH_GET_SDK_EP(ep) \
    723         (ep + oc->bhh_base_endpoint_id)
    724 #define BCM_OAM_BHH_GET_UKERNEL_EP(ep) \
    725         (ep - oc->bhh_base_endpoint_id)
    726 
    727 #define BCM_OAM_BHH_VALIDATE_EP(_ep_) \
    728             do {                                                       \
    729                 if (((_ep_) < oc->bhh_base_endpoint_id) ||         \
    730                     ((_ep_) >= (oc->bhh_base_endpoint_id           \
    731                                          + oc->bhh_endpoint_count))) { \
    732                     LOG_ERROR(BSL_LS_BCM_OAM, \
    733                               (BSL_META_U(unit, \
    734                                           "OAM(unit %d) Error: Invalid Endpoint ID" \
    735                                           " = %d.\n"), unit, _ep_));   \
    736                     _BCM_OAM_UNLOCK(oc);                               \
    737                     return (BCM_E_PARAM);                              \
    738                 }                                                      \
    739             } while (0);
    740 
    741 #define BHH_TYPE(type) ( (type == bcmOAMEndpointTypeBHHMPLS) ||        \
    742                 (type == bcmOAMEndpointTypeBHHMPLSVccv)||\
    743                 (type == bcmOAMEndpointTypeBhhSection)||\
    744                 (type == bcmOAMEndpointTypeBhhSectionInnervlan)||\
    745                 (type == bcmOAMEndpointTypeBhhSectionOuterVlan)||\
    746                 (type == bcmOAMEndpointTypeBhhSectionOuterPlusInnerVlan)\
    747                          ) 
    748 
    749 #define BHH_EP_TYPE(ep) (BHH_TYPE(ep->type)) 
    750 
    751 #define BHH_EP_MPLS_SECTION_TYPE(ep) (\
    752                 (ep->type == bcmOAMEndpointTypeBhhSection)||\
    753                 (ep->type == bcmOAMEndpointTypeBhhSectionInnervlan)||\
    754                 (ep->type == bcmOAMEndpointTypeBhhSectionOuterVlan)||\
    755                 (ep->type == bcmOAMEndpointTypeBhhSectionOuterPlusInnerVlan)\
    756                                      )
    757 
    758 #define BHH_EP_LSP_TYPE(ep) (ep->type == bcmOAMEndpointTypeBHHMPLS)
    759 
    760 /*
    761  * Macro:
    762  *     _BCM_FP_OAM_BHH_GROUP_INDEX_VALIDATE
    763  * Purpose:
    764  *     Validate BHH Group ID value.
    765  * Parameters:
    766  *     _group_ - Group ID value.
    767  */
    768 #define _BCM_FP_OAM_BHH_GROUP_INDEX_VALIDATE(_group_)               \
    769     do {                                                            \
    770         if (((_group_) < oc->bhh_base_group_id) ||               \
    771             ((_group_) >= (oc->bhh_base_group_id +               \
    772                            oc->bhh_endpoint_count))) {              \
    773             LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META("OAM Error: "       \
    774               "Invalid Group ID = %d.\n"), _group_));               \
    775             return (BCM_E_PARAM);                                   \
    776         }                                                           \
    777     } while (0);
    778 
    779 
    780 
    781 /*
    782  * Macro:
    783  *     _BHH_FP_OAM_HASH_DATA_CLEAR
    784  * Purpose:
    785  *      Clear hash data memory occupied by one endpoint.
    786  * Parameters:
    787  *     _ptr_    - Pointer to endpoint hash data memory. 
    788  */
    789 #define _BHH_FP_OAM_HASH_DATA_CLEAR(_ptr_) \
    790             sal_memset(_ptr_, 0, sizeof(_bhh_fp_oam_ep_data_t));
    791 
    792 STATIC void
    793 _bcm_fp_oam_bhh_callback_thread(void *param);
    794 STATIC int
    795 _bcm_fp_oam_bhh_event_mask_set(int unit);
    796 STATIC int
    797 _bcm_fp_oam_bhh_endpoint_create(int unit,
    798                                 bcm_oam_endpoint_info_t *endpoint_info);
    799 
    800 #endif /* INCLUDE_BHH */
    801 
    802 /*******************************************************************************/
    803 /* MPLS LM/DM specific MACROs                                                  */
    804 /*******************************************************************************/
    805 #if defined(INCLUDE_MPLS_LM_DM)
    806 #define MPLS_LM_DM_MAX_RAW_DATA_SESSIONS 128 /* Max sessions when PM is operating
    807                                               * in Raw data mode
    808                                               */
    809 #define MPLS_LM_DM_MAX_SESSIONS          256
    810 #define _MPLS_LM_DM_INVALID_SESS_ID      0xFFFFFFFF
    811 #define _MPLS_LM_DM_INVALID_EP_ID      0xFFFFFFFF
    812 
    813 #define _MPLS_LM_DM_MPLS_MAX_LABELS    9   /* Max MPLS labels in Apache */
    814 
    815 #define MPLS_LM_DM_RX_CHANNEL_UC_VIEW        1
    816 
    817 
    818 #define _MPLS_LM_DM_ENDPOINT_TYPE(_type_)                                \
    819     (((_type_) == bcmOAMEndpointTypeMplsLmDmSectionPort)              || \
    820      ((_type_) == bcmOAMEndpointTypeMplsLmDmSectionInnervlan)         || \
    821      ((_type_) == bcmOAMEndpointTypeMplsLmDmSectionOuterVlan)         || \
    822      ((_type_) == bcmOAMEndpointTypeMplsLmDmSectionOuterPlusInnerVlan)|| \
    823      ((_type_) == bcmOAMEndpointTypeMplsLmDmPw)                       || \
    824      ((_type_) == bcmOAMEndpointTypeMplsLmDmLsp))
    825 
    826 #define _MPLS_LM_DM_SECTION_ENDPOINT_TYPE(_type_)                        \
    827     (((_type_) == bcmOAMEndpointTypeMplsLmDmSectionPort)              || \
    828      ((_type_) == bcmOAMEndpointTypeMplsLmDmSectionInnervlan)         || \
    829      ((_type_) == bcmOAMEndpointTypeMplsLmDmSectionOuterVlan)         || \
    830      ((_type_) == bcmOAMEndpointTypeMplsLmDmSectionOuterPlusInnerVlan))
    831 
    832 
    833 #define _MPLS_LM_DM_EP_ID_RANGE(_id_) \
    834     (((_id_) >= oc->mpls_lm_dm_base_endpoint_id) &&  \
    835      ((_id_) < (oc->mpls_lm_dm_base_endpoint_id + oc->mpls_lm_dm_max_ep_count)))
    836 
    837 #define _MPLS_LM_DM_SESS_ID_RANGE(_id_) \
    838     ( ( (_id_) >= 0 ) && ( (_id_) < oc->mpls_lm_dm_max_ep_count) )
    839 
    840 #define _MPLS_LM_DM_EP_ID_TO_SESS_ID(_id_)                                     \
    841     _MPLS_LM_DM_EP_ID_RANGE(_id_) ? ((_id_) - oc->mpls_lm_dm_base_endpoint_id) \
    842                                   : _MPLS_LM_DM_INVALID_SESS_ID
    843 
    844 #define _MPLS_LM_DM_SESS_ID_TO_EP_ID(_id_)                                       \
    845     _MPLS_LM_DM_SESS_ID_RANGE(_id_) ? ((_id_) + oc->mpls_lm_dm_base_endpoint_id) \
    846                                     : _MPLS_LM_DM_INVALID_EP_ID
    847 
    848 #define _MPLS_LM_DM_HW_SESS_ID_GET(_pool_, _index_)  \
    849     ((((_pool_) << 12) & 0x7000) | ((_index_) & 0xfff))
    850 
    851 #define _MPLS_LM_DM_EP_ITER(_ep_, _idx_)                          \
    852     for((_idx_) = 0, (_ep_) = &(oc->mpls_lm_dm_ep_data[0]);       \
    853         (_idx_) < oc->mpls_lm_dm_max_ep_count;                    \
    854         (_idx_)++, (_ep_)++)
    855 
    856 #define _MPLS_LM_DM_OLP_REPL_OFFSET_DLM          24
    857 #define _MPLS_LM_DM_OLP_REPL_OFFSET_DM           12
    858 
    859 #if defined (BCM_WARM_BOOT_SUPPORT)
    860 typedef struct _bcm_fp_oam_mpls_lm_dm_scache_v0_global_data_s {
    861     uint8              uc_num;
    862     uint8              ukernel_ready;
    863     uint8              rx_channel;
    864     uint16             max_ep_count;
    865     bcm_oam_endpoint_t base_endpoint_id;
    866 } _bcm_fp_oam_mpls_lm_dm_scache_v0_global_data_t;
    867 
    868 typedef struct _bcm_fp_oam_mpls_lm_dm_scache_v0_ep_data_s {
    869     uint8                      in_use;
    870     uint8                      type;
    871     uint8                      vccv_type;
    872     uint8                      trunk_index;
    873     uint8                      session_num_entries;
    874     uint8                      lm_ctr_offset[BCM_OAM_LM_COUNTER_MAX];
    875     uint8                      lm_ctr_action[BCM_OAM_LM_COUNTER_MAX];
    876     uint8                      lm_ctr_size;
    877     uint8                      dm_ctr_offset[BCM_OAM_LM_COUNTER_MAX];
    878     uint8                      dm_ctr_size;
    879     uint8                      lm_exp;
    880     uint8                      dm_exp;
    881     uint8                      outer_pri;
    882     uint8                      inner_pri;
    883     uint8                      lm_int_pri;
    884     uint8                      dm_int_pri;
    885     uint8                      dst_mac[6];
    886     uint8                      src_mac[6];
    887     uint8                      pm_profile;
    888     uint16                     inner_vlan;
    889     uint16                     outer_vlan;
    890     uint16                     vpn;
    891     uint16                     outer_tpid;
    892     uint16                     inner_tpid;
    893     uint32                     flags;
    894     uint32                     lm_ctr_base_id[BCM_OAM_LM_COUNTER_MAX];
    895     uint32                     dm_ctr_base_id[BCM_OAM_LM_COUNTER_MAX];
    896     uint32                     session_id;
    897     uint32                     egress_label;
    898     bcm_gport_t                gport;
    899     bcm_if_t                   intf_id;
    900 } _bcm_fp_oam_mpls_lm_dm_scache_v0_ep_data_t;
    901 
    902 #define _MPLS_LM_DM_SCACHE_V0_SIZE                                   \
    903    ((sizeof(_bcm_fp_oam_mpls_lm_dm_scache_v0_global_data_t)        +   \
    904     (sizeof(_bcm_fp_oam_mpls_lm_dm_scache_v0_ep_data_t) *            \
    905                                      oc->mpls_lm_dm_max_ep_count)) + \
    906     _BCM_FP_OAM_PM_PROFILE_SCACHE_SIZE)
    907 
    908 
    909 #define BCM_WB_MPLS_LM_DM_VERSION_1_0      SOC_SCACHE_VERSION(1,0)
    910 #define BCM_WB_MPLS_LM_DM_DEFAULT_VERSION  BCM_WB_MPLS_LM_DM_VERSION_1_0
    911 
    912 #endif /* BCM_WARM_BOOT_SUPPORT */
    913 
    914 STATIC int _bcm_fp_oam_mpls_lm_dm_loss_delete(int unit, bcm_oam_endpoint_t id);
    915 STATIC int _bcm_fp_oam_mpls_lm_dm_delay_delete(int unit, bcm_oam_endpoint_t id);
    916 STATIC int _bcm_fp_mpls_lm_dm_event_mask_set(int unit);
    917 
    918 #endif /* INCLUDE_MPLS_LM_DM */
    919 
    920 #if defined(INCLUDE_CCM) || defined(INCLUDE_BHH) || defined(INCLUDE_MPLS_LM_DM)
    921 /*******************************************************************************/
    922 /* Common supporting functions used by CCM and BHH Embedded Apps Start */
    923 /*******************************************************************************/
    924 
    925 /* External functions definition */
    926 extern void _bcm_esw_stat_get_counter_id_info(
    927                                          int                   unit,
    928                                          uint32                stat_counter_id,
    929                                          bcm_stat_group_mode_t *group,
    930                                          bcm_stat_object_t     *object,
    931                                          uint32                *mode,
    932                                          uint32                *pool_number,
    933                                          uint32                *base_idx);
    934 
    935 extern int
    936 _bcm_olp_l2_hdr_get(int unit, int glp, uint8 nbo, soc_olp_l2_hdr_t *l2hdr);
    937 extern int soc_uc_in_reset(int unit, int uC);
    938 extern int soc_uc_status(int unit, int uC, int *status);
    939 
    940 #define BCM_OAM_ABS(x)   (((x) < 0) ? (-(x)) : (x))
    941 /*
    942  *Macro:
    943  *     _BCM_OAM_LOCK
    944  * Purpose:
    945  *     Lock take the OAM control mutex
    946  * Parameters:
    947  *     control - Pointer to OAM control structure.
    948  */
    949 #define _BCM_OAM_LOCK(control) \
    950     sal_mutex_take((control)->oc_lock, sal_mutex_FOREVER)
    951 
    952 
    953 /*
    954  * Macro:
    955  *     _BCM_OAM_UNLOCK
    956  * Purpose:
    957  *     Lock take the OAM control mutex
    958  * Parameters:
    959  *     control - Pointer to OAM control structure.
    960  */
    961 #define _BCM_OAM_UNLOCK(control) \
    962     sal_mutex_give((control)->oc_lock);
    963 
    964 
    965 /*
    966  *Macro:
    967  *     _BCM_OAM_IS_INIT
    968  * Purpose:
    969  *     Check if module is initialized
    970  * Parameters:
    971  *     unit - soc unit number.
    972  */
    973 #define _BCM_OAM_IS_INIT(unit)                                         \
    974     do {                                                               \
    975         if (_fp_oam_control[unit] == NULL) {                           \
    976             LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: Module " \
    977                 "not initialized\n")));                                \
    978             return (BCM_E_INIT);                                       \
    979         }                                                              \
    980     } while (0)
    981 
    982 /*
    983  * Macro:
    984  *     _BCM_OAM_ALLOC
    985  * Purpose:
    986  *      Generic memory allocation routine.
    987  * Parameters:
    988  *    _ptr_     - Pointer to allocated memory.
    989  *    _ptype_   - Pointer type.
    990  *    _size_    - Size of heap memory to be allocated.
    991  *    _descr_   - Information about this memory allocation.
    992  */
    993 #define _BCM_OAM_ALLOC(_ptr_,_ptype_,_size_,_descr_)             \
    994     do {                                                         \
    995         if (NULL == (_ptr_)) {                                   \
    996            (_ptr_) = (_ptype_ *) sal_alloc((_size_), (_descr_)); \
    997         }                                                        \
    998         if((_ptr_) != NULL) {                                    \
    999             sal_memset((_ptr_), 0, (_size_));                    \
   1000         }  else {                                                \
   1001             LOG_ERROR(BSL_LS_BCM_OAM, \
   1002                       (BSL_META("OAM Error: Allocation failure %s\n"), \
   1003                        (_descr_)));                              \
   1004         }                                                        \
   1005     } while (0)
   1006 
   1007 /*
   1008  * Macro:
   1009  *     _BCM_OAM_KEY_PACK
   1010  * Purpose:
   1011  *     Pack the hash table look up key fields.
   1012  * Parameters:
   1013  *     _dest_ - Hash key buffer.
   1014  *     _src_  - Hash key field to be packed.
   1015  *     _size_ - Hash key field size in bytes.
   1016  */
   1017 #define _BCM_OAM_KEY_PACK(_dest_,_src_,_size_)            \
   1018     do {                                          \
   1019         sal_memcpy((_dest_), (_src_), (_size_));  \
   1020         (_dest_) += (_size_);                     \
   1021     } while (0)
   1022 
   1023  /* Device OAM control structure */
   1024 _bcm_fp_oam_control_t *_fp_oam_control[SOC_MAX_NUM_DEVICES];
   1025 
   1026 
   1027 /*
   1028  * Function:
   1029  *     _bcm_fp_oam_control_get
   1030  * Purpose:
   1031  *     Lookup a OAM control config from a bcm device id.
   1032  * Parameters:
   1033  *     unit -  (IN)BCM unit number.
   1034  *     oc   -  (OUT) OAM control structure.
   1035  * Retruns:
   1036  *     BCM_E_XXX
   1037  */
   1038 STATIC int
   1039 _bcm_fp_oam_control_get(int unit, _bcm_fp_oam_control_t **oc)
   1040 {
   1041     if (NULL == oc) {
   1042         return (BCM_E_PARAM);
   1043     }
   1044 
   1045     /* Ensure oam module is initialized. */
   1046     _BCM_OAM_IS_INIT(unit);
   1047 
   1048     *oc = _fp_oam_control[unit];
   1049 
   1050     return (BCM_E_NONE);
   1051 }
   1052 
   1053 /*
   1054  * Function:
   1055  *      _bcm_fp_oam_msg_send_receive
   1056  * Purpose:
   1057  *      Sends given control message to the uController.
   1058  *      Receives and verifies expected reply.
   1059  *      Performs DMA operation if required.
   1060  * Parameters:
   1061  *      unit        - (IN) Unit number.
   1062  *      msg_class   - (IN) Message Class
   1063  *      s_subclass  - (IN) Message subclass.
   1064  *      s_len       - (IN) Value for 'len' field in message struct.
   1065  *                         Length of buffer to flush if DMA send is required.
   1066  *      s_data      - (IN) Value for 'data' field in message struct.
   1067  *                         Ignored if message requires a DMA send/receive
   1068  *                         operation.
   1069  *      r_subclass  - (IN) Expected reply message subclass.
   1070  *      r_len       - (OUT) Returns value in 'len' reply message field.
   1071  * Returns:
   1072  *      BCM_E_XXX
   1073  * Notes:
   1074  *     - The uc_msg 'len' and 'data' fields of mos_msg_data_t
   1075  *       can take any arbitrary data.
   1076  */
   1077 STATIC int
   1078 _bcm_fp_oam_msg_send_receive(int unit, uint8 msg_class, uint8 s_subclass,
   1079                                     uint16 s_len, uint32 s_data,
   1080                                     uint8 r_subclass, uint16 *r_len)
   1081 {
   1082     int rv;
   1083     _bcm_fp_oam_control_t *oc;
   1084     mos_msg_data_t send, reply;
   1085     uint8 *dma_buffer = NULL;
   1086     int dma_buffer_len = 0, uc_num = 0;
   1087     uint32 uc_rv;
   1088 
   1089     /* Lock already taken by the calling routine. */
   1090     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
   1091 
   1092     sal_memset(&send, 0, sizeof(send));
   1093     sal_memset(&reply, 0, sizeof(reply));
   1094     send.s.mclass = msg_class;
   1095     send.s.subclass = s_subclass;
   1096     send.s.len = bcm_htons(s_len);
   1097 
   1098     /* Set 'data' to DMA buffer address if a DMA operation is
   1099      * required for send or receive. */
   1100 #if defined(INCLUDE_CCM)
   1101     if (msg_class == MOS_MSG_CLASS_CCM) {
   1102         dma_buffer = oc->dma_buffer;
   1103         dma_buffer_len = oc->dma_buffer_len;
   1104         uc_num = oc->ccm_uc_num;
   1105     } else
   1106 #endif /* INCLUDE_CCM */
   1107 #if defined(INCLUDE_BHH)
   1108     if (msg_class == MOS_MSG_CLASS_BHH) {
   1109         dma_buffer = oc->bhh_dma_buffer;
   1110         dma_buffer_len = oc->bhh_dma_buffer_len;
   1111         uc_num = oc->bhh_uc_num;
   1112     } else
   1113 #endif /* INCLUDE_BHH */
   1114 #if defined(INCLUDE_MPLS_LM_DM)
   1115     if (msg_class == MOS_MSG_CLASS_MPLS_LM_DM) {
   1116         dma_buffer = oc->mpls_lm_dm_dma_buffer;
   1117         dma_buffer_len = oc->mpls_lm_dm_dma_buffer_len;
   1118         uc_num = oc->mpls_lm_dm_uc_num;
   1119     }
   1120 #endif /* INCLUDE_MPLS_LM_DM */
   1121 
   1122     if(dma_buffer == NULL){
   1123         return (BCM_E_INTERNAL);
   1124     }
   1125 
   1126     if (MOS_MSG_DMA_MSG(s_subclass) ||
   1127         MOS_MSG_DMA_MSG(r_subclass)) {
   1128         send.s.data = bcm_htonl(soc_cm_l2p(unit, dma_buffer));
   1129     } else {
   1130         send.s.data = bcm_htonl(s_data);
   1131     }
   1132 
   1133     /* Flush DMA memory */
   1134     if (MOS_MSG_DMA_MSG(s_subclass)) {
   1135         soc_cm_sflush(unit, dma_buffer, s_len);
   1136     }
   1137 
   1138     /* Invalidate DMA memory to read */
   1139     if (MOS_MSG_DMA_MSG(r_subclass)) {
   1140         soc_cm_sinval(unit, dma_buffer, dma_buffer_len);
   1141     }
   1142 
   1143     rv = soc_cmic_uc_msg_send_receive(unit, uc_num, &send, &reply,
   1144                                       _UC_MSG_TIMEOUT_USECS);
   1145 
   1146     /* Check reply class, subclass */
   1147     if (rv == SOC_E_TIMEOUT) {
   1148         return (BCM_E_TIMEOUT);
   1149     } else if (rv == SOC_E_INIT) {
   1150         return (BCM_E_INIT);
   1151     } else if (rv != SOC_E_NONE) {
   1152         LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: "
   1153                   "UC Message Send/Rcv Failed %s\n"), bcm_errmsg(rv)));
   1154         return (BCM_E_INTERNAL);
   1155     }
   1156 
   1157     /* Convert uController error code to BCM */
   1158     uc_rv = bcm_ntohl(reply.s.data);
   1159     switch(uc_rv) {
   1160     case SHR_UC_E_NONE:
   1161         rv = BCM_E_NONE;
   1162         break;
   1163     case SHR_UC_E_INTERNAL:
   1164         rv = BCM_E_INTERNAL;
   1165         break;
   1166     case SHR_UC_E_MEMORY:
   1167         rv = BCM_E_MEMORY;
   1168         break;
   1169     case SHR_UC_E_PARAM:
   1170         rv = BCM_E_PARAM;
   1171         break;
   1172     case SHR_UC_E_RESOURCE:
   1173         rv = BCM_E_RESOURCE;
   1174         break;
   1175     case SHR_UC_E_EXISTS:
   1176         rv = BCM_E_EXISTS;
   1177         break;
   1178     case SHR_UC_E_NOT_FOUND:
   1179         rv = BCM_E_NOT_FOUND;
   1180         break;
   1181     case SHR_UC_E_INIT:
   1182         rv = BCM_E_INIT;
   1183         break;
   1184     case SHR_UC_E_UNAVAIL:
   1185         rv = BCM_E_UNAVAIL;
   1186         break;
   1187     default:
   1188         rv = BCM_E_INTERNAL;
   1189         break;
   1190     }
   1191 
   1192     *r_len = bcm_ntohs(reply.s.len);
   1193 
   1194     /*Check reply class and subclass*/
   1195     if((rv == SOC_E_NONE) && ((reply.s.mclass != msg_class) ||
   1196         (reply.s.subclass != r_subclass)))
   1197     {
   1198         LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: "
   1199           "UC Err or Rcv Sclass not same as Expected %s\n"), bcm_errmsg(rv)));
   1200         return BCM_E_INTERNAL;
   1201     }
   1202 
   1203     return (rv);
   1204 }
   1205 
   1206 /*
   1207  * Function:
   1208  *     _bcm_fp_oam_endpoint_gport_resolve
   1209  * Purpose:
   1210  *     Resolve an endpoint GPORT value to SGLP and DGLP value.
   1211  * Parameters:
   1212  *     unit       - (IN) BCM device number
   1213  *     ep_info_p  - (IN/OUT) Pointer to endpoint information.
   1214  *     src_glp    - (IN/OUT) Pointer to source generic logical port value.
   1215  *     dst_glp    - (IN/OUT) Pointer to destination generic logical port value.
   1216  *     tx_gport   - (OUT)    Physical gport on which OAM pkts should go out
   1217  *     trunk_id   - (IN/OUT) Pointer to trunk id
   1218  *     trunk_member - (OUT)  trunk member on which EP present 
   1219  *
   1220  * Retruns:
   1221  *     BCM_E_XXX
   1222  */
   1223 STATIC int
   1224 _bcm_fp_oam_endpoint_gport_resolve(int unit,
   1225                                    bcm_oam_endpoint_info_t *ep_info_p,
   1226                                    int *src_glp,
   1227                                    int *dst_glp,
   1228                                    bcm_gport_t *tx_gport,
   1229                                    bcm_trunk_t *trunk_id,
   1230                                    bcm_trunk_member_t *trunk_member)
   1231 {
   1232     bcm_module_t        module_id;              /* Module ID */
   1233     bcm_port_t          port_id;                /* Port ID */
   1234     int                 local_id;               /* Hardware ID */
   1235     bcm_trunk_info_t    trunk_info;             /* Trunk information.  */
   1236     bcm_trunk_member_t *member_array = NULL;   /* Trunk member array */
   1237     int                 member_count = 0;       /* Trunk Member count */
   1238     bcm_trunk_t         tid = BCM_TRUNK_INVALID;
   1239     int                 tx_enabled = 1;         /* CCM Tx enabled */
   1240     int                 rv = 0;                 /* Return Value */
   1241     int                 is_local = 0;
   1242 
   1243     /* Get Trunk ID or (Modid + Port) value from Gport */
   1244     BCM_IF_ERROR_RETURN(_bcm_esw_gport_resolve(unit, ep_info_p->gport,
   1245                                                &module_id, &port_id, trunk_id,
   1246                                                &local_id));
   1247 
   1248     /* Set CCM endpoint Tx status only for local endpoints. */
   1249     if(ep_info_p->type == bcmOAMEndpointTypeEthernet) {
   1250         if (!(ep_info_p->flags & BCM_OAM_ENDPOINT_REMOTE)) {
   1251             tx_enabled =
   1252                 (ep_info_p->ccm_period != BCM_OAM_ENDPOINT_CCM_PERIOD_DISABLED) ? 1 : 0;
   1253         }
   1254     }
   1255 
   1256     if (SOC_GPORT_IS_MPLS_PORT(ep_info_p->gport)) {
   1257         if(BCM_TRUNK_INVALID == (*trunk_id)){
   1258             rv = _bcm_esw_modid_is_local(unit, module_id, &is_local);
   1259             if(BCM_SUCCESS(rv) && (is_local)) {
   1260                 _bcm_esw_glp_construct(unit, *trunk_id, module_id, port_id,
   1261                                        dst_glp);
   1262                 *src_glp = *dst_glp;
   1263             }
   1264         }
   1265     }
   1266 
   1267     /*
   1268      * If Gport is Trunk type, _bcm_esw_gport_resolve()
   1269      * sets trunk_id. Using Trunk ID, get Dst Modid and Port value.
   1270      */
   1271     if (BCM_GPORT_IS_TRUNK(ep_info_p->gport)) {
   1272         if (BCM_TRUNK_INVALID == *trunk_id)  {
   1273             /* Has to be a valid Trunk. */
   1274             return (BCM_E_PARAM);
   1275         }
   1276     }
   1277 
   1278 
   1279     if (BCM_TRUNK_INVALID == *trunk_id) { /* Phy gport */
   1280         BCM_GPORT_MODPORT_SET(*tx_gport, module_id, port_id);
   1281     } else {
   1282 
   1283         /* Construct Hw SGLP value. */
   1284         BCM_IF_ERROR_RETURN(_bcm_esw_glp_construct(unit, *trunk_id,
   1285                                                    module_id, port_id,
   1286                                                    src_glp));
   1287 
   1288         /*
   1289          * CCM Tx is enabled on a trunk member port.
   1290          * trunk_index value is required to derive the Modid and Port info.
   1291          */
   1292         if (1 == tx_enabled) {
   1293 
   1294             if (_BCM_OAM_INVALID_INDEX == ep_info_p->trunk_index) {
   1295                 /* Invalid Trunk member index passed. */
   1296                 return (BCM_E_PORT);
   1297             }
   1298 
   1299             /* Get count of ports in this trunk. */
   1300             BCM_IF_ERROR_RETURN(bcm_esw_trunk_get(unit, *trunk_id, NULL,
   1301                                                   0, NULL, &member_count));
   1302             if (0 == member_count) {
   1303                 /* No members have been added to the trunk group yet */
   1304                 return BCM_E_PARAM;
   1305             }
   1306 
   1307             _BCM_OAM_ALLOC(member_array, bcm_trunk_member_t,
   1308                            sizeof(bcm_trunk_member_t) * member_count,
   1309                            "Trunk info");
   1310             if (NULL == member_array) {
   1311                 return (BCM_E_MEMORY);
   1312             }
   1313 
   1314             /* Get Trunk Info for the Trunk ID. */
   1315             rv = bcm_esw_trunk_get(unit, *trunk_id, &trunk_info,
   1316                                    member_count, member_array, &member_count);
   1317             if (BCM_FAILURE(rv)) {
   1318                 sal_free(member_array);
   1319                 return (rv);
   1320             }
   1321 
   1322             /* Check if the input trunk_index is valid. */
   1323             if (ep_info_p->trunk_index >= member_count) {
   1324                 sal_free(member_array);
   1325                 return BCM_E_PARAM;
   1326             }
   1327 
   1328             /* Get the Modid and Port value using Trunk Index value. */
   1329             rv = _bcm_esw_gport_resolve(unit,
   1330                                         member_array[ep_info_p->trunk_index].gport,
   1331                                         &module_id, &port_id, &tid, &local_id);
   1332             if (BCM_FAILURE(rv)) {
   1333                 sal_free(member_array);
   1334                 return (rv);
   1335             }
   1336 
   1337             sal_free(member_array);
   1338 
   1339             /* Construct Hw DGLP value. */
   1340             BCM_IF_ERROR_RETURN(_bcm_esw_glp_construct(unit, BCM_TRUNK_INVALID,
   1341                                                        module_id, port_id,
   1342                                                        dst_glp));
   1343             *trunk_member = member_array[ep_info_p->trunk_index];
   1344 
   1345             *tx_gport = member_array[ep_info_p->trunk_index].gport;
   1346         } else {
   1347             *dst_glp = *src_glp;
   1348         }
   1349     }
   1350 
   1351     /*
   1352      * Application can resolve the trunk and pass the desginated
   1353      * port as Gport value. Check if the Gport belongs to a trunk.
   1354      */
   1355     if ((BCM_TRUNK_INVALID == (*trunk_id)) &&
   1356         (BCM_GPORT_IS_MODPORT(ep_info_p->gport) ||
   1357          BCM_GPORT_IS_LOCAL(ep_info_p->gport))) {
   1358 
   1359         /* When Gport is ModPort or Port type, _bcm_esw_gport_resolve()
   1360          * returns Modid and Port value. Use these values to make the DGLP
   1361          * value.
   1362          */
   1363         _bcm_esw_glp_construct(unit, BCM_TRUNK_INVALID,
   1364                                module_id, port_id, dst_glp);
   1365 
   1366         /* Use the Modid, Port value and determine if the port
   1367          * belongs to a Trunk.
   1368          */
   1369         rv = bcm_esw_trunk_find(unit, module_id, port_id, trunk_id);
   1370         if (BCM_SUCCESS(rv)) {
   1371             /*
   1372              * Port is member of a valid trunk.
   1373              * Now create the SGLP value from Trunk ID.
   1374              */
   1375             _bcm_esw_glp_construct(unit, *trunk_id, module_id, port_id, src_glp);
   1376         } else {
   1377             /* Port not a member of trunk. DGLP and SGLP are the same. */
   1378             *src_glp = *dst_glp;
   1379         }
   1380     }
   1381 
   1382     return BCM_E_NONE;
   1383 }
   1384 
   1385 
   1386 /*
   1387  * Function:
   1388  *     _bcm_fp_oam_olp_l2_header_pack
   1389  * Purpose:
   1390  *     Pack OLP L2 Header into buffer.
   1391  * Parameters:
   1392  *     buffer     - (IN/OUT) Buffer to Pack OLP Header
   1393  *     l2         - (IN)     Pointer to OLP L2 Header fields structure.
   1394  * Retruns:
   1395  *     Pointer to end of packet buffer
   1396  */
   1397 STATIC uint8 *
   1398 _bcm_fp_oam_olp_l2_header_pack(uint8 *buffer, soc_olp_l2_hdr_t *l2)
   1399 {
   1400 
   1401     int     i;
   1402 
   1403     for (i = 0; i < 6; i++) {
   1404         _SHR_PACK_U8(buffer, l2->dst_mac[i]);
   1405     }
   1406 
   1407     for (i = 0; i < 6; i++) {
   1408         _SHR_PACK_U8(buffer, l2->src_mac[i]);
   1409     }
   1410 
   1411     /* Vlan tpid */
   1412     _SHR_PACK_U16(buffer, l2->tpid);
   1413 
   1414     /* Vlan Id */
   1415     _SHR_PACK_U16(buffer, l2->vlan);
   1416 
   1417     /* Ethertype */
   1418     _SHR_PACK_U16(buffer, l2->etherType);
   1419 
   1420     return (buffer);
   1421 }
   1422 
   1423 /*
   1424  * Function:
   1425  *     _bcm_fp_oam_olp_l2_header_unpack
   1426  * Purpose:
   1427  *     Unpack OLP L2 Header into buffer.
   1428  * Parameters:
   1429  *     buffer     - (IN/OUT) Buffer to Pack OLP Header
   1430  *     l2         - (IN)     Pointer to OLP L2 Header fields structure.
   1431  * Retruns:
   1432  *     Pointer to end of packet buffer
   1433  */
   1434 STATIC uint8 *
   1435 _bcm_fp_oam_olp_l2_header_unpack(uint8 *buffer, soc_olp_l2_hdr_t *l2)
   1436 {
   1437 
   1438     int     i;
   1439 
   1440     for (i = 0; i < 6; i++) {
   1441         _SHR_UNPACK_U8(buffer, l2->dst_mac[i]);
   1442     }
   1443 
   1444     for (i = 0; i < 6; i++) {
   1445         _SHR_UNPACK_U8(buffer, l2->src_mac[i]);
   1446     }
   1447 
   1448     /* Vlan tpid */
   1449     _SHR_UNPACK_U16(buffer, l2->tpid);
   1450 
   1451     /* Vlan Id */
   1452     _SHR_UNPACK_U16(buffer, l2->vlan);
   1453 
   1454     /* Ethertype */
   1455     _SHR_UNPACK_U16(buffer, l2->etherType);
   1456 
   1457     return (buffer);
   1458 }
   1459 
   1460 int
   1461 bcm_fp_oam_convert_ep_to_time_spec(bcm_time_spec_t* bts, int sec, int ns)
   1462 {
   1463     int rv = BCM_E_NONE;
   1464 
   1465     if (bts != NULL) {
   1466         /* if both seconds and nanoseconds are negative or both positive,
   1467          * then the ucode's subtraction is ok.
   1468          * if seconds and nanoseconds have different signs, then "borrow"
   1469          * 1000000000 nanoseconds from seconds.
   1470          */
   1471         if ((sec < 0) && (ns > 0)) {
   1472             ns -= 1000000000;
   1473             sec += 1;
   1474         } else if ((sec > 0) && (ns < 0)) {
   1475             ns += 1000000000;
   1476             sec -= 1;
   1477         }
   1478 
   1479         if (ns < 0) {
   1480             /* if still negative, then something else is wrong.
   1481              * the nanoseconds field is the difference between two
   1482              * (non-negative) time-stamps.
   1483              */
   1484             rv = BCM_E_INTERNAL;
   1485         }
   1486 
   1487         /* if seconds is negative then set the bts is-negative flag,
   1488          * and use the absolute value of seconds & nanoseconds.
   1489          */
   1490         bts->isnegative  = (sec < 0 ? 1 : 0);
   1491         bts->seconds     = BCM_OAM_ABS(sec);
   1492         bts->nanoseconds = BCM_OAM_ABS(ns);
   1493     } else {
   1494         rv = BCM_E_INTERNAL;
   1495     }
   1496 
   1497     return rv;
   1498 }
   1499 #endif /* INCLUDE_CCM || INCLUDE_BHH || INCLUDE_MPLS_LM_DM */
   1500 
   1501 
   1502 /*******************************************************************************/
   1503 /* PM routines for BHH & MPLS LM/DM app start                                  */
   1504 /*******************************************************************************/
   1505 #if defined(INCLUDE_BHH) || defined(INCLUDE_MPLS_LM_DM)
   1506 /*
   1507  * Function:
   1508  *     _bcm_fp_oam_data_collection_modes_init
   1509  * Purpose:
   1510  *     Get the data collection mode for all apps
   1511  * Parameters:
   1512  *     unit      - (IN) BCM device number
   1513  * Returns:
   1514  *     None
   1515  */
   1516 void _bcm_fp_oam_data_collection_modes_init(int unit)
   1517 {
   1518     _bcm_fp_oam_control_t   *oc = NULL; /* Pointer to control structure.    */
   1519     int rv = BCM_E_NONE;
   1520 
   1521     rv = _bcm_fp_oam_control_get(unit, &oc);
   1522 
   1523     if (BCM_FAILURE(rv)) {
   1524         LOG_ERROR(BSL_LS_BCM_OAM,
   1525                 (BSL_META_U(unit,
   1526                             "OAM(unit %d) Error: Oam control get failed "
   1527                             "- %s.\n"), unit, bcm_errmsg(rv)));
   1528         return;
   1529     }
   1530 #if defined (INCLUDE_BHH)
   1531     oc->pm_bhh_lmdm_data_collection_mode = soc_property_get(unit,
   1532             spn_BHH_DATA_COLLECTION_MODE, _BCM_OAM_PM_COLLECTION_MODE_NONE);
   1533 #endif /* INCLUDE_BHH */
   1534 #if defined (INCLUDE_MPLS_LM_DM)
   1535     oc->pm_mpls_lm_dm_data_collection_mode = soc_property_get(unit,
   1536             spn_MPLS_LMDM_DATA_COLLECTION_MODE, _BCM_OAM_PM_COLLECTION_MODE_NONE);
   1537 #endif /* INCLUDE_MPLS_LM_DM */
   1538 }
   1539 
   1540 /*
   1541  * Function:
   1542  *     _bcm_fp_oam_pm_init
   1543  * Purpose:
   1544  *     Initialize PM module for all apps
   1545  * Parameters:
   1546  *     unit      - (IN) BCM device number
   1547  * Returns:
   1548  *     BCM_E_XXX
   1549  */
   1550 int _bcm_fp_oam_pm_init(int unit)
   1551 {
   1552     /* Profile data structure initialization */
   1553     _bcm_fp_oam_pm_profile_control_t *pmc = NULL;
   1554     _bcm_fp_oam_control_t            *oc  = NULL;
   1555 
   1556     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
   1557     _BCM_OAM_LOCK(oc);
   1558 
   1559      _bcm_fp_oam_data_collection_modes_init(unit);
   1560 
   1561 
   1562     /* Allocate profiles only if one of them has processed stats
   1563      * collection enabled
   1564      */
   1565     if ((_BCM_FP_OAM_PM_BHH_DATA_COLLECTION_MODE_IS_PROCESSED(oc)) ||
   1566         (_BCM_FP_OAM_PM_MPLS_LM_DM_DATA_COLLECTION_MODE_IS_PROCESSED(oc))) {
   1567 
   1568         _BCM_OAM_ALLOC(pmc, _bcm_fp_oam_pm_profile_control_t,
   1569                 sizeof (_bcm_fp_oam_pm_profile_control_t),
   1570                 "OAM PM profile control");
   1571         if (!pmc) {
   1572             _BCM_OAM_UNLOCK(oc);
   1573             return BCM_E_MEMORY;
   1574         }
   1575 
   1576         pm_profile_control[unit] = pmc;
   1577     }
   1578     _BCM_OAM_UNLOCK(oc);
   1579     return BCM_E_NONE;
   1580 }
   1581 
   1582 #if defined (INCLUDE_BHH)
   1583 /*
   1584  * Function:
   1585  *     _bcm_fp_oam_bhh_pm_init
   1586  * Purpose:
   1587  *     Initialize PM module for BHH app
   1588  * Parameters:
   1589  *     unit      - (IN) BCM device number
   1590  * Returns:
   1591  *     BCM_E_XXX
   1592  */
   1593 int _bcm_fp_oam_bhh_pm_init(int unit)
   1594 {
   1595 
   1596     _bcm_fp_oam_control_t            *oc  = NULL;
   1597 
   1598     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
   1599     _BCM_OAM_LOCK(oc);
   1600 
   1601 
   1602     /*
   1603      * Allocate DMA buffers and raw data buffers.
   1604      *
   1605      * 1) DMA buffer will be used to send and receive 'long' messages
   1606      * between SDK Host and uController (BTE).
   1607      *
   1608      *
   1609      * 2) Allocate RAW data buffers which is provided
   1610      * to Application during PM event callback
   1611      */
   1612     /* DMA buffer */
   1613     if (!oc->ukernel_not_ready) {
   1614         if (_BCM_FP_OAM_PM_BHH_DATA_COLLECTION_MODE_ENABLED(oc)) {
   1615             oc->pm_bhh_dma_buffer_len = sizeof(shr_oam_pm_msg_ctrl_t);
   1616             oc->pm_bhh_dma_buffer = soc_cm_salloc(unit,
   1617                                                   oc->pm_bhh_dma_buffer_len,
   1618                                                   "PM DMA buffer");
   1619             if (!oc->pm_bhh_dma_buffer) {
   1620                 _BCM_OAM_UNLOCK(oc);
   1621                return (BCM_E_MEMORY);
   1622             }
   1623             sal_memset(oc->pm_bhh_dma_buffer, 0, oc->pm_bhh_dma_buffer_len);
   1624             if (_BCM_FP_OAM_PM_BHH_DATA_COLLECTION_MODE_IS_RAW_DATA(oc)) {
   1625                 /* Raw data buffers */
   1626                 oc->pm_bhh_raw_data_num_buffers =
   1627                                 soc_property_get(unit,
   1628                                                  spn_BHH_PM_RAW_DATA_BUFFERS, 4);
   1629             }
   1630             /* For first time, when we write this will be
   1631                incremented to zero index */
   1632             PM_WRITE_DONE_INDEX(_BCM_FP_OAM_PM_BHH_EVENT_IDX) = -1;
   1633             /* Initially all the buffers are free */
   1634             NUM_FREE_BUFFERS(_BCM_FP_OAM_PM_BHH_EVENT_IDX) = BCM_OAM_MAX_PM_BUFFERS;
   1635         }
   1636     }
   1637     _BCM_OAM_UNLOCK(oc);
   1638     return BCM_E_NONE;
   1639 }
   1640 #endif /* INCLUDE_BHH */
   1641 
   1642 #if defined (INCLUDE_MPLS_LM_DM)
   1643 /*
   1644  * Function:
   1645  *     _bcm_fp_oam_mpls_lm_dm_pm_init
   1646  * Purpose:
   1647  *     Initialize PM module for BHH app
   1648  * Parameters:
   1649  *     unit      - (IN) BCM device number
   1650  * Returns:
   1651  *     BCM_E_XXX
   1652  */
   1653 int _bcm_fp_oam_mpls_lm_dm_pm_init(int unit)
   1654 {
   1655 
   1656     _bcm_fp_oam_control_t            *oc  = NULL;
   1657 
   1658     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
   1659     _BCM_OAM_LOCK(oc);
   1660 
   1661     /* DMA buffer */
   1662     if (oc->mpls_lm_dm_ukernel_ready) {
   1663         if (_BCM_FP_OAM_PM_MPLS_LM_DM_DATA_COLLECTION_MODE_ENABLED(oc)) {
   1664 
   1665             if (_BCM_FP_OAM_PM_MPLS_LM_DM_DATA_COLLECTION_MODE_IS_RAW_DATA(oc)) {
   1666                 /* Raw data buffers */
   1667                 oc->pm_mpls_lm_dm_raw_data_num_buffers =
   1668                           soc_property_get(unit,
   1669                                            spn_MPLS_LMDM_PM_RAW_DATA_BUFFERS, 4);
   1670                 /* For first time, when we write this will be incremented to
   1671                  * zero index
   1672                  */
   1673                 PM_READ_DONE_INDEX(_BCM_FP_OAM_PM_MPLS_LM_DM_EVENT_IDX) = -1;
   1674                 PM_WRITE_DONE_INDEX(_BCM_FP_OAM_PM_MPLS_LM_DM_EVENT_IDX) = -1;
   1675 
   1676                 /* Initially all the buffers are free */
   1677                 NUM_FREE_BUFFERS(_BCM_FP_OAM_PM_MPLS_LM_DM_EVENT_IDX) =
   1678                                                          BCM_OAM_MAX_PM_BUFFERS;
   1679 
   1680             }
   1681         }
   1682     }
   1683     _BCM_OAM_UNLOCK(oc);
   1684     return BCM_E_NONE;
   1685 }
   1686 #endif /* INCLUDE_MPLS_LM_DM */
   1687 
   1688 /*
   1689  * Function:
   1690  *     _bcm_fp_oam_pm_dma_buffer_from_endpoint_type_get
   1691  * Purpose:
   1692  *     Get DMA buffer from endpoint type
   1693  * Parameters:
   1694  *     unit      - (IN)  BCM device number
   1695  *     type      - (OUT) Endpoint type
   1696  * Returns:
   1697  *     Pointer to dma buffer
   1698  */
   1699 uint8*
   1700 _bcm_fp_oam_pm_dma_buffer_from_endpoint_type_get(int unit,
   1701                                                  bcm_oam_endpoint_type_t type)
   1702 {
   1703     _bcm_fp_oam_control_t *oc = NULL;
   1704     int rv = BCM_E_NONE;
   1705 
   1706     rv = _bcm_fp_oam_control_get(unit, &oc);
   1707     if (BCM_FAILURE(rv)) {
   1708         return NULL;
   1709     }
   1710 
   1711 #if defined (INCLUDE_BHH)
   1712     if (BHH_TYPE(type)) {
   1713         return oc->pm_bhh_dma_buffer;
   1714 
   1715     } else
   1716 #endif /* INCLUDE_BHH */
   1717 
   1718 #if defined(INCLUDE_MPLS_LM_DM)
   1719     if (_MPLS_LM_DM_ENDPOINT_TYPE(type)) {
   1720         return oc->mpls_lm_dm_dma_buffer;
   1721     }
   1722 #endif /* INCLUDE_MPLS_LM_DM */
   1723     return NULL;
   1724 }
   1725 
   1726 int
   1727 _bcm_fp_oam_pm_dma_buffer_and_len_from_class_get(int unit, uint8 class,
   1728                                                  uint8 **buffer, int *buffer_len)
   1729 {
   1730     _bcm_fp_oam_control_t *oc = NULL;
   1731     int rv = BCM_E_NONE;
   1732 
   1733     rv = _bcm_fp_oam_control_get(unit, &oc);
   1734     if (BCM_FAILURE(rv)) {
   1735         return rv;
   1736     }
   1737 
   1738     switch(class) {
   1739 #if defined(INCLUDE_BHH)
   1740         case MOS_MSG_CLASS_BHH:
   1741             *buffer = oc->pm_bhh_dma_buffer;
   1742             *buffer_len = oc->pm_bhh_dma_buffer_len;
   1743             break;
   1744 #endif /* INCLUDE_BHH */
   1745 #if defined(INCLUDE_MPLS_LM_DM)
   1746         case MOS_MSG_CLASS_MPLS_LM_DM:
   1747             *buffer = oc->mpls_lm_dm_dma_buffer;
   1748             *buffer_len = oc->mpls_lm_dm_dma_buffer_len;
   1749             break;
   1750 #endif /* INCLUDE_MPLS_LM_DM */
   1751         default:
   1752             return BCM_E_PARAM;
   1753             break;
   1754     }
   1755     return BCM_E_NONE;
   1756 }
   1757 
   1758 uint8* _bcm_fp_oam_pm_dma_buffer_get(int unit, bcm_oam_event_type_t event_type)
   1759 {
   1760     _bcm_fp_oam_control_t *oc = NULL;
   1761     int rv = BCM_E_NONE;
   1762     uint8   *buffer = NULL;
   1763 
   1764     rv = _bcm_fp_oam_control_get(unit, &oc);
   1765     if (BCM_FAILURE(rv)) {
   1766         return buffer;
   1767     }
   1768     switch(event_type) {
   1769 #if defined(INCLUDE_BHH)
   1770         case bcmOAMEventBHHRawData:
   1771             buffer = oc->pm_bhh_dma_buffer;
   1772             break;
   1773 #endif /* INCLUDE_BHH */
   1774 #if defined(INCLUDE_MPLS_LM_DM)
   1775         case bcmOAMEventMplsLmDmRawData:
   1776             buffer = oc->mpls_lm_dm_dma_buffer;
   1777             break;
   1778 #endif /* INCLUDE_MPLS_LM_DM */
   1779         default:
   1780             buffer = NULL;
   1781             break;
   1782     }
   1783     return buffer;
   1784 }
   1785 
   1786 /*
   1787  * Function:
   1788  *      _bcm_fp_oam_pm_msg_send_receive
   1789  * Purpose:
   1790  *      Sends given PM control message to the uController.
   1791  *      Receives and verifies expected reply.
   1792  *      Performs DMA operation if required.
   1793  * Parameters:
   1794  *      unit        - (IN) Unit number.
   1795  *      s_class     - (IN) PM message class.
   1796  *      s_len       - (IN) Value for 'len' field in message struct.
   1797  *                         Length of buffer to flush if DMA send is required.
   1798  *      s_data      - (IN) Value for 'data' field in message struct.
   1799  *                         Ignored if message requires a DMA send/receive
   1800  *                         operation.
   1801  *      r_subclass  - (IN) Expected reply message subclass.
   1802  *      r_len       - (OUT) Returns value in 'len' reply message field.
   1803  * Returns:
   1804  *      BCM_E_XXX
   1805  * Notes:
   1806  *     - The uc_msg 'len' and 'data' fields of mos_msg_data_t
   1807  *       can take any arbitrary data.
   1808  *
   1809  *     PM Long Control message:
   1810  *     - PM control messages that require send/receive of information
   1811  *       that cannot fit in the uc_msg 'len' and 'data' fields need to
   1812  *       use DMA operations to exchange information (long control message).
   1813  *
   1814  *     - PM convention for long control messages for
   1815  *        'mos_msg_data_t' fields:
   1816  *          'len'    size of the DMA buffer to send to uController
   1817  *          'data'   physical DMA memory address to send or receive
   1818  *
   1819  *      DMA Operations:
   1820  *      - DMA read/write operation is performed when a long BHH control
   1821  *        message is involved.
   1822  *
   1823  *      - Messages that require DMA operation (long control message)
   1824  *        is indicated by MOS_MSG_DMA_MSG().
   1825  *
   1826  *      - Callers must 'pack' and 'unpack' corresponding information
   1827  *        into/from DMA buffer indicated by dma_buffer.
   1828  */
   1829 STATIC int
   1830 _bcm_fp_oam_pm_msg_send_receive(int unit, uint8 s_class, uint8 s_subclass,
   1831                                     uint16 s_len, uint32 s_data,
   1832                                     uint8 r_subclass, uint16 *r_len)
   1833 {
   1834     int rv = BCM_E_NONE;
   1835     _bcm_fp_oam_control_t *oc;
   1836     mos_msg_data_t send, reply;
   1837     uint8 *dma_buffer = NULL;
   1838     int dma_buffer_len = 0;
   1839     uint32 uc_rv;
   1840     int uc_num = -1;
   1841 
   1842     /* Lock already taken by the calling routine. */
   1843     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
   1844 
   1845     sal_memset(&send, 0, sizeof(send));
   1846     sal_memset(&reply, 0, sizeof(reply));
   1847     send.s.mclass = s_class;
   1848     send.s.subclass = s_subclass;
   1849     send.s.len = bcm_htons(s_len);
   1850 
   1851     /*
   1852      * Set 'data' to DMA buffer address if a DMA operation is
   1853      * required for send or receive.
   1854      */
   1855 
   1856     BCM_IF_ERROR_RETURN(
   1857               _bcm_fp_oam_pm_dma_buffer_and_len_from_class_get(unit, s_class,
   1858                                                                &dma_buffer,
   1859                                                                &dma_buffer_len));
   1860 
   1861     if (MOS_MSG_DMA_MSG(s_subclass) ||
   1862         MOS_MSG_DMA_MSG(r_subclass)) {
   1863         send.s.data = bcm_htonl(soc_cm_l2p(unit, dma_buffer));
   1864     } else {
   1865         send.s.data = bcm_htonl(s_data);
   1866     }
   1867 
   1868     /* Flush DMA memory */
   1869     if (MOS_MSG_DMA_MSG(s_subclass)) {
   1870         soc_cm_sflush(unit, dma_buffer, s_len);
   1871     }
   1872 
   1873     /* Invalidate DMA memory to read */
   1874     if (MOS_MSG_DMA_MSG(r_subclass)) {
   1875         soc_cm_sinval(unit, dma_buffer, dma_buffer_len);
   1876     }
   1877 
   1878     switch (s_class) {
   1879 #if defined(INCLUDE_BHH)
   1880         case MOS_MSG_CLASS_BHH:
   1881             uc_num = oc->bhh_uc_num;
   1882             break;
   1883 #endif /* INCLUDE_BHH */
   1884 #if defined(INCLUDE_MPLS_LM_DM)
   1885         case MOS_MSG_CLASS_MPLS_LM_DM:
   1886             uc_num = oc->mpls_lm_dm_uc_num;
   1887             break;
   1888 #endif /* INCLUDE_MPLS_LM_DM */
   1889         default:
   1890             uc_num = -1;
   1891             break;
   1892     }
   1893 
   1894     if (uc_num == -1) {
   1895         return BCM_E_PARAM;
   1896     }
   1897     /* coverity[unreachable] */
   1898     rv = soc_cmic_uc_msg_send_receive(unit, uc_num,
   1899                                       &send, &reply,
   1900                                       _PM_UC_MSG_TIMEOUT_USECS);
   1901 
   1902     /* Check reply class, subclass */
   1903     /* We can expect the same class that was sent */
   1904     if ((rv != SOC_E_NONE) ||
   1905         (reply.s.mclass != s_class) ||
   1906         (reply.s.subclass != r_subclass)) {
   1907         return (BCM_E_INTERNAL);
   1908     }
   1909 
   1910     /* Convert OAM PM uController error code to BCM */
   1911     uc_rv = bcm_ntohl(reply.s.data);
   1912     switch(uc_rv) {
   1913     case SHR_OAM_PM_UC_E_NONE:
   1914         rv = BCM_E_NONE;
   1915         break;
   1916     case SHR_OAM_PM_UC_E_INTERNAL:
   1917         rv = BCM_E_INTERNAL;
   1918         break;
   1919     case SHR_OAM_PM_UC_E_MEMORY:
   1920         rv = BCM_E_MEMORY;
   1921         break;
   1922     case SHR_OAM_PM_UC_E_PARAM:
   1923         rv = BCM_E_PARAM;
   1924         break;
   1925     case SHR_OAM_PM_UC_E_RESOURCE:
   1926         rv = BCM_E_RESOURCE;
   1927         break;
   1928     case SHR_OAM_PM_UC_E_EXISTS:
   1929         rv = BCM_E_EXISTS;
   1930         break;
   1931     case SHR_OAM_PM_UC_E_NOT_FOUND:
   1932         rv = BCM_E_NOT_FOUND;
   1933         break;
   1934     case SHR_OAM_PM_UC_E_UNAVAIL:
   1935         rv = BCM_E_UNAVAIL;
   1936         break;
   1937     case SHR_OAM_PM_UC_E_VERSION:
   1938         rv = BCM_E_CONFIG;
   1939         break;
   1940     case SHR_OAM_PM_UC_E_INIT:
   1941         rv = BCM_E_INIT;
   1942         break;
   1943     default:
   1944         rv = BCM_E_INTERNAL;
   1945         break;
   1946     }
   1947 
   1948     *r_len = bcm_ntohs(reply.s.len);
   1949 
   1950     return (rv);
   1951 }
   1952 
   1953 int _bcm_fp_oam_pm_profile_compare(bcm_oam_pm_profile_info_t *profile_info1,
   1954                                    bcm_oam_pm_profile_info_t *profile_info2)
   1955 {
   1956     if (!(sal_memcmp(profile_info1->bin_edges, profile_info2->bin_edges,
   1957                      BCM_OAM_MAX_PM_PROFILE_BIN_EDGES * sizeof(uint32)))) {
   1958         /* Match */
   1959         return 1;
   1960     }
   1961     return 0;
   1962 }
   1963 
   1964 int
   1965 _bcm_fp_oam_pm_profile_exists(int unit, bcm_oam_pm_profile_info_t *profile_info)
   1966 {
   1967     int id = 0;
   1968     _bcm_fp_oam_pm_profile_control_t *pmc = NULL;
   1969 
   1970     pmc = pm_profile_control[unit];
   1971     if (!pmc) {
   1972         return 0;
   1973     }
   1974 
   1975     for (id = 0; id < _BCM_OAM_MAX_PM_PROFILES; id++) {
   1976         /* If a profile is in use */
   1977         if (_BCM_FP_OAM_PM_CTRL_PROFILE_IN_USE(pmc, id)) {
   1978             if (_bcm_fp_oam_pm_profile_compare(
   1979                                       _BCM_FP_OAM_PM_CTRL_PROFILE_PTR(pmc, id),
   1980                                       profile_info)) {
   1981                 return 1;
   1982             }
   1983         }
   1984     }
   1985     return 0;
   1986 }
   1987 
   1988 int
   1989 _bcm_fp_oam_find_free_pm_profile_id(int unit, int *pm_profile_id)
   1990 {
   1991     int id = 0;
   1992     _bcm_fp_oam_pm_profile_control_t *pmc = NULL;
   1993 
   1994     pmc = pm_profile_control[unit];
   1995     if (!pmc) {
   1996         return BCM_E_INIT;
   1997     }
   1998 
   1999     /* return the lowest unused id */
   2000     for (id = 0; id < _BCM_OAM_MAX_PM_PROFILES; id++) {
   2001         if (!(_BCM_FP_OAM_PM_CTRL_PROFILE_IN_USE(pmc, id))) {
   2002             /* If a profile is not in use */
   2003             /* Assign it and return */
   2004             *pm_profile_id = id;
   2005             return BCM_E_NONE;
   2006         }
   2007     }
   2008     return BCM_E_RESOURCE;
   2009 }
   2010 
   2011 int
   2012 _bcm_fp_oam_pm_profile_delete(int unit, bcm_oam_pm_profile_t profile_id, int all)
   2013 {
   2014     _bcm_fp_oam_pm_profile_control_t  *pmc;
   2015 #if defined(INCLUDE_MPLS_LM_DM)
   2016     _bcm_fp_oam_control_t             *oc;
   2017     _bcm_fp_oam_mpls_lm_dm_ep_data_t  *ep;
   2018     bcm_oam_endpoint_t                 endpoint_id;
   2019     int                                idx;
   2020 #endif /* INCLUDE_MPLS_LM_DM */
   2021 
   2022     pmc = pm_profile_control[unit];
   2023     if (!pmc) {
   2024         return BCM_E_INIT;
   2025     }
   2026 
   2027     /* Check it only if it is a delete for a particular profile */
   2028     if (!(_BCM_FP_OAM_PM_CTRL_PROFILE_IN_USE(pmc, profile_id)) && !all) {
   2029         /* It is not in use. Return error */
   2030         return BCM_E_NOT_FOUND;
   2031     }
   2032 
   2033     /* Detach all EPs having this profile */
   2034 #if defined(INCLUDE_MPLS_LM_DM)
   2035     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
   2036 
   2037     _MPLS_LM_DM_EP_ITER(ep, idx) {
   2038 
   2039         if (!ep->in_use) {
   2040             continue;
   2041         }
   2042 
   2043         if (ep->pm_profile == profile_id) {
   2044             endpoint_id = _MPLS_LM_DM_SESS_ID_TO_EP_ID(idx);
   2045             BCM_IF_ERROR_RETURN(bcm_fp_oam_pm_profile_detach(unit, endpoint_id,
   2046                                                              profile_id));
   2047         }
   2048     }
   2049 #endif /* INCLUDE_MPLS_LM_DM */
   2050 
   2051     /* Zero out that profile */
   2052     sal_memset(_BCM_FP_OAM_PM_CTRL_PROFILE_PTR(pmc, profile_id), 0,
   2053                 sizeof(bcm_oam_pm_profile_info_t));
   2054     /* Mark it un used */
   2055     _BCM_FP_OAM_SET_PM_CTRL_PROFILE_NOT_IN_USE(pmc, profile_id);
   2056 
   2057     return BCM_E_NONE;
   2058 }
   2059 
   2060 int
   2061 bcm_fp_oam_pm_profile_delete(int unit, bcm_oam_pm_profile_t profile_id)
   2062 {
   2063     if (!(_BCM_FP_OAM_PM_PROFILE_ID_VALID(profile_id))) {
   2064         return BCM_E_PARAM;
   2065     }
   2066     return _bcm_fp_oam_pm_profile_delete(unit, profile_id, 0);
   2067 }
   2068 
   2069 int
   2070 bcm_fp_oam_pm_profile_delete_all(int unit)
   2071 {
   2072     int id;
   2073     for (id = 0; id < _BCM_OAM_MAX_PM_PROFILES; id++) {
   2074         BCM_IF_ERROR_RETURN(_bcm_fp_oam_pm_profile_delete(unit, id, 1));
   2075     }
   2076     return BCM_E_NONE;
   2077 }
   2078 
   2079 int
   2080 bcm_fp_oam_pm_profile_create(int unit, bcm_oam_pm_profile_info_t *profile_info)
   2081 {
   2082     _bcm_fp_oam_pm_profile_control_t *pmc = NULL;
   2083     bcm_oam_pm_profile_info_t        *profile_ptr = NULL;
   2084     int                               pm_profile_id = 0;
   2085 
   2086     pmc = pm_profile_control[unit];
   2087     if (!pmc) {
   2088         return BCM_E_INIT;
   2089     }
   2090 
   2091     if (_BCM_FP_OAM_PM_PROFILE_WITH_ID_FLAG_SET(profile_info)) {
   2092         if (!(_BCM_FP_OAM_PM_PROFILE_ID_VALID(profile_info->id))) {
   2093             return BCM_E_PARAM;
   2094         }
   2095     }
   2096 
   2097     if (_BCM_FP_OAM_PM_PROFILE_REPLACE_FLAG_SET(profile_info)) {
   2098         if (!(_BCM_FP_OAM_PM_PROFILE_WITH_ID_FLAG_SET(profile_info))) {
   2099             /* replace needs the id to be present */
   2100             return BCM_E_PARAM;
   2101         }
   2102 
   2103         if (!(_BCM_FP_OAM_PM_CTRL_PROFILE_IN_USE(pmc, profile_info->id))) {
   2104             /* Trying to replace a non-existent PM profile */
   2105             return BCM_E_NOT_FOUND;
   2106         }
   2107 
   2108         /* Delete the previous profile. */
   2109         BCM_IF_ERROR_RETURN(bcm_fp_oam_pm_profile_delete(unit,
   2110                                                          profile_info->id));
   2111     }
   2112 
   2113     if (_BCM_FP_OAM_PM_PROFILE_WITH_ID_FLAG_SET(profile_info)) {
   2114 
   2115         if (_BCM_FP_OAM_PM_CTRL_PROFILE_IN_USE(pmc, profile_info->id)) {
   2116             /* That profile id is in use. */
   2117             return BCM_E_EXISTS;
   2118         }
   2119 
   2120         /* Else use that as the id */
   2121         pm_profile_id = profile_info->id;
   2122     } else {
   2123         BCM_IF_ERROR_RETURN(_bcm_fp_oam_find_free_pm_profile_id(unit,
   2124                                                                 &pm_profile_id));
   2125     }
   2126 
   2127     /* Check if such a profile already exists. */
   2128     if (_bcm_fp_oam_pm_profile_exists(unit, profile_info)) {
   2129         return BCM_E_EXISTS;
   2130     }
   2131 
   2132     /* Copy it to local profile information */
   2133     profile_ptr = _BCM_FP_OAM_PM_CTRL_PROFILE_PTR(pmc, pm_profile_id);
   2134     sal_memcpy(profile_ptr, profile_info,
   2135                 sizeof(bcm_oam_pm_profile_info_t));
   2136 
   2137     /* Update the id in the profile */
   2138     profile_ptr->id = profile_info->id =  pm_profile_id;
   2139 
   2140 
   2141     /* Current flags have only transient meaning, so clear them */
   2142     profile_ptr->flags = 0;
   2143 
   2144     /* Mark that profile used */
   2145     _BCM_FP_OAM_SET_PM_CTRL_PROFILE_IN_USE(pmc, pm_profile_id);
   2146 
   2147 
   2148     return BCM_E_NONE;
   2149 }
   2150 
   2151 int
   2152 bcm_fp_oam_pm_profile_get(int unit, bcm_oam_pm_profile_info_t *profile_info)
   2153 {
   2154     _bcm_fp_oam_pm_profile_control_t *pmc;
   2155     int                               profile_id = profile_info->id;
   2156 
   2157     pmc = pm_profile_control[unit];
   2158     if (!pmc) {
   2159         return BCM_E_INIT;
   2160     }
   2161 
   2162     if (profile_info->id >= _BCM_OAM_MAX_PM_PROFILES) {
   2163         return BCM_E_PARAM;
   2164     }
   2165 
   2166     if (!(_BCM_FP_OAM_PM_PROFILE_ID_VALID(profile_id))) {
   2167         return BCM_E_PARAM;
   2168     }
   2169 
   2170     if (!(_BCM_FP_OAM_PM_CTRL_PROFILE_IN_USE(pmc, profile_id))) {
   2171         /* It is not in use. Return error */
   2172         return BCM_E_NOT_FOUND;
   2173     }
   2174 
   2175     /* Copy the profile to the profile structure passed */
   2176     sal_memcpy(profile_info, _BCM_FP_OAM_PM_CTRL_PROFILE_PTR(pmc, profile_id),
   2177                sizeof(bcm_oam_pm_profile_info_t));
   2178 
   2179     return BCM_E_NONE;
   2180 }
   2181 
   2182 int bcm_fp_oam_pm_profile_attach(int unit, bcm_oam_endpoint_t endpoint_id,
   2183                                  bcm_oam_pm_profile_t profile_id)
   2184 {
   2185     _bcm_fp_oam_pm_profile_control_t    *pmc = NULL;
   2186     bcm_oam_pm_profile_info_t           *profile_info = NULL;
   2187     bcm_oam_pm_profile_t                *profile = NULL;
   2188     _bcm_fp_oam_control_t               *oc = NULL;
   2189     shr_oam_pm_msg_ctrl_profile_attach_t msg;
   2190     uint8                                msg_class = 0;
   2191     uint16                               reply_len = 0;
   2192     uint8                                msg_subclass = 0;
   2193     uint8                                msg_reply_subclass = 0;
   2194     uint8                               *buffer = NULL, *buffer_ptr = NULL;
   2195     uint16                               buffer_len;
   2196 #if defined(INCLUDE_BHH)
   2197     _bhh_fp_oam_ep_data_t               *h_data_p = NULL;
   2198     int                                  bhh_pool_ep_idx = 0;
   2199 #endif /* INCLUDE_BHH */
   2200 #if defined(INCLUDE_MPLS_LM_DM)
   2201     _bcm_fp_oam_mpls_lm_dm_ep_data_t    *ep;
   2202     uint16                               idx;
   2203 #endif /* INCLUDE_MPLS_LM_DM */
   2204     int                                  ep_found = 0;
   2205     int                                  rv = BCM_E_NONE;
   2206 
   2207     pmc = pm_profile_control[unit];
   2208     if (!pmc) {
   2209         return BCM_E_INIT;
   2210     }
   2211 
   2212     if (!(_BCM_FP_OAM_PM_PROFILE_ID_VALID(profile_id))) {
   2213         return BCM_E_PARAM;
   2214     }
   2215 
   2216     /* Check profile id exists or not */
   2217     if (!(_BCM_FP_OAM_PM_CTRL_PROFILE_IN_USE(pmc, profile_id))) {
   2218         /* It is not in use. Return error */
   2219         return BCM_E_NOT_FOUND;
   2220     }
   2221 
   2222     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
   2223     _BCM_OAM_LOCK(oc);
   2224 
   2225 #if defined(INCLUDE_BHH)
   2226     if ((endpoint_id >= oc->bhh_base_endpoint_id) &&
   2227         (endpoint_id < (oc->bhh_base_endpoint_id + oc->bhh_endpoint_count))) {
   2228 
   2229         ep_found = 1;
   2230 
   2231         bhh_pool_ep_idx = BCM_OAM_BHH_GET_UKERNEL_EP(endpoint_id);
   2232         h_data_p =  &oc->bhh_ep_data[bhh_pool_ep_idx];
   2233 
   2234         if (0 == h_data_p->in_use) {
   2235             LOG_ERROR(BSL_LS_BCM_OAM,
   2236                       (BSL_META_U(unit,
   2237                                   "OAM(unit %d) Error: h_data_p not in use EP=%d\n"),
   2238                        unit, endpoint_id));
   2239             _BCM_OAM_UNLOCK(oc);
   2240             return (BCM_E_NOT_FOUND);
   2241         }
   2242 
   2243         /* Check if a profile id is already attached to this endpoint */
   2244         if (h_data_p->pm_profile_attached != _BCM_OAM_INVALID_INDEX) {
   2245             _BCM_OAM_UNLOCK(oc);
   2246             return BCM_E_EXISTS;
   2247         }
   2248 
   2249         /* Attach it to the endpoint */
   2250         h_data_p->pm_profile_attached = profile_id;
   2251         profile = &(h_data_p->pm_profile_attached);
   2252 
   2253         /* Send info to u-Kernel about the profile attached with the endpoint */
   2254         sal_memset(&msg, 0, sizeof(msg));
   2255         msg_class                  = MOS_MSG_CLASS_BHH;
   2256         msg_subclass               = MOS_MSG_SUBCLASS_BHH_PM_PROFILE_ATTACH;
   2257         msg_reply_subclass         = MOS_MSG_SUBCLASS_BHH_PM_PROFILE_ATTACH_REPLY;
   2258         msg.sess_id                = BCM_OAM_BHH_GET_UKERNEL_EP(endpoint_id);
   2259         buffer                     = oc->pm_bhh_dma_buffer;
   2260     }
   2261 #endif /* INCLUDE_BHH */
   2262 #if defined(INCLUDE_MPLS_LM_DM)
   2263     if(_MPLS_LM_DM_EP_ID_RANGE(endpoint_id)) {
   2264 
   2265         ep_found = 1;
   2266 
   2267         if (!oc->mpls_lm_dm_ukernel_ready) {
   2268             _BCM_OAM_UNLOCK(oc);
   2269             return BCM_E_INIT;
   2270         }
   2271         idx = _MPLS_LM_DM_EP_ID_TO_SESS_ID(endpoint_id);
   2272         ep = &(oc->mpls_lm_dm_ep_data[idx]);
   2273 
   2274         if (!ep->in_use) {
   2275             _BCM_OAM_UNLOCK(oc);
   2276             return BCM_E_NOT_FOUND;
   2277         }
   2278 
   2279         if (!(ep->flags & SHR_MPLS_LM_DM_FLAG_DELAY_ADDED)) {
   2280             _BCM_OAM_UNLOCK(oc);
   2281             return BCM_E_PARAM;
   2282         }
   2283 
   2284 
   2285         /* Check if a profile id is already attached to this endpoint */
   2286         if (ep->pm_profile != _BCM_OAM_INVALID_INDEX) {
   2287             _BCM_OAM_UNLOCK(oc);
   2288             return BCM_E_EXISTS;
   2289         }
   2290 
   2291         /* Attach it to the endpoint */
   2292         ep->pm_profile = profile_id;
   2293         profile = &(ep->pm_profile);
   2294 
   2295         /* Send info to u-Kernel about the profile attached with the endpoint */
   2296         sal_memset(&msg, 0, sizeof(msg));
   2297         msg_class          = MOS_MSG_CLASS_MPLS_LM_DM;
   2298         msg_subclass       = MOS_MSG_SUBCLASS_MPLS_LM_DM_PM_PROFILE_ATTACH;
   2299         msg_reply_subclass = MOS_MSG_SUBCLASS_MPLS_LM_DM_PM_PROFILE_ATTACH_REPLY;
   2300         msg.sess_id        = idx;
   2301         buffer             = oc->mpls_lm_dm_dma_buffer;
   2302     }
   2303 #endif /* INCLUDE_MPLS_LM_DM */
   2304 
   2305     if (!ep_found) {
   2306         _BCM_OAM_UNLOCK(oc);
   2307         return BCM_E_PARAM;
   2308     }
   2309 
   2310     profile_info = _BCM_FP_OAM_PM_CTRL_PROFILE_PTR(pmc, profile_id);
   2311 
   2312     msg.profile_id    = profile_id;
   2313     msg.profile_flags = profile_info->flags;
   2314     sal_memcpy(&(msg.profile_edges), &(profile_info->bin_edges),
   2315                (sizeof(uint32) * SHR_OAM_PM_MAX_PM_BIN_EDGES));
   2316 
   2317     buffer_ptr = shr_oam_pm_msg_ctrl_profile_attach_pack(buffer, &msg);
   2318     buffer_len = buffer_ptr - buffer;
   2319 
   2320 
   2321     rv = _bcm_fp_oam_pm_msg_send_receive(unit, msg_class, msg_subclass,
   2322                                          buffer_len, 0, msg_reply_subclass,
   2323                                          &reply_len);
   2324 
   2325     if(BCM_FAILURE(rv)) {
   2326         *profile = _BCM_OAM_INVALID_INDEX;
   2327         _BCM_OAM_UNLOCK(oc);
   2328         return BCM_E_INTERNAL;
   2329     }
   2330 
   2331     _BCM_OAM_UNLOCK(oc);
   2332     return BCM_E_NONE;
   2333 }
   2334 
   2335 int bcm_fp_oam_pm_profile_detach(int unit, bcm_oam_endpoint_t endpoint_id,
   2336                                  bcm_oam_pm_profile_t profile_id)
   2337 {
   2338     int                               rv = BCM_E_NONE;
   2339     _bcm_fp_oam_pm_profile_control_t *pmc = NULL;
   2340     _bcm_fp_oam_control_t            *oc = NULL;
   2341     uint8                             msg_class = 0;
   2342     uint16                            reply_len = 0;
   2343     uint8                             msg_subclass = 0;
   2344     uint8                             msg_reply_subclass = 0;
   2345     uint16                            sess_id = 0;
   2346     int                               ep_found = 0;
   2347     bcm_oam_pm_profile_t             *profile = NULL;
   2348 #if defined(INCLUDE_BHH)
   2349     _bhh_fp_oam_ep_data_t            *h_data_p = NULL;
   2350     int                               bhh_pool_ep_idx = 0;
   2351 #endif /* INCLUDE_BHH */
   2352 #if defined(INCLUDE_MPLS_LM_DM)
   2353     _bcm_fp_oam_mpls_lm_dm_ep_data_t  *ep;
   2354     uint16                             idx;
   2355 #endif /* INCLUDE_MPLS_LM_DM */
   2356 
   2357     pmc = pm_profile_control[unit];
   2358     if (!pmc) {
   2359         return BCM_E_INIT;
   2360     }
   2361 
   2362     if (!(_BCM_FP_OAM_PM_PROFILE_ID_VALID(profile_id))) {
   2363         return BCM_E_PARAM;
   2364     }
   2365 
   2366     /* Check profile id exists or not */
   2367     if (!(_BCM_FP_OAM_PM_CTRL_PROFILE_IN_USE(pmc, profile_id))) {
   2368         /* It is not in use. Return error */
   2369         return BCM_E_NOT_FOUND;
   2370     }
   2371 
   2372     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
   2373     _BCM_OAM_LOCK(oc);
   2374 
   2375 #if defined(INCLUDE_BHH)
   2376     if ((endpoint_id >= oc->bhh_base_endpoint_id) &&
   2377         (endpoint_id < (oc->bhh_base_endpoint_id + oc->bhh_endpoint_count))) {
   2378 
   2379         ep_found = 1;
   2380 
   2381         /* Validate endpoint index value. */
   2382         BCM_OAM_BHH_VALIDATE_EP(endpoint_id);
   2383 
   2384         bhh_pool_ep_idx = BCM_OAM_BHH_GET_UKERNEL_EP(endpoint_id);
   2385         h_data_p =  &oc->bhh_ep_data[bhh_pool_ep_idx];
   2386         profile = &(h_data_p->pm_profile_attached);
   2387 
   2388         if (0 == h_data_p->in_use) {
   2389             LOG_ERROR(BSL_LS_BCM_OAM,
   2390                       (BSL_META_U(unit,
   2391                                   "OAM(unit %d) Error: h_data_p not in use EP=%d\n"),
   2392                        unit, endpoint_id));
   2393             _BCM_OAM_UNLOCK(oc);
   2394             return (BCM_E_NOT_FOUND);
   2395         }
   2396 
   2397         /* Check if the passed profile id is the one that is attached */
   2398         if (profile_id != h_data_p->pm_profile_attached) {
   2399             _BCM_OAM_UNLOCK(oc);
   2400             return BCM_E_PARAM;
   2401         }
   2402 
   2403         msg_class          = MOS_MSG_CLASS_BHH;
   2404         msg_subclass       = MOS_MSG_SUBCLASS_BHH_PM_PROFILE_DETACH;
   2405         msg_reply_subclass = MOS_MSG_SUBCLASS_BHH_PM_PROFILE_DETACH_REPLY;
   2406         sess_id            = BCM_OAM_BHH_GET_UKERNEL_EP(endpoint_id);
   2407     }
   2408 #endif /* INCLUDE_BHH */
   2409 #if defined(INCLUDE_MPLS_LM_DM)
   2410     if(_MPLS_LM_DM_EP_ID_RANGE(endpoint_id)) {
   2411 
   2412         ep_found = 1;
   2413 
   2414         if (!oc->mpls_lm_dm_ukernel_ready) {
   2415             _BCM_OAM_UNLOCK(oc);
   2416             return BCM_E_INIT;
   2417         }
   2418         idx = _MPLS_LM_DM_EP_ID_TO_SESS_ID(endpoint_id);
   2419         ep = &(oc->mpls_lm_dm_ep_data[idx]);
   2420 
   2421         if (!ep->in_use) {
   2422             _BCM_OAM_UNLOCK(oc);
   2423             return BCM_E_NOT_FOUND;
   2424         }
   2425 
   2426 
   2427         /* Attach it to the endpoint */
   2428         profile = &(ep->pm_profile);
   2429 
   2430         /* Check if the passed profile id is the one that is attached */
   2431         if (profile_id != ep->pm_profile) {
   2432             _BCM_OAM_UNLOCK(oc);
   2433             return BCM_E_PARAM;
   2434         }
   2435 
   2436 
   2437         /* Send info to u-Kernel about the profile attached with the endpoint */
   2438         msg_class          = MOS_MSG_CLASS_MPLS_LM_DM;
   2439         msg_subclass       = MOS_MSG_SUBCLASS_MPLS_LM_DM_PM_PROFILE_DETACH;
   2440         msg_reply_subclass = MOS_MSG_SUBCLASS_MPLS_LM_DM_PM_PROFILE_DETACH_REPLY;
   2441         sess_id            = idx;
   2442     }
   2443 #endif /* INCLUDE_MPLS_LM_DM */
   2444 
   2445     if (!ep_found) {
   2446         _BCM_OAM_UNLOCK(oc);
   2447         return BCM_E_PARAM;
   2448     }
   2449 
   2450     rv = _bcm_fp_oam_pm_msg_send_receive(unit, msg_class, msg_subclass,
   2451                                          sess_id, profile_id, msg_reply_subclass,
   2452                                          &reply_len);
   2453     if(BCM_FAILURE(rv)) {
   2454         _BCM_OAM_UNLOCK(oc);
   2455         return BCM_E_INTERNAL;
   2456     }
   2457     /* Detach the profile from endpoint */
   2458     *profile = _BCM_OAM_INVALID_INDEX;
   2459 
   2460     _BCM_OAM_UNLOCK(oc);
   2461     return BCM_E_NONE;
   2462 }
   2463 
   2464 int bcm_fp_oam_pm_profile_traverse(int unit,
   2465                                    bcm_oam_pm_profile_traverse_cb cb,
   2466                                    void *user_data)
   2467 {
   2468     int                               rv = BCM_E_NONE;
   2469     bcm_oam_pm_profile_info_t        *profile_info = NULL;
   2470     _bcm_fp_oam_pm_profile_control_t *pmc = NULL;
   2471     int profile_id;
   2472 
   2473     /* Validate input parameter. */
   2474     if (NULL == cb) {
   2475         return (BCM_E_PARAM);
   2476     }
   2477     pmc = pm_profile_control[unit];
   2478     if (!pmc) {
   2479         return BCM_E_INIT;
   2480     }
   2481 
   2482     for (profile_id = 0; profile_id < _BCM_OAM_MAX_PM_PROFILES; profile_id++) {
   2483         /* Check profile id is in use or not */
   2484         if (!(_BCM_FP_OAM_PM_CTRL_PROFILE_IN_USE(pmc, profile_id))) {
   2485             /* Skip that profile id */
   2486             continue;
   2487         }
   2488         profile_info = _BCM_FP_OAM_PM_CTRL_PROFILE_PTR(pmc, profile_id);
   2489         rv = cb(unit, profile_info, user_data);
   2490         if (BCM_FAILURE(rv)) {
   2491             LOG_ERROR(BSL_LS_BCM_OAM,
   2492                       (BSL_META_U(unit,
   2493                                   "OAM(unit %d) Error: EP=%d callback "
   2494                                   "failed - %s.\n"),
   2495                        unit, profile_id, bcm_errmsg(rv)));
   2496             return (rv);
   2497         }
   2498     }
   2499     return (rv);
   2500 }
   2501 
   2502 void
   2503 _bcm_fp_oam_copy_stats_msg_to_stats_ptr(
   2504                                    shr_oam_pm_msg_ctrl_pm_stats_get_t *stats_msg,
   2505                                    bcm_oam_pm_stats_t *stats_ptr,
   2506                                    uint8 pm_stat_extra_elem_feature)
   2507 {
   2508     stats_ptr->far_loss_min  = stats_msg->far_loss_min;
   2509     stats_ptr->far_tx_min    = stats_msg->far_tx_min;
   2510     stats_ptr->far_loss_max  = stats_msg->far_loss_max;
   2511     stats_ptr->far_tx_max    = stats_msg->far_tx_max;
   2512     stats_ptr->far_loss      = stats_msg->far_loss;
   2513     stats_ptr->near_loss_min = stats_msg->near_loss_min;
   2514     stats_ptr->near_tx_min   = stats_msg->near_tx_min;
   2515     stats_ptr->near_loss_max = stats_msg->near_loss_max;
   2516     stats_ptr->near_tx_max   = stats_msg->near_tx_max;
   2517     stats_ptr->near_loss     = stats_msg->near_loss;
   2518     stats_ptr->lm_tx_count   = stats_msg->lm_tx_count;
   2519     stats_ptr->DM_min        = stats_msg->DM_min;
   2520     stats_ptr->DM_max        = stats_msg->DM_max;
   2521     if(stats_msg->dm_rx_count) {
   2522         stats_ptr->DM_avg = stats_msg->DM_avg/stats_msg->dm_rx_count;
   2523     }
   2524     stats_ptr->dm_tx_count   = stats_msg->dm_tx_count;
   2525     stats_ptr->profile_id    = stats_msg->profile_id;
   2526     sal_memcpy(&(stats_ptr->bin_counters), &(stats_msg->bin_counters),
   2527                sizeof(uint32) * (SHR_OAM_PM_MAX_PM_BIN_EDGES + 1));
   2528     if(pm_stat_extra_elem_feature) {
   2529         stats_ptr->lm_rx_count             = stats_msg->lm_rx_count;
   2530         stats_ptr->dm_rx_count             = stats_msg->dm_rx_count;
   2531         stats_ptr->far_total_tx_pkt_count  = stats_msg->far_total_tx_pkt_count;
   2532         stats_ptr->near_total_tx_pkt_count = stats_msg->near_total_tx_pkt_count;
   2533     }
   2534 
   2535     if (stats_msg->flags & SHR_OAM_PM_STATS_FLAG_COUNTER_ROLLOVER) {
   2536         stats_ptr->flags |= BCM_OAM_PM_STATS_PROCESSED_COUNTER_ROLLOVER;
   2537     }
   2538 }
   2539 
   2540 int bcm_fp_oam_pm_stats_get(int unit,
   2541                             bcm_oam_endpoint_t endpoint_id,
   2542                             bcm_oam_pm_stats_t *stats_ptr)
   2543 {
   2544     _bcm_fp_oam_pm_profile_control_t   *pmc = NULL;
   2545     _bcm_fp_oam_control_t              *oc = NULL;
   2546     shr_oam_pm_msg_ctrl_pm_stats_get_t  stats_msg;
   2547     int                                 rv = BCM_E_NONE;
   2548     uint16                              sess_id = 0;
   2549     uint8                               msg_class = 0;
   2550     uint16                              reply_len = 0;
   2551     uint8                               msg_subclass = 0;
   2552     uint8                               msg_reply_subclass = 0;
   2553     uint8                              *dma_buffer = NULL;
   2554     uint8                               pm_stat_extra_elem_feature = 0;
   2555     int                                 ep_found = 0;
   2556 #if defined(INCLUDE_BHH)
   2557     _bhh_fp_oam_ep_data_t              *h_data_p = NULL;
   2558     int                                 bhh_pool_ep_idx = 0;
   2559 #endif /* INCLUDE_BHH */
   2560 #if defined(INCLUDE_MPLS_LM_DM)
   2561     _bcm_fp_oam_mpls_lm_dm_ep_data_t  *ep;
   2562     uint16                             idx;
   2563 #endif /* INCLUDE_MPLS_LM_DM */
   2564 
   2565     pmc = pm_profile_control[unit];
   2566     if (!pmc) {
   2567         return BCM_E_INIT;
   2568     }
   2569 
   2570     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
   2571     _BCM_OAM_LOCK(oc);
   2572 
   2573 #if defined(INCLUDE_BHH)
   2574     if ((endpoint_id >= oc->bhh_base_endpoint_id) &&
   2575         (endpoint_id < (oc->bhh_base_endpoint_id + oc->bhh_endpoint_count))) {
   2576 
   2577         ep_found = 1;
   2578         /* Validate endpoint index value. */
   2579         BCM_OAM_BHH_VALIDATE_EP(endpoint_id);
   2580 
   2581         bhh_pool_ep_idx = BCM_OAM_BHH_GET_UKERNEL_EP(endpoint_id);
   2582         /* Check endpoint status. */
   2583         rv = shr_idxres_list_elem_state(oc->bhh_pool, bhh_pool_ep_idx);
   2584         if ((BCM_E_EXISTS != rv)) {
   2585             /* Endpoint not in use. */
   2586             LOG_ERROR(BSL_LS_BCM_OAM,
   2587                       (BSL_META_U(unit,
   2588                                   "OAM(unit %d) Error: Endpoint EP=%d %s.\n"),
   2589                        unit, endpoint_id, bcm_errmsg(rv)));
   2590             _BCM_OAM_UNLOCK(oc);
   2591             return (rv);
   2592         }
   2593 
   2594         h_data_p =  &oc->bhh_ep_data[bhh_pool_ep_idx];
   2595 
   2596         if (0 == h_data_p->in_use) {
   2597             LOG_ERROR(BSL_LS_BCM_OAM,
   2598                       (BSL_META_U(unit,
   2599                                   "OAM(unit %d) Error: h_data_p not in use EP=%d\n"),
   2600                        unit, endpoint_id));
   2601             _BCM_OAM_UNLOCK(oc);
   2602             return (BCM_E_INTERNAL);
   2603         }
   2604 
   2605         msg_class = MOS_MSG_CLASS_BHH;
   2606         msg_subclass = MOS_MSG_SUBCLASS_BHH_PM_STATS_GET;
   2607         msg_reply_subclass = MOS_MSG_SUBCLASS_BHH_PM_STATS_GET_REPLY;
   2608         sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(endpoint_id);
   2609         pm_stat_extra_elem_feature = BHH_UC_FEATURE_CHECK(
   2610                                                         BHH_PM_STAT_EXTRA_ELEM);
   2611         dma_buffer = _bcm_fp_oam_pm_dma_buffer_from_endpoint_type_get(unit,
   2612                                                                       h_data_p->type);
   2613     }
   2614 #endif /* INCLUDE_BHH */
   2615 #if defined(INCLUDE_MPLS_LM_DM)
   2616     if(_MPLS_LM_DM_EP_ID_RANGE(endpoint_id)) {
   2617         ep_found = 1;
   2618 
   2619         if (!oc->mpls_lm_dm_ukernel_ready) {
   2620             _BCM_OAM_UNLOCK(oc);
   2621             return BCM_E_INIT;
   2622         }
   2623         idx = _MPLS_LM_DM_EP_ID_TO_SESS_ID(endpoint_id);
   2624         ep = &(oc->mpls_lm_dm_ep_data[idx]);
   2625 
   2626         if (!ep->in_use) {
   2627             _BCM_OAM_UNLOCK(oc);
   2628             return BCM_E_NOT_FOUND;
   2629         }
   2630 
   2631         if (!(ep->flags & SHR_MPLS_LM_DM_FLAG_LOSS_ADDED) &&
   2632             !(ep->flags & SHR_MPLS_LM_DM_FLAG_DELAY_ADDED)) {
   2633             _BCM_OAM_UNLOCK(oc);
   2634             return BCM_E_NOT_FOUND;
   2635         }
   2636 
   2637         if (!_BCM_FP_OAM_PM_MPLS_LM_DM_DATA_COLLECTION_MODE_IS_PROCESSED(oc)) {
   2638             _BCM_OAM_UNLOCK(oc);
   2639             return BCM_E_NOT_FOUND;
   2640         }
   2641 
   2642         msg_class          = MOS_MSG_CLASS_MPLS_LM_DM;
   2643         msg_subclass       = MOS_MSG_SUBCLASS_MPLS_LM_DM_PM_STATS_GET;
   2644         msg_reply_subclass = MOS_MSG_SUBCLASS_MPLS_LM_DM_PM_STATS_GET_REPLY;
   2645         sess_id            = idx;
   2646         pm_stat_extra_elem_feature = MPLS_LM_DM_UC_FEATURE_CHECK(
   2647                                                   MPLS_LM_DM_PM_STAT_EXTRA_ELEM);
   2648         dma_buffer = oc->mpls_lm_dm_dma_buffer;
   2649     }
   2650 #endif /* INCLUDE_MPLS_LM_DM */
   2651 
   2652     if (!ep_found) {
   2653         _BCM_OAM_UNLOCK(oc);
   2654         return BCM_E_PARAM;
   2655     }
   2656 
   2657     /* Pass the buffer pointer in data and sess id in length fields.*/
   2658     rv = _bcm_fp_oam_pm_msg_send_receive(unit, msg_class,
   2659                                          msg_subclass,
   2660                                          sess_id, soc_cm_l2p(unit, dma_buffer),
   2661                                          msg_reply_subclass,
   2662                                          &reply_len);
   2663     if(BCM_FAILURE(rv) || reply_len == 0) {
   2664         _BCM_OAM_UNLOCK(oc);
   2665         return BCM_E_INTERNAL;
   2666     }
   2667 
   2668     shr_oam_pm_msg_ctrl_pm_stats_get_unpack(dma_buffer, &stats_msg,
   2669                                             pm_stat_extra_elem_feature);
   2670 
   2671     _bcm_fp_oam_copy_stats_msg_to_stats_ptr(&stats_msg, stats_ptr,
   2672                                             pm_stat_extra_elem_feature);
   2673 
   2674     _BCM_OAM_UNLOCK(oc);
   2675     return BCM_E_NONE;
   2676 }
   2677 
   2678 
   2679 int
   2680 bcm_fp_oam_pm_profile_attach_get(int unit,
   2681                                  bcm_oam_endpoint_t endpoint_id,
   2682                                  bcm_oam_pm_profile_t *profile_id)
   2683 {
   2684     _bcm_fp_oam_pm_profile_control_t *pmc = NULL;
   2685     _bcm_fp_oam_control_t            *oc = NULL;
   2686     int                               ep_found = 0;
   2687 #if defined(INCLUDE_BHH)
   2688     _bhh_fp_oam_ep_data_t            *h_data_p = NULL;
   2689     int                               bhh_pool_ep_idx = 0;
   2690     int                               rv = BCM_E_NONE;
   2691 #endif /* INCLUDE_BHH */
   2692 #if defined(INCLUDE_MPLS_LM_DM)
   2693     _bcm_fp_oam_mpls_lm_dm_ep_data_t  *ep;
   2694     uint16                             idx;
   2695 #endif /* INCLUDE_MPLS_LM_DM */
   2696 
   2697     pmc = pm_profile_control[unit];
   2698     if (!pmc) {
   2699         return BCM_E_INIT;
   2700     }
   2701 
   2702     /* Check profile id exists or not */
   2703     if (!(_BCM_FP_OAM_PM_CTRL_PROFILE_IN_USE(pmc, *profile_id))) {
   2704         /* It is not in use. Return error */
   2705         return BCM_E_PARAM;
   2706     }
   2707 
   2708 
   2709     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
   2710     _BCM_OAM_LOCK(oc);
   2711 
   2712 #if defined(INCLUDE_BHH)
   2713     if ((endpoint_id >= oc->bhh_base_endpoint_id) &&
   2714         (endpoint_id < (oc->bhh_base_endpoint_id + oc->bhh_endpoint_count))) {
   2715 
   2716         ep_found = 1;
   2717         /* Validate endpoint index value. */
   2718         BCM_OAM_BHH_VALIDATE_EP(endpoint_id);
   2719 
   2720         bhh_pool_ep_idx = BCM_OAM_BHH_GET_UKERNEL_EP(endpoint_id);
   2721         /* Check endpoint status. */
   2722         rv = shr_idxres_list_elem_state(oc->bhh_pool, bhh_pool_ep_idx);
   2723         if ((BCM_E_EXISTS != rv)) {
   2724             /* Endpoint not in use. */
   2725             LOG_ERROR(BSL_LS_BCM_OAM,
   2726                       (BSL_META_U(unit,
   2727                                   "OAM(unit %d) Error: Endpoint EP=%d %s.\n"),
   2728                        unit, endpoint_id, bcm_errmsg(rv)));
   2729             _BCM_OAM_UNLOCK(oc);
   2730             return (rv);
   2731         }
   2732         h_data_p =  &oc->bhh_ep_data[bhh_pool_ep_idx];
   2733 
   2734         if (0 == h_data_p->in_use) {
   2735             LOG_ERROR(BSL_LS_BCM_OAM,
   2736                       (BSL_META_U(unit,
   2737                                   "OAM(unit %d) Error: h_data_p not in use EP=%d\n"),
   2738                        unit, endpoint_id));
   2739             _BCM_OAM_UNLOCK(oc);
   2740             return (BCM_E_INTERNAL);
   2741         }
   2742         /* Get the attached profile */
   2743         *profile_id = h_data_p->pm_profile_attached;
   2744     }
   2745 #endif /* INCLUDE_BHH */
   2746 #if defined(INCLUDE_MPLS_LM_DM)
   2747     if(_MPLS_LM_DM_EP_ID_RANGE(endpoint_id)) {
   2748 
   2749         ep_found = 1;
   2750 
   2751         if (!oc->mpls_lm_dm_ukernel_ready) {
   2752             _BCM_OAM_UNLOCK(oc);
   2753             return BCM_E_INIT;
   2754         }
   2755         idx = _MPLS_LM_DM_EP_ID_TO_SESS_ID(endpoint_id);
   2756         ep = &(oc->mpls_lm_dm_ep_data[idx]);
   2757 
   2758         if (!ep->in_use) {
   2759             _BCM_OAM_UNLOCK(oc);
   2760             return BCM_E_NOT_FOUND;
   2761         }
   2762 
   2763         /* Check if a profile id is already attached to this endpoint */
   2764         if (ep->pm_profile == _BCM_OAM_INVALID_INDEX) {
   2765             _BCM_OAM_UNLOCK(oc);
   2766             return BCM_E_EXISTS;
   2767         }
   2768         /* Get the attached profile */
   2769         *profile_id = ep->pm_profile;
   2770     }
   2771 #endif /* INCLUDE_MPLS_LM_DM */
   2772 
   2773     if (!ep_found) {
   2774         _BCM_OAM_UNLOCK(oc);
   2775         return BCM_E_PARAM;
   2776     }
   2777     if (*profile_id == _BCM_OAM_INVALID_INDEX) {
   2778         _BCM_OAM_UNLOCK(oc);
   2779         return BCM_E_NOT_FOUND;
   2780     }
   2781 
   2782     _BCM_OAM_UNLOCK(oc);
   2783     return BCM_E_NONE;
   2784 }
   2785 
   2786 void
   2787 _bcm_fp_oam_write_dma_buffer_to_raw_buffer(int unit, uint8 *dma_buffer,
   2788                                         bcm_oam_pm_raw_data_t *raw_data, int write_index)
   2789 {
   2790     shr_oam_pm_msg_ctrl_raw_buffer_unpack(dma_buffer,
   2791      (shr_oam_pm_msg_ctrl_raw_buffer_t *)(&(raw_data->raw_buffer[write_index])));
   2792 }
   2793 
   2794 int _bcm_fp_oam_pm_raw_data_event_index_from_event_get(bcm_oam_event_type_t event_type)
   2795 {
   2796     switch (event_type) {
   2797 #if defined(INCLUDE_BHH)
   2798         case bcmOAMEventBHHRawData:
   2799             return _BCM_FP_OAM_PM_BHH_EVENT_IDX;
   2800             break;
   2801 #endif /* INCLUDE_BHH */
   2802 #if defined(INCLUDE_MPLS_LM_DM)
   2803         case bcmOAMEventMplsLmDmRawData:
   2804             return _BCM_FP_OAM_PM_MPLS_LM_DM_EVENT_IDX;
   2805             break;
   2806 #endif /* INCLUDE_MPLS_LM_DM */
   2807         default:
   2808             return -1;
   2809             break;
   2810     }
   2811     return -1;
   2812 }
   2813 
   2814 void _bcm_fp_oam_update_num_free_buffers(_bcm_fp_oam_control_t *oc,
   2815                                          int event_idx, int read_idx,
   2816                                          int write_idx, int last_op)
   2817 {
   2818     /* Normal case */
   2819     if (read_idx < write_idx) {
   2820         SET_NUM_FREE_BUFFERS(event_idx,
   2821                 (BCM_OAM_MAX_PM_BUFFERS - (write_idx - read_idx)));
   2822     } else if (read_idx > write_idx) {
   2823         /* rollover case */
   2824         SET_NUM_FREE_BUFFERS(event_idx,
   2825                 (read_idx - write_idx));
   2826     } else { /* read index = write index case */
   2827         if (last_op == 1) {
   2828             /* Last operation was write, means write idx has caught
   2829                up with read_idx.
   2830                Just decrement the number of buffers by 1.
   2831                Ideally this would mean the num of free buffers would
   2832                become zero */
   2833             DECR_NUM_FREE_BUFFERS(event_idx);
   2834         }  else if (last_op == 0) {
   2835             /* Last operation was read, means read idx has caught
   2836                up with write idx.
   2837                Just increment the number of buffers by 1.
   2838                Ideally this would mean the num of free buffers would
   2839                have become max. */
   2840             INCR_NUM_FREE_BUFFERS(event_idx);
   2841         }
   2842     }
   2843 }
   2844 
   2845 /* Returns 0 - Not updated or 1 - Updated */
   2846 int
   2847 _bcm_fp_oam_update_dma_buffer_into_raw_buffer(int unit,
   2848                                               bcm_oam_event_type_t event_type,
   2849                                               uint8 *dma_buffer,
   2850                                               bcm_oam_pm_raw_data_t *raw_data)
   2851 {
   2852     int rv = BCM_E_NONE;
   2853     int event_idx = -1;
   2854     _bcm_fp_oam_control_t *oc;
   2855     int read_idx = -1;
   2856     int write_idx = -1;
   2857 
   2858     /* Get OAM Control Structure. */
   2859     rv = _bcm_fp_oam_control_get(unit, &oc);
   2860     if (BCM_FAILURE(rv)) {
   2861         return FALSE;
   2862     }
   2863 
   2864     event_idx = _bcm_fp_oam_pm_raw_data_event_index_from_event_get(event_type);
   2865     if (event_idx == -1) {
   2866         return FALSE;
   2867     }
   2868 
   2869     if (NUM_FREE_BUFFERS(event_idx) > 0) {
   2870         PM_WRITE_DONE_INDEX(event_idx) = INCREMENT_PM_WRITE_DONE_INDEX
   2871                                                                   (event_idx);
   2872         /* Writing at the incremented index */
   2873         _bcm_fp_oam_write_dma_buffer_to_raw_buffer(unit, dma_buffer, raw_data,
   2874                 PM_WRITE_DONE_INDEX(event_idx));
   2875     } else {
   2876         /* There are no free buffers. Do not update */
   2877         return FALSE;
   2878     }
   2879     read_idx = PM_READ_DONE_INDEX(event_idx);
   2880     write_idx = PM_WRITE_DONE_INDEX(event_idx);
   2881 
   2882     /* 1 passed indicates last operation was write */
   2883     _bcm_fp_oam_update_num_free_buffers(oc, event_idx, read_idx, write_idx, 1);
   2884 
   2885     raw_data->read_index = PM_READ_DONE_INDEX(event_idx);
   2886     raw_data->write_index = PM_WRITE_DONE_INDEX(event_idx);
   2887 
   2888     return TRUE;
   2889 }
   2890 
   2891 int
   2892 bcm_fp_oam_pm_raw_data_read_done(int unit,
   2893                                   bcm_oam_event_types_t event_types,
   2894                                   uint32 read_index)
   2895 {
   2896     bcm_oam_event_type_t event_type;
   2897     _bcm_fp_oam_control_t *oc;
   2898     int event_idx = -1;
   2899 
   2900     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
   2901     /* Do sanity validation of event_types and read_index */
   2902     if (!(_BCM_FP_OAM_EVENT_TYPE_PM_EVENT(event_types))) {
   2903         return BCM_E_PARAM;
   2904     }
   2905 
   2906     if (!(VALID_PM_RAW_DATA_BUFFER_READ_WRITE_INDEX(read_index))) {
   2907         return BCM_E_PARAM;
   2908     }
   2909 
   2910     for (event_type = bcmOAMEventBHHRawData;
   2911          event_type <= bcmOAMEventMplsLmDmRawData; event_type++) {
   2912         if (BCM_OAM_EVENT_TYPE_GET(event_types, event_type)) {
   2913             event_idx = _bcm_fp_oam_pm_raw_data_event_index_from_event_get
   2914                                                                (event_type);
   2915             if (event_idx == -1) {
   2916                 return BCM_E_PARAM;
   2917             }
   2918             PM_READ_DONE_INDEX(event_idx) = read_index;
   2919             /* 0 passed indicates last operation was read */
   2920             _bcm_fp_oam_update_num_free_buffers(oc, event_idx, read_index,
   2921                                              PM_WRITE_DONE_INDEX(event_idx), 0);
   2922         }
   2923     }
   2924     return BCM_E_NONE;
   2925 }
   2926 
   2927 bcm_oam_pm_raw_data_t*
   2928 _bcm_fp_oam_pm_raw_data_info_get(int unit,
   2929                                  bcm_oam_event_type_t event_type)
   2930 {
   2931     int rv = BCM_E_NONE;
   2932     _bcm_fp_oam_control_t *oc;
   2933     bcm_oam_pm_raw_data_t *buffer = NULL;
   2934 
   2935     rv = _bcm_fp_oam_control_get(unit, &oc);
   2936     if (BCM_FAILURE(rv)) {
   2937         return NULL;
   2938     }
   2939     switch (event_type) {
   2940 #if defined(INCLUDE_BHH)
   2941         case bcmOAMEventBHHRawData:
   2942             buffer = &(oc->pm_bhh_raw_data_info);
   2943             break;
   2944 #endif /* INCLUDE_BHH */
   2945 #if defined(INCLUDE_MPLS_LM_DM)
   2946         case bcmOAMEventMplsLmDmRawData:
   2947             buffer = &(oc->pm_mpls_lm_dm_raw_data_info);
   2948             break;
   2949 #endif /* INCLUDE_MPLS_LM_DM */
   2950         default:
   2951             buffer = NULL;
   2952             break;
   2953     }
   2954     return buffer;
   2955 }
   2956 
   2957 STATIC void _bcm_fp_oam_pm_event_msg_handle(_bcm_fp_oam_control_t *oc,
   2958                                              mos_msg_data_t *event_msg)
   2959 {
   2960     bcm_oam_event_type_t event_type = 0;
   2961     _bcm_oam_pm_event_handler_t *pm_event_handler_p;
   2962     bcm_oam_pm_raw_data_t *raw_data = NULL;
   2963     uint8 *dma_buffer = NULL;
   2964     int is_updated = 0;
   2965 #if defined (INCLUDE_MPLS_LM_DM)
   2966     uint32       event_mask;
   2967     int          sess_id;
   2968     uint16       ep_id = 0;
   2969     bcm_oam_event_types_t events;
   2970     _bcm_oam_event_handler_t *event_handler_p;
   2971 #endif
   2972 
   2973 
   2974     switch (event_msg->s.mclass) {
   2975 #if defined(INCLUDE_BHH)
   2976         case MOS_MSG_CLASS_BHH_EVENT:
   2977             event_type = bcmOAMEventBHHRawData;
   2978             break;
   2979 #endif /* INCLUDE_BHH */
   2980 #if defined(INCLUDE_MPLS_LM_DM)
   2981        case MOS_MSG_CLASS_MPLS_LM_DM_EVENT:
   2982             event_mask = bcm_ntohl(event_msg->s.data);
   2983             if (event_mask & MPLS_LM_DM_BTE_EVENT_PM_STATS_COUNTER_ROLLOVER) {
   2984                 event_type = bcmOAMEventMplsLmDmPmCounterRollover;
   2985                 /* Get data from event message */
   2986                 sess_id = (int)bcm_ntohs(event_msg->s.len);
   2987                 ep_id = _MPLS_LM_DM_SESS_ID_TO_EP_ID(sess_id);
   2988                 /* Set events */
   2989                 sal_memset(&events, 0, sizeof(events));
   2990                 LOG_DEBUG(BSL_LS_BCM_OAM,
   2991                           (BSL_META_U(oc->unit,
   2992                            "****** OAM PM MPLS_LM_DM Counter Rollover ******\n")));
   2993                 if (oc->event_handler_cnt[bcmOAMEventMplsLmDmPmCounterRollover] > 0) {
   2994                     SHR_BITSET(events.w, bcmOAMEventMplsLmDmPmCounterRollover);
   2995                 }
   2996             } else {
   2997                 event_type = bcmOAMEventMplsLmDmRawData;
   2998             }
   2999            break;
   3000 #endif /* INCLUDE_MPLS_LM_DM */
   3001         default:
   3002             LOG_ERROR(BSL_LS_BCM_OAM,
   3003                     (BSL_META(
   3004                               "OAM(unit %d) Error: %s called"
   3005                               "for unknown protocol"
   3006                               "- %d.\n"),
   3007                      oc->unit, FUNCTION_NAME(), event_msg->s.mclass));
   3008             return;
   3009     }
   3010 
   3011     if (oc->event_handler_cnt[event_type] <= 0) {
   3012         LOG_ERROR(BSL_LS_BCM_OAM,
   3013                 (BSL_META(
   3014                           "OAM(unit %d) Error: Received notif for"
   3015                           "event without callback - %d.\n"),
   3016                  oc->unit, event_type));
   3017         return;
   3018     }
   3019 
   3020     /* Loop over registered callbacks
   3021      */
   3022     if (event_type == bcmOAMEventMplsLmDmPmCounterRollover) {
   3023 #if defined (INCLUDE_MPLS_LM_DM)
   3024         for (event_handler_p = oc->event_handler_list_p; event_handler_p != NULL;
   3025              event_handler_p = event_handler_p->next_p) {
   3026             if (SHR_BITGET(events.w, event_type)) {
   3027                 if (SHR_BITGET(event_handler_p->event_types.w, event_type)) {
   3028                     event_handler_p->cb(oc->unit,
   3029                                         0, event_type,
   3030                                         0,
   3031                                         ep_id,
   3032                                         event_handler_p->user_data);
   3033                 }
   3034             }
   3035         }
   3036 #endif
   3037     } else {
   3038         for (pm_event_handler_p = oc->pm_event_handler_list_p;
   3039                 pm_event_handler_p != NULL;
   3040                 pm_event_handler_p = pm_event_handler_p->next_p) {
   3041             if (SHR_BITGET(pm_event_handler_p->event_types.w,
   3042                         event_type)) {
   3043                 raw_data   = _bcm_fp_oam_pm_raw_data_info_get(oc->unit, event_type);
   3044                 dma_buffer = _bcm_fp_oam_pm_dma_buffer_get(oc->unit, event_type);
   3045                 if (!raw_data) {
   3046                     /* Should not happen. This would mean you have received
   3047                      * a PM event for which you have not allocated buffers
   3048                      * itself.
   3049                      */
   3050                     LOG_ERROR(BSL_LS_BCM_OAM,
   3051                             (BSL_META_U(oc->unit,
   3052                                         "OAM(unit %d) Error: Oam raw data get failed"
   3053                                         " event - %d.\n"), oc->unit, event_type));
   3054                     return;
   3055                 }
   3056                 is_updated = _bcm_fp_oam_update_dma_buffer_into_raw_buffer(oc->unit,
   3057                         event_type,
   3058                         dma_buffer,
   3059                         raw_data);
   3060                 if (is_updated) {
   3061                     pm_event_handler_p->cb(oc->unit,
   3062                             event_type,
   3063                             raw_data, /* The raw data */
   3064                             pm_event_handler_p->user_data);
   3065                 } else {
   3066                     /* Oops ! The event is lost ! */
   3067                     LOG_WARN(BSL_LS_BCM_OAM,
   3068                             (BSL_META_U(oc->unit,
   3069                                         "OAM(unit %d) Error: PM event missed "
   3070                                         "event - %d.\n"), oc->unit, event_type));
   3071                 }
   3072             }
   3073         }
   3074     }
   3075 }
   3076 
   3077 /*
   3078  * Function:
   3079  *     bcm_fp_oam_pm_event_register
   3080  * Purpose:
   3081  *     Register a callback for handling OAM PM events
   3082  * Parameters:
   3083  *     unit        - (IN) BCM device number
   3084  *     event_types - (IN) The set of OAM PM events for which the specified
   3085  *                        callback should be called.
   3086  *     cb          - (IN) A pointer to the callback function to call for
   3087  *                        the specified OAM PM events
   3088  *     user_data   - (IN) Pointer to user data to supply in the callback
   3089  * Returns:
   3090  *      BCM_E_XXX
   3091  */
   3092 int
   3093 bcm_fp_oam_pm_event_register(int unit, bcm_oam_event_types_t event_types,
   3094                              bcm_oam_pm_event_cb cb, void *user_data)
   3095 {
   3096     _bcm_fp_oam_control_t       *oc;
   3097     _bcm_oam_pm_event_handler_t *event_h_p;
   3098     _bcm_oam_pm_event_handler_t *prev_p = NULL;
   3099     int                          rv;             /* Operation return status. */
   3100     uint16                       reply_len = 0;
   3101     uint8                        msg_class = 0;
   3102     uint8                        msg_subclass = 0;
   3103     uint8                        msg_reply_subclass = 0;
   3104     uint8                       *dma_buffer = NULL;
   3105 
   3106     /* Validate event callback input parameter. */
   3107     if (NULL == cb) {
   3108         return (BCM_E_PARAM);
   3109     }
   3110 
   3111     /* Validate the event type to be of PM event type */
   3112     if (!(_BCM_FP_OAM_EVENT_TYPE_PM_EVENT(event_types))) {
   3113         return (BCM_E_PARAM);
   3114     }
   3115 
   3116     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
   3117     _BCM_OAM_LOCK(oc);
   3118 
   3119     for (event_h_p = oc->pm_event_handler_list_p; event_h_p != NULL;
   3120          event_h_p = event_h_p->next_p) {
   3121         if (event_h_p->cb == cb) {
   3122             break;
   3123         }
   3124         prev_p = event_h_p;
   3125     }
   3126 
   3127     if (NULL == event_h_p) {
   3128 
   3129         _BCM_OAM_ALLOC(event_h_p, _bcm_oam_pm_event_handler_t,
   3130                        sizeof(_bcm_oam_pm_event_handler_t), "OAM event handler");
   3131 
   3132         if (NULL == event_h_p) {
   3133             LOG_ERROR(BSL_LS_BCM_OAM,
   3134                       (BSL_META_U(unit,
   3135                                   "OAM(unit %d) Error: Event handler alloc failed -"
   3136                                    " %s.\n"), unit, bcm_errmsg(BCM_E_MEMORY)));
   3137             _BCM_OAM_UNLOCK(oc);
   3138             return (BCM_E_MEMORY);
   3139         }
   3140 
   3141         event_h_p->next_p = NULL;
   3142         event_h_p->cb = cb;
   3143 
   3144         SHR_BITCLR_RANGE(event_h_p->event_types.w, 0, bcmOAMEventCount);
   3145         if (prev_p != NULL) {
   3146             prev_p->next_p = event_h_p;
   3147         } else {
   3148             oc->pm_event_handler_list_p = event_h_p;
   3149         }
   3150     }
   3151 
   3152 #if defined(INCLUDE_BHH)
   3153     if (SHR_BITGET(event_types.w, bcmOAMEventBHHRawData)) {
   3154         if (!SHR_BITGET(event_h_p->event_types.w, bcmOAMEventBHHRawData)) {
   3155             /* Add this event to the registered events list. */
   3156             SHR_BITSET(event_h_p->event_types.w, bcmOAMEventBHHRawData);
   3157             msg_class          = MOS_MSG_CLASS_BHH;
   3158             msg_subclass       = MOS_MSG_SUBCLASS_BHH_PM_RAW_DATA_EVENT_SET;
   3159             msg_reply_subclass =
   3160                          MOS_MSG_SUBCLASS_BHH_PM_RAW_DATA_EVENT_SET_REPLY;
   3161             dma_buffer = oc->pm_bhh_dma_buffer;
   3162             rv = _bcm_fp_oam_pm_msg_send_receive(unit, msg_class,
   3163                                                  msg_subclass,
   3164                                                  0, soc_cm_l2p(unit, dma_buffer),
   3165                                                  msg_reply_subclass,
   3166                                                  &reply_len);
   3167             if(BCM_FAILURE(rv)) {
   3168                 _BCM_OAM_UNLOCK(oc);
   3169                 return BCM_E_INTERNAL;
   3170             }
   3171         }
   3172         oc->event_handler_cnt[bcmOAMEventBHHRawData]++;
   3173     }
   3174 #endif /* INCLUDE_BHH */
   3175 
   3176 #if defined(INCLUDE_MPLS_LM_DM)
   3177     if (oc->mpls_lm_dm_ukernel_ready) {
   3178         if (SHR_BITGET(event_types.w, bcmOAMEventMplsLmDmRawData)) {
   3179             if (!SHR_BITGET(event_h_p->event_types.w, bcmOAMEventMplsLmDmRawData)) {
   3180                 /* Add this event to the registered events list. */
   3181                 SHR_BITSET(event_h_p->event_types.w, bcmOAMEventMplsLmDmRawData);
   3182                 msg_class   = MOS_MSG_CLASS_MPLS_LM_DM;
   3183                 msg_subclass = MOS_MSG_SUBCLASS_MPLS_LM_DM_PM_RAW_DATA_EVENT_SET;
   3184                 msg_reply_subclass =
   3185                     MOS_MSG_SUBCLASS_MPLS_LM_DM_PM_RAW_DATA_EVENT_SET_REPLY;
   3186                 dma_buffer = oc->mpls_lm_dm_dma_buffer;
   3187 
   3188                 rv = _bcm_fp_oam_pm_msg_send_receive(unit, msg_class,
   3189                                                      msg_subclass,
   3190                                                      0, soc_cm_l2p(unit,
   3191                                                                    dma_buffer),
   3192                                                      msg_reply_subclass,
   3193                                                      &reply_len);
   3194                 if(BCM_FAILURE(rv)) {
   3195                     _BCM_OAM_UNLOCK(oc);
   3196                     return BCM_E_INTERNAL;
   3197                 }
   3198             }
   3199             oc->event_handler_cnt[bcmOAMEventMplsLmDmRawData]++;
   3200         }
   3201     }
   3202 #endif /* INCLUDE_MPLS_LM_DM */
   3203 
   3204 
   3205 
   3206     event_h_p->user_data = user_data;
   3207 
   3208     _BCM_OAM_UNLOCK(oc);
   3209     return (BCM_E_NONE);
   3210 }
   3211 
   3212 /*
   3213  * Function:
   3214  *     bcm_fp_oam_pm_event_unregister
   3215  * Purpose:
   3216  *     Remove a registered event from the event handler list.
   3217  * Parameters:
   3218  *     unit        - (IN) BCM device number
   3219  *     event_types - (IN) The set of OAM PM events for which the specified
   3220  *                        callback should not be called
   3221  *     cb          - (IN) A pointer to the callback function to unregister
   3222  *                        from the specified OAM PM events
   3223  * Returns:
   3224  *      BCM_E_XXX
   3225  */
   3226 int
   3227 bcm_fp_oam_pm_event_unregister(int unit, bcm_oam_event_types_t event_types,
   3228                              bcm_oam_pm_event_cb cb)
   3229 {
   3230     _bcm_fp_oam_control_t       *oc;
   3231     _bcm_oam_pm_event_handler_t *event_h_p;
   3232     _bcm_oam_pm_event_handler_t *prev_p = NULL;
   3233     bcm_oam_event_type_t         e_type;
   3234     int                          rv; /* Operation return status. */
   3235     uint8                        msg_class = 0;
   3236     uint16                       reply_len = 0;
   3237     uint8                        msg_subclass = 0;
   3238     uint8                        msg_reply_subclass = 0;
   3239 
   3240     /* Validate event callback input parameter. */
   3241     if (NULL == cb) {
   3242         return (BCM_E_PARAM);
   3243     }
   3244 
   3245     /* Validate the event type to be of PM event type */
   3246     if (!_BCM_FP_OAM_EVENT_TYPE_PM_EVENT(event_types)) {
   3247         return (BCM_E_PARAM);
   3248     }
   3249 
   3250     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
   3251     _BCM_OAM_LOCK(oc);
   3252 
   3253     for (event_h_p = oc->pm_event_handler_list_p; event_h_p != NULL;
   3254          event_h_p = event_h_p->next_p) {
   3255         if (event_h_p->cb == cb) {
   3256             break;
   3257         }
   3258         prev_p = event_h_p;
   3259     }
   3260     if (NULL == event_h_p) {
   3261         _BCM_OAM_UNLOCK(oc);
   3262         return (BCM_E_NOT_FOUND);
   3263     }
   3264 
   3265 #if defined(INCLUDE_BHH)
   3266     e_type = bcmOAMEventBHHRawData;
   3267     if (SHR_BITGET(event_types.w, e_type)) {
   3268         if ((oc->event_handler_cnt[e_type] > 0)
   3269                 && SHR_BITGET(event_h_p->event_types.w, e_type)) {
   3270 
   3271             /* Remove this event from the registered events list. */
   3272             SHR_BITCLR(event_h_p->event_types.w, e_type);
   3273 
   3274             oc->event_handler_cnt[e_type] -= 1;
   3275 
   3276             if (oc->event_handler_cnt[e_type] == 0) {
   3277                 /* There are no event handlers for this event type
   3278                  * Send msg to uKernel to stop notifying this event.
   3279                  */
   3280                 if (e_type == bcmOAMEventBHHRawData) {
   3281                     msg_class  = MOS_MSG_CLASS_BHH;
   3282                     msg_subclass =
   3283                         MOS_MSG_SUBCLASS_BHH_PM_RAW_DATA_EVENT_UNSET;
   3284                     msg_reply_subclass =
   3285                         MOS_MSG_SUBCLASS_BHH_PM_RAW_DATA_EVENT_UNSET_REPLY;
   3286                 }
   3287                 rv = _bcm_fp_oam_pm_msg_send_receive
   3288                     (unit, msg_class,
   3289                      msg_subclass,
   3290                      0, 0,
   3291                      msg_reply_subclass,
   3292                      &reply_len);
   3293                 if(BCM_FAILURE(rv)) {
   3294                     _BCM_OAM_UNLOCK(oc);
   3295                     return BCM_E_INTERNAL;
   3296                 }
   3297             }
   3298         }
   3299     }
   3300 #endif /* INCLUDE_BHH */
   3301 
   3302 #if defined(INCLUDE_MPLS_LM_DM)
   3303     e_type = bcmOAMEventMplsLmDmRawData;
   3304     if (SHR_BITGET(event_types.w, e_type)) {
   3305         if ((oc->event_handler_cnt[e_type] > 0)
   3306                 && SHR_BITGET(event_h_p->event_types.w, e_type)) {
   3307 
   3308             /* Remove this event from the registered events list. */
   3309             SHR_BITCLR(event_h_p->event_types.w, e_type);
   3310 
   3311             oc->event_handler_cnt[e_type] -= 1;
   3312 
   3313             if (oc->event_handler_cnt[e_type] == 0) {
   3314                 /* There are no event handlers for this event type
   3315                  * Send msg to uKernel to stop notifying this event.
   3316                  */
   3317                 msg_class  = MOS_MSG_CLASS_MPLS_LM_DM;
   3318                 msg_subclass =
   3319                     MOS_MSG_SUBCLASS_MPLS_LM_DM_PM_RAW_DATA_EVENT_UNSET;
   3320                 msg_reply_subclass =
   3321                     MOS_MSG_SUBCLASS_MPLS_LM_DM_PM_RAW_DATA_EVENT_UNSET_REPLY;
   3322 
   3323                 rv = _bcm_fp_oam_pm_msg_send_receive(unit, msg_class,
   3324                                                      msg_subclass,
   3325                                                      0, 0,
   3326                                                      msg_reply_subclass,
   3327                                                      &reply_len);
   3328                 if(BCM_FAILURE(rv)) {
   3329                     _BCM_OAM_UNLOCK(oc);
   3330                     return BCM_E_INTERNAL;
   3331                 }
   3332             }
   3333         }
   3334     }
   3335 #endif /* INCLUDE_MPLS_LM_DM */
   3336 
   3337     if (!_BCM_FP_OAM_EVENT_TYPE_PM_EVENT(event_h_p->event_types)) {
   3338         /* No more PM events for this callback registered
   3339            Delete the node. */
   3340         if (NULL != prev_p) {
   3341             prev_p->next_p = event_h_p->next_p;
   3342 
   3343         } else {
   3344             oc->pm_event_handler_list_p = event_h_p->next_p;
   3345         }
   3346         sal_free(event_h_p);
   3347     }
   3348 
   3349     _BCM_OAM_UNLOCK(oc);
   3350     return (BCM_E_NONE);
   3351 }
   3352 
   3353 #if defined(INCLUDE_MPLS_LM_DM)
   3354 /*
   3355  * Function:
   3356  *      _bcm_fp_oam_mpls_lm_dm_pm_callback_thread_func
   3357  * Purpose:
   3358  *      Thread to listen for event messages MPLS LM/DM uC for PM events.
   3359  * Parameters:
   3360  *      oc - Pointer to oam control structures.
   3361  *      events - the set of events that we are listening.
   3362  * Returns:
   3363  *      None
   3364  */
   3365 STATIC void
   3366 _bcm_fp_oam_mpls_lm_dm_pm_callback_thread_func(_bcm_fp_oam_control_t *oc,
   3367                                                bcm_oam_event_types_t event_types)
   3368 {
   3369     int            rv;
   3370     mos_msg_data_t event_msg;
   3371 
   3372     if (!(BCM_OAM_EVENT_TYPE_GET(event_types, bcmOAMEventMplsLmDmRawData) ||
   3373           BCM_OAM_EVENT_TYPE_GET(event_types, bcmOAMEventMplsLmDmPmCounterRollover))) {
   3374         /* No other event is currently handled here. return. */
   3375         LOG_ERROR(BSL_LS_BCM_OAM,
   3376                 (BSL_META_U(oc->unit,
   3377                             "OAM(unit %d) Error: %s called for unknown "
   3378                             "event.\n"), oc->unit, FUNCTION_NAME()));
   3379         return;
   3380     }
   3381 
   3382     while (1) {
   3383         /* Wait on notifications from uController */
   3384         rv = soc_cmic_uc_msg_receive(oc->unit, oc->mpls_lm_dm_uc_num,
   3385                                      MOS_MSG_CLASS_MPLS_LM_DM_EVENT,
   3386                                      &event_msg,
   3387                                      sal_sem_FOREVER);
   3388 
   3389         if (BCM_FAILURE(rv)) {
   3390             break;  /*  Thread exit */
   3391         } else {
   3392             if (event_msg.s.subclass == _MPLS_LM_DM_EVENT_OAM_PM_EVENT) {
   3393                 _bcm_fp_oam_pm_event_msg_handle(oc, &event_msg);
   3394             } else {
   3395                 LOG_ERROR(BSL_LS_BCM_OAM,
   3396                         (BSL_META(
   3397                                   "OAM(unit %d) Error: Unknown PM event"
   3398                                   "- %d.\n"),
   3399                          oc->unit, event_msg.s.subclass));
   3400             }
   3401         }
   3402     }
   3403 
   3404     oc->mpls_lm_dm_pm_event_thread_id = NULL;
   3405     sal_thread_exit(0);
   3406 }
   3407 
   3408 STATIC void
   3409 _bcm_fp_oam_mpls_lm_dm_pm_thread(void *param)
   3410 {
   3411     bcm_oam_event_types_t event_types = {{0}};
   3412     BCM_OAM_EVENT_TYPE_SET(event_types, bcmOAMEventMplsLmDmRawData);
   3413     BCM_OAM_EVENT_TYPE_SET(event_types, bcmOAMEventMplsLmDmPmCounterRollover);
   3414 
   3415     _bcm_fp_oam_mpls_lm_dm_pm_callback_thread_func((_bcm_fp_oam_control_t *)param,
   3416                                                     event_types);
   3417 }
   3418 #endif /* INCLUDE_MPLS_LM_DM */
   3419 
   3420 
   3421 #endif /* INCLUDE_BHH || INCLUDE_MPLS_LM_DM */
   3422 /*******************************************************************************/
   3423 /* PM routines for BHH & MPLS LM/DM app start                                  */
   3424 /*******************************************************************************/
   3425 
   3426 
   3427 /*******************************************************************************/
   3428 /* BHH Embedded App supporting functions Start */
   3429 /*******************************************************************************/
   3430 #if defined (INCLUDE_BHH)
   3431 /*
   3432  * Function:
   3433  *      _bcm_fp_oam_bhh_callback_thread
   3434  * Purpose:
   3435  *      Thread to listen for event messages from uController.
   3436  * Parameters:
   3437  *      param - Pointer to OAM info structure.
   3438  * Returns:
   3439  *      None
   3440  */
   3441 STATIC void
   3442 _bcm_fp_oam_bhh_callback_thread(void *param)
   3443 {
   3444     int rv;
   3445     _bcm_fp_oam_control_t *oc = (_bcm_fp_oam_control_t *)param;
   3446     bcm_oam_event_types_t events;
   3447     bcm_oam_event_type_t event_type;
   3448     bhh_msg_event_t event_msg;
   3449     int sess_id;
   3450     uint32 event_mask;
   3451     _bcm_oam_event_handler_t *event_handler_p;
   3452     _bhh_fp_oam_ep_data_t *h_data_p;
   3453     int ep_id = 0;
   3454     char thread_name[SAL_THREAD_NAME_MAX_LEN];
   3455     uint8 msg_subclass = 0;
   3456 
   3457     thread_name[0] = 0;
   3458     sal_thread_name(oc->event_thread_id, thread_name, sizeof (thread_name));
   3459 
   3460     while (1) {
   3461         /* Wait on notifications from uController */
   3462         rv = soc_cmic_uc_msg_receive(oc->unit, oc->bhh_uc_num,
   3463                                      MOS_MSG_CLASS_BHH_EVENT, &event_msg,
   3464                                      sal_sem_FOREVER);
   3465         if (BCM_FAILURE(rv)) {
   3466             break;  /*  Thread exit */
   3467         }
   3468 
   3469         /* Get data from event message */
   3470         sess_id = (int)bcm_ntohs(event_msg.s.len);
   3471         ep_id = BCM_OAM_BHH_GET_SDK_EP(sess_id);
   3472 
   3473         msg_subclass = event_msg.s.subclass;
   3474         if (msg_subclass == _BHH_EVENT_OAM_PM_EVENT) {
   3475             /* Call PM message handling function and continue */
   3476             _bcm_fp_oam_pm_event_msg_handle(oc, &event_msg);
   3477             continue;
   3478         }
   3479         if (sess_id < 0 ||
   3480             sess_id >= oc->bhh_endpoint_count) {
   3481             LOG_CLI((BSL_META_U(oc->unit,
   3482                                 "%s: Invalid sess_id:%d \n"), FUNCTION_NAME(), sess_id));
   3483             continue;
   3484         }
   3485 
   3486         /* Check endpoint status. */
   3487         rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id);
   3488         if ((BCM_E_EXISTS != rv)) {
   3489             /* Endpoint not in use. */
   3490             LOG_ERROR(BSL_LS_BCM_OAM,
   3491                       (BSL_META("OAM(unit %d) Error: Endpoint EP=%d %s.\n"),
   3492                        oc->unit, ep_id, bcm_errmsg(rv)));
   3493             continue;
   3494         }
   3495         h_data_p = &oc->bhh_ep_data[sess_id];
   3496         event_mask = bcm_ntohl(event_msg.s.data);
   3497 
   3498         /* Set events */
   3499         sal_memset(&events, 0, sizeof(events));
   3500 
   3501         if (event_mask & BHH_BTE_EVENT_LB_TIMEOUT) {
   3502             LOG_DEBUG(BSL_LS_BCM_OAM,
   3503                       (BSL_META_U(oc->unit,
   3504                                 "****** OAM BHH LB Timeout ******\n")));
   3505 
   3506             if (oc->event_handler_cnt[bcmOAMEventBHHLBTimeout] > 0) {
   3507                 SHR_BITSET(events.w, bcmOAMEventBHHLBTimeout);
   3508             }
   3509         }
   3510         if (event_mask & BHH_BTE_EVENT_LB_DISCOVERY_UPDATE) {
   3511             LOG_DEBUG(BSL_LS_BCM_OAM,
   3512                       (BSL_META_U(oc->unit,
   3513                                "****** OAM BHH LB Discovery Update ******\n")));
   3514             if (oc->event_handler_cnt[bcmOAMEventBHHLBDiscoveryUpdate] > 0) {
   3515                 SHR_BITSET(events.w, bcmOAMEventBHHLBDiscoveryUpdate);
   3516             }
   3517         }
   3518         if (event_mask & BHH_BTE_EVENT_CCM_TIMEOUT) {
   3519             LOG_DEBUG(BSL_LS_BCM_OAM,
   3520                       (BSL_META_U(oc->unit,
   3521                                 "****** OAM BHH CCM Timeout ******\n")));
   3522             if (oc->event_handler_cnt[bcmOAMEventBHHCCMTimeout] > 0) {
   3523                 SHR_BITSET(events.w, bcmOAMEventBHHCCMTimeout);
   3524             }
   3525         }
   3526         if (event_mask & BHH_BTE_EVENT_CCM_TIMEOUT_CLEAR) {
   3527             LOG_DEBUG(BSL_LS_BCM_OAM,
   3528                       (BSL_META_U(oc->unit,
   3529                                 "****** OAM BHH CCM Timeout Clear ******\n")));
   3530             if (oc->event_handler_cnt[bcmOAMEventBHHCCMTimeoutClear] > 0) {
   3531                 SHR_BITSET(events.w, bcmOAMEventBHHCCMTimeoutClear);
   3532             }
   3533         }
   3534         if (event_mask & BHH_BTE_EVENT_STATE) {
   3535             LOG_DEBUG(BSL_LS_BCM_OAM,
   3536                       (BSL_META_U(oc->unit,
   3537                                 "****** OAM BHH State ******\n")));
   3538             if (oc->event_handler_cnt[bcmOAMEventBHHCCMState] > 0) {
   3539                 SHR_BITSET(events.w, bcmOAMEventBHHCCMState);
   3540             }
   3541         }
   3542         if (event_mask & BHH_BTE_EVENT_CCM_RDI) {
   3543             LOG_DEBUG(BSL_LS_BCM_OAM,
   3544                       (BSL_META_U(oc->unit,
   3545                                   "****** OAM BHH CCM RDI ******\n")));
   3546             if (oc->event_handler_cnt[bcmOAMEventBHHCCMRdi] > 0) {
   3547                 SHR_BITSET(events.w, bcmOAMEventBHHCCMRdi);
   3548             }
   3549         }
   3550         if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_LEVEL) {
   3551             LOG_DEBUG(BSL_LS_BCM_OAM,
   3552                       (BSL_META_U(oc->unit,
   3553                             "****** OAM BHH CCM  Unknown MEG LEVEL ******\n")));
   3554             if (oc->event_handler_cnt[bcmOAMEventBHHCCMUnknownMegLevel] > 0) {
   3555                 SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownMegLevel);
   3556             }
   3557         }
   3558         if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_ID) {
   3559             LOG_DEBUG(BSL_LS_BCM_OAM,
   3560                       (BSL_META_U(oc->unit,
   3561                                "****** OAM BHH CCM  Unknown MEG ID ******\n")));
   3562             if (oc->event_handler_cnt[bcmOAMEventBHHCCMUnknownMegId] > 0) {
   3563                 SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownMegId);
   3564             }
   3565         }
   3566         if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_MEP_ID) {
   3567             LOG_DEBUG(BSL_LS_BCM_OAM,
   3568                       (BSL_META_U(oc->unit,
   3569                                 "****** OAM BHH CCM  Unknown MEP ID ******\n")));
   3570             if (oc->event_handler_cnt[bcmOAMEventBHHCCMUnknownMepId] > 0) {
   3571                 SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownMepId);
   3572             }
   3573         }
   3574         if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_PERIOD) {
   3575             LOG_DEBUG(BSL_LS_BCM_OAM,
   3576                       (BSL_META_U(oc->unit,
   3577                                 "****** OAM BHH CCM  Unknown Period ******\n")));
   3578             if (oc->event_handler_cnt[bcmOAMEventBHHCCMUnknownPeriod] > 0) {
   3579                 SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownPeriod);
   3580             }
   3581         }
   3582         if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_PRIORITY) {
   3583             LOG_DEBUG(BSL_LS_BCM_OAM,
   3584                       (BSL_META_U(oc->unit,
   3585                               "****** OAM BHH CCM  Unknown Priority ******\n")));
   3586             if (oc->event_handler_cnt[bcmOAMEventBHHCCMUnknownPriority] > 0) {
   3587                 SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownPriority);
   3588             }
   3589         }
   3590         if (event_mask & BHH_BTE_EVENT_CCM_RDI_CLEAR) {
   3591             LOG_DEBUG(BSL_LS_BCM_OAM,
   3592                       (BSL_META_U(oc->unit,
   3593                                   "****** OAM BHH CCM  RDI Clear ******\n")));
   3594             if (oc->event_handler_cnt[bcmOAMEventBHHCCMRdiClear] > 0) {
   3595                 SHR_BITSET(events.w, bcmOAMEventBHHCCMRdiClear);
   3596             }
   3597         }
   3598         if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_LEVEL_CLEAR) {
   3599             LOG_DEBUG(BSL_LS_BCM_OAM,
   3600                       (BSL_META_U(oc->unit,
   3601                        "****** OAM BHH CCM  Unknown MEG Level Clear ******\n")));
   3602             if (oc->event_handler_cnt[bcmOAMEventBHHCCMUnknownMegLevelClear] > 0) {
   3603                 SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownMegLevelClear);
   3604             }
   3605         }
   3606         if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_ID_CLEAR) {
   3607             LOG_DEBUG(BSL_LS_BCM_OAM,
   3608                       (BSL_META_U(oc->unit,
   3609                           "****** OAM BHH CCM  Unknown MEG ID Clear ******\n")));
   3610             if (oc->event_handler_cnt[bcmOAMEventBHHCCMUnknownMegIdClear] > 0) {
   3611                 SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownMegIdClear);
   3612             }
   3613         }
   3614         if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_MEP_ID_CLEAR) {
   3615             LOG_DEBUG(BSL_LS_BCM_OAM,
   3616                       (BSL_META_U(oc->unit,
   3617                           "****** OAM BHH CCM  Unknown MEP ID Clear ******\n")));
   3618             if (oc->event_handler_cnt[bcmOAMEventBHHCCMUnknownMepIdClear] > 0) {
   3619                 SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownMepIdClear);
   3620             }
   3621         }
   3622         if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_PERIOD_CLEAR) {
   3623             LOG_DEBUG(BSL_LS_BCM_OAM,
   3624                       (BSL_META_U(oc->unit,
   3625                           "****** OAM BHH CCM  Unknown Period Clear ******\n")));
   3626             if (oc->event_handler_cnt[bcmOAMEventBHHCCMUnknownPeriodClear] > 0) {
   3627                 SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownPeriodClear);
   3628             }
   3629         }
   3630         if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_PRIORITY_CLEAR) {
   3631             LOG_DEBUG(BSL_LS_BCM_OAM,
   3632                       (BSL_META_U(oc->unit,
   3633                         "****** OAM BHH CCM  Unknown Priority Clear ******\n")));
   3634             if (oc->event_handler_cnt[bcmOAMEventBHHCCMUnknownPriorityClear] > 0) {
   3635                 SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownPriorityClear);
   3636             }
   3637         }
   3638         if (event_mask & BHH_BTE_EVENT_PM_STATS_COUNTER_ROLLOVER) {
   3639             LOG_DEBUG(BSL_LS_BCM_OAM,
   3640                     (BSL_META_U(oc->unit,
   3641                                 "****** OAM PM BHH Counter Rollover ******\n")));
   3642 
   3643             if (oc->event_handler_cnt[bcmOAMEventBhhPmCounterRollover] > 0) {
   3644                 SHR_BITSET(events.w, bcmOAMEventBhhPmCounterRollover);
   3645             }
   3646         }
   3647         if (event_mask & BHH_BTE_EVENT_CSF_LOS) {
   3648             LOG_DEBUG(BSL_LS_BCM_OAM,
   3649                       (BSL_META_U(oc->unit,
   3650                                   "****** OAM BHH CSF LOS ******\n")));
   3651 
   3652             if (oc->event_handler_cnt[bcmOAMEventCsfLos] > 0) {
   3653                 SHR_BITSET(events.w, bcmOAMEventCsfLos);
   3654             }
   3655         }
   3656         if (event_mask & BHH_BTE_EVENT_CSF_FDI) {
   3657             LOG_DEBUG(BSL_LS_BCM_OAM,
   3658                       (BSL_META_U(oc->unit,
   3659                                   "****** OAM BHH CSF FDI ******\n")));
   3660 
   3661             if (oc->event_handler_cnt[bcmOAMEventCsfFdi] > 0) {
   3662                 SHR_BITSET(events.w, bcmOAMEventCsfFdi);
   3663             }
   3664         }
   3665         if (event_mask & BHH_BTE_EVENT_CSF_RDI) {
   3666             LOG_DEBUG(BSL_LS_BCM_OAM,
   3667                       (BSL_META_U(oc->unit,
   3668                                   "****** OAM BHH CSF RDI ******\n")));
   3669 
   3670             if (oc->event_handler_cnt[bcmOAMEventCsfRdi] > 0) {
   3671                 SHR_BITSET(events.w, bcmOAMEventCsfRdi);
   3672             }
   3673         }
   3674         if (event_mask & BHH_BTE_EVENT_CSF_DCI) {
   3675             LOG_DEBUG(BSL_LS_BCM_OAM,
   3676                       (BSL_META_U(oc->unit,
   3677                                   "****** OAM BHH CSF DCI ******\n")));
   3678 
   3679             if (oc->event_handler_cnt[bcmOAMEventCsfDci] > 0) {
   3680                 SHR_BITSET(events.w, bcmOAMEventCsfDci);
   3681             }
   3682         }
   3683         /* Loop over registered callbacks,
   3684          * If any match the events field, then invoke
   3685          */
   3686         for (event_handler_p = oc->event_handler_list_p;
   3687              event_handler_p != NULL;
   3688              event_handler_p = event_handler_p->next_p) {
   3689             for (event_type = bcmOAMEventBHHLBTimeout; event_type < bcmOAMEventCount; ++event_type) {
   3690                 if (SHR_BITGET(events.w, event_type)) {
   3691                     if (SHR_BITGET(event_handler_p->event_types.w,
   3692                                    event_type)) {
   3693                         event_handler_p->cb(oc->unit,
   3694                                         0,
   3695                                         event_type,
   3696                                         h_data_p->group_index, /* Group index */
   3697                                         ep_id, /* Endpoint index */
   3698                                         event_handler_p->user_data);
   3699                     }
   3700                 }
   3701             }
   3702         }
   3703     }
   3704 
   3705     oc->bhh_event_thread_id   = NULL;
   3706     LOG_VERBOSE(BSL_LS_BCM_OAM,
   3707               (BSL_META_U(oc->unit,
   3708                           "Thread Exit:%s\n"), thread_name));
   3709     sal_thread_exit(0);
   3710 }
   3711 
   3712 STATIC uint8 *
   3713 _bcm_fp_oam_ach_header_pack(uint8 *buffer, _ach_header_t *ach)
   3714 {
   3715     uint32  tmp;
   3716 
   3717     tmp = ((ach->f_nibble & 0xf) << 28) | ((ach->version & 0xf) << 24) |
   3718         (ach->reserved << 16) | ach->channel_type;
   3719 
   3720     _BHH_ENCAP_PACK_U32(buffer, tmp);
   3721 
   3722     return (buffer);
   3723 }
   3724 
   3725 STATIC uint8 *
   3726 _bcm_fp_oam_mpls_label_pack(uint8 *buffer, _mpls_label_t *mpls)
   3727 {
   3728     uint32  tmp;
   3729     
   3730     tmp = ((mpls->label & 0xfffff) << 12) | ((mpls->exp & 0x7) << 9) |
   3731         ((mpls->s & 0x1) << 8) | mpls->ttl;
   3732     _BHH_ENCAP_PACK_U32(buffer, tmp);
   3733 
   3734     return (buffer);
   3735 }
   3736 
   3737 STATIC uint8 *
   3738 _bcm_fp_oam_mpls_label_unpack(uint8 *buffer, _mpls_label_t *mpls)
   3739 {
   3740      uint32  tmp;
   3741 
   3742     _SHR_UNPACK_U32(buffer, tmp);
   3743     mpls->label = (tmp >> 12) & 0xfffff;
   3744     mpls->exp = (tmp >> 9) & 0x7;
   3745     mpls->s = (tmp >> 8) & 0x1;
   3746     mpls->ttl = tmp & 0xffff;
   3747 
   3748     return (buffer);
   3749 }
   3750 
   3751 STATIC uint8 *
   3752 _bcm_fp_oam_l2_header_pack(bcm_oam_endpoint_type_t type,
   3753                                 uint8 *buffer, _l2_header_t *l2)
   3754 {
   3755     uint32  tmp;
   3756     int     i;
   3757 
   3758     for (i = 0; i < _BHH_MAC_ADDR_LENGTH; i++) {
   3759         _BHH_ENCAP_PACK_U8(buffer, l2->dst_mac[i]);
   3760     }
   3761 
   3762     for (i = 0; i < _BHH_MAC_ADDR_LENGTH; i++) {
   3763         _BHH_ENCAP_PACK_U8(buffer, l2->src_mac[i]);
   3764     }
   3765 
   3766     /* Vlan Tag tpid = 0 indicates untagged */
   3767     if (0 != l2->vlan_tag.tpid) {
   3768         tmp =  (l2->vlan_tag.tpid            << 16) |
   3769               ((l2->vlan_tag.tci.prio & 0x7) << 13) |
   3770               ((l2->vlan_tag.tci.cfi  & 0x1) << 12) |
   3771                (l2->vlan_tag.tci.vid  & 0xfff);
   3772         _BHH_ENCAP_PACK_U32(buffer, tmp);
   3773     }
   3774     /*Inner Vlan Tag inner_tpid = 0 indicates single tag  */
   3775     if (0 != l2->vlan_tag_inner.tpid) {
   3776         tmp = (l2->vlan_tag_inner.tpid            << 16) |
   3777              ((l2->vlan_tag_inner.tci.prio & 0x7) << 13) |
   3778              ((l2->vlan_tag_inner.tci.cfi  & 0x1) << 12) |
   3779               (l2->vlan_tag_inner.tci.vid  & 0xfff);
   3780         _BHH_ENCAP_PACK_U32(buffer, tmp);
   3781     }
   3782     _BHH_ENCAP_PACK_U16(buffer, l2->etype);
   3783 
   3784     return (buffer);
   3785 }
   3786 
   3787 /*
   3788  * Function:
   3789  *      bcm_fp_oam_mpls_tp_channel_type_tx_get
   3790  * Purpose:
   3791  *      Get MPLS TP(BHH) ACH Channel type
   3792  * Parameters:
   3793  *      unit                (IN)  BCM device number
   3794  *      channel_type        (IN)  Channel type is ignored in XGS devices
   3795  *      Value               (OUT) User define MPLS TP(BHH) ACH channel type
   3796  *
   3797  * Returns:
   3798  *      BCM_E_NONE          No error
   3799  *      BCM_E_XXXX          Error
   3800  */
   3801 int
   3802 bcm_fp_oam_mpls_tp_channel_type_tx_get(int unit,
   3803                                        bcm_oam_mpls_tp_channel_type_t channel_type,
   3804                                        int *value)
   3805 {
   3806     *value = fp_oam_mpls_tp_ach_channel_type;
   3807     return BCM_E_NONE;
   3808 }
   3809 
   3810 /*
   3811  * Function:
   3812  *      bcm_fp_oam_mpls_tp_channel_type_tx_set
   3813  * Purpose:
   3814  *      Update MPLS TP(BHH) ACH Channel type with user defined value
   3815  * Parameters:
   3816  *      unit                (IN) BCM device number
   3817  *      channel_type        (IN) Channel type is ignored in XGS devices
   3818  *      Value               (IN) User define MPLS TP(BHH) ACH channel type
   3819  *
   3820  * Returns:
   3821  *      BCM_E_NONE          No error
   3822  *      BCM_E_XXXX          Error
   3823  */
   3824 int
   3825 bcm_fp_oam_mpls_tp_channel_type_tx_set(int unit,
   3826                                        bcm_oam_mpls_tp_channel_type_t channel_type,
   3827                                        int value)
   3828 {
   3829     uint8               *buffer, *buffer_ptr;
   3830     uint16              buffer_len, reply_len;
   3831     int                 rv = BCM_E_NONE;
   3832     uint32              *msg;
   3833     _bcm_fp_oam_control_t *oc = NULL;           /* OAM control structure */
   3834 
   3835     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
   3836     _BCM_OAM_LOCK(oc);
   3837 
   3838     if (oc->ukernel_not_ready) {
   3839         _BCM_OAM_UNLOCK(oc);
   3840         return BCM_E_INIT;
   3841     }
   3842 
   3843     if ((value != SHR_BHH_ACH_CHANNEL_TYPE) &&
   3844         (value != SHR_BHH_ACH_CHANNEL_TYPE_1)) {
   3845         _BCM_OAM_UNLOCK(oc);
   3846         return BCM_E_CONFIG;
   3847     }
   3848 
   3849     fp_oam_mpls_tp_ach_channel_type = value;
   3850     msg = (uint32 *)&fp_oam_mpls_tp_ach_channel_type;
   3851 
   3852     /* Pack control message data into DMA buffer */
   3853     buffer     = oc->dma_buffer;
   3854     buffer_ptr = bhh_sdk_msg_ctrl_ach_channel_type_msg_pack(buffer, msg);
   3855     buffer_len = buffer_ptr - buffer;
   3856 
   3857     rv = _bcm_fp_oam_msg_send_receive(
   3858                                       unit,
   3859                                       MOS_MSG_CLASS_BHH,
   3860                                       MOS_MSG_SUBCLASS_BHH_ACH_CHANNEL_TYPE,
   3861                                       buffer_len, 0,
   3862                                       MOS_MSG_SUBCLASS_BHH_ACH_CHANNEL_TYPE_REPLY,
   3863                                       &reply_len);
   3864 
   3865     if (BCM_FAILURE(rv)) {
   3866         _BCM_OAM_UNLOCK(oc);
   3867         return (rv);
   3868     }
   3869 
   3870     _BCM_OAM_UNLOCK(oc);
   3871     return BCM_E_NONE;
   3872 }
   3873 
   3874 
   3875 STATIC int
   3876 _bcm_fp_oam_ach_header_get(uint32 packet_flags, _ach_header_t *ach)
   3877 {
   3878     sal_memset(ach, 0, sizeof(*ach));
   3879     
   3880     ach->f_nibble = SHR_BHH_ACH_FIRST_NIBBLE;
   3881     ach->version  = SHR_BHH_ACH_VERSION;
   3882     ach->reserved = 0;
   3883     ach->channel_type = fp_oam_mpls_tp_ach_channel_type;
   3884 
   3885     return (BCM_E_NONE);
   3886 }
   3887     
   3888 STATIC int
   3889 _bcm_fp_oam_mpls_label_get(uint32 label, uint8 exp, uint8 s, uint8 ttl,
   3890                            _mpls_label_t *mpls)
   3891 {
   3892     sal_memset(mpls, 0, sizeof(*mpls));
   3893         
   3894     mpls->label = label;
   3895     mpls->exp   = exp & 0x07;
   3896     mpls->s     = s;
   3897     if(ttl){
   3898         mpls->ttl   = ttl;
   3899     } else {
   3900         mpls->ttl   = _BHH_MPLS_DFLT_TTL;
   3901     }
   3902  
   3903     return (BCM_E_NONE);
   3904 }
   3905 
   3906 STATIC int
   3907 _bcm_fp_oam_mpls_gal_label_get(_mpls_label_t *mpls, uint8 oam_exp)
   3908 {
   3909     return _bcm_fp_oam_mpls_label_get(SHR_BHH_MPLS_GAL_LABEL,
   3910                                       oam_exp, 1, 1, mpls);
   3911 }
   3912 
   3913 STATIC int
   3914 _bcm_fp_oam_mpls_labels_get(int unit, _bhh_fp_oam_ep_data_t *h_data_p,
   3915                                 uint32 packet_flags,
   3916                                 int max_count, 
   3917                                 _mpls_label_t *pw_label,
   3918                                 _mpls_label_t *mpls,
   3919                                 int *mpls_count, bcm_if_t *l3_intf_id, uint8 oam_exp,
   3920                                 uint8 oam_ttl)
   3921 {
   3922     int count = 0;
   3923     bcm_l3_egress_t l3_egress;
   3924     bcm_mpls_port_t mpls_port;
   3925     bcm_mpls_egress_label_t label_array[_BHH_FP_OAM_MPLS_MAX_LABELS];
   3926     bcm_mpls_egress_label_t tmp_label;
   3927     int label_count;
   3928     int i = 0;
   3929 
   3930      /* Get L3 objects */
   3931     bcm_l3_egress_t_init(&l3_egress);
   3932     if (BCM_FAILURE(bcm_esw_l3_egress_get(unit, h_data_p->egress_if, &l3_egress))) {
   3933         return (BCM_E_PARAM);
   3934     }
   3935 
   3936     /* Look for a tunnel associated with this interface */
   3937     if (BCM_SUCCESS
   3938         (bcm_esw_mpls_tunnel_initiator_get(unit, l3_egress.intf,
   3939                                            _BHH_FP_OAM_MPLS_MAX_LABELS,
   3940                                            label_array, &label_count))) {
   3941         /* We need to sawp the labels configured in tunnel initiator as
   3942            it returns labels in reverse order than how it should be in pkt */
   3943         for (i=0; i<(label_count/2); i++) {
   3944             sal_memcpy(&tmp_label, &label_array[i], sizeof(tmp_label));
   3945             sal_memcpy(&label_array[i], &label_array[label_count - 1 - i],
   3946                        sizeof(tmp_label));
   3947             sal_memcpy(&label_array[label_count - 1 - i], &tmp_label,
   3948                        sizeof(tmp_label));
   3949         }
   3950 
   3951         /* Add VRL Label */
   3952         if (BHH_EP_LSP_TYPE(h_data_p)) {
   3953             if ( (l3_egress.mpls_label != BCM_MPLS_LABEL_INVALID) &&
   3954                  (label_count < _BHH_FP_OAM_MPLS_MAX_LABELS) ) {
   3955                 label_array[label_count].label = l3_egress.mpls_label;
   3956                 label_array[label_count].exp = l3_egress.mpls_exp;
   3957                 label_array[label_count].ttl = l3_egress.mpls_ttl;
   3958                 label_count++;
   3959             }
   3960         }
   3961         /* Traverse through Label stack and match on control label, this
   3962            label should be the one just above GAL in the label stack, any
   3963            following labels should not be added */
   3964         for (i=0;  i < label_count; i++) {
   3965             if (label_array[i].label == h_data_p->egr_label) {
   3966                 /* Set the intended msg type EXP for control Label */
   3967                 label_array[i].exp = oam_exp;
   3968                 if (soc_property_get(unit, spn_MPLS_OAM_EGRESS_LABEL_TTL, 0) &&
   3969                     oam_ttl) {
   3970                     label_array[i].ttl = oam_ttl;
   3971                 }
   3972                 label_count = i;
   3973                 _bcm_fp_oam_mpls_label_get(label_array[i].label,
   3974                         label_array[i].exp,
   3975                         0,
   3976                         label_array[i].ttl,
   3977                         &mpls[count++]);
   3978                 break;
   3979             }
   3980             _bcm_fp_oam_mpls_label_get(label_array[i].label,
   3981                     label_array[i].exp,
   3982                     0,
   3983                     label_array[i].ttl,
   3984                     &mpls[count++]);
   3985         }
   3986     }
   3987 
   3988         /* MPLS Router Alert */
   3989     if (packet_flags & _BHH_ENCAP_PKT_MPLS_ROUTER_ALERT) {
   3990         /* Ignore overrun error as RAL is only added for PW MEPs and so overrun
   3991          * condition will not exist.
   3992          */
   3993         /* coverity[overrun-local] */
   3994         mpls[count].label = SHR_BHH_MPLS_ROUTER_ALERT_LABEL;
   3995         mpls[count].exp = 0;
   3996         mpls[count].s = 0;
   3997         mpls[count].ttl = _BHH_MPLS_DFLT_TTL;
   3998         count++;
   3999     }
   4000 
   4001     /* Use GPORT to resolve interface */
   4002     if (BCM_GPORT_IS_MPLS_PORT(h_data_p->gport)) {
   4003         /* Get mpls port and label info */
   4004         bcm_mpls_port_t_init(&mpls_port);
   4005         mpls_port.mpls_port_id = h_data_p->gport;
   4006         if (BCM_FAILURE(bcm_esw_mpls_port_get(unit, h_data_p->vpn,
   4007                                               &mpls_port))) {
   4008             return (BCM_E_PARAM);
   4009         }
   4010         if (h_data_p->type == bcmOAMEndpointTypeBHHMPLSVccv &&
   4011             h_data_p->vccv_type == bcmOamBhhVccvTtl) {
   4012             mpls_port.egress_label.ttl = 0x1;
   4013         }
   4014         if (h_data_p->egr_label == mpls_port.egress_label.label) {
   4015             mpls_port.egress_label.exp = oam_exp;
   4016             if (soc_property_get(unit, spn_MPLS_OAM_EGRESS_LABEL_TTL, 0) &&
   4017                 oam_ttl) {
   4018                 mpls_port.egress_label.ttl = oam_ttl;
   4019             }
   4020         }
   4021 
   4022         _bcm_fp_oam_mpls_label_get(mpls_port.egress_label.label,
   4023                                    mpls_port.egress_label.exp,
   4024                                    0,
   4025                                    mpls_port.egress_label.ttl,
   4026                                    &mpls[count++]);
   4027     }
   4028 
   4029 
   4030     /* Set Bottom of Stack if there is no GAL label */
   4031     if (!(packet_flags & _BHH_ENCAP_PKT_GAL)) {
   4032         mpls[count-1].s = 1;
   4033     }
   4034 
   4035     *mpls_count = count;
   4036 
   4037     return (BCM_E_NONE);
   4038 
   4039 }
   4040 
   4041 STATIC int
   4042 _bcm_fp_oam_l2_header_get(int unit, _bhh_fp_oam_ep_data_t *h_data_p,
   4043                                 bcm_port_t port, uint16 etype,
   4044                                 _l2_header_t *l2, uint8 *lm_pdu_counter_offset)
   4045 {
   4046     uint16 tpid;
   4047     bcm_l3_egress_t l3_egress;
   4048     bcm_l3_intf_t l3_intf;
   4049     bcm_vlan_control_vlan_t vc;
   4050     int tpid_select;
   4051     bcm_pbmp_t pbmp, ubmp;
   4052 
   4053     sal_memset(l2, 0, sizeof(*l2));
   4054 
   4055     if (!BHH_EP_MPLS_SECTION_TYPE(h_data_p)) {
   4056         /* Get L3 interfaces */
   4057         bcm_l3_egress_t_init(&l3_egress);
   4058         bcm_l3_intf_t_init(&l3_intf);
   4059 
   4060         if (BCM_FAILURE
   4061                 (bcm_esw_l3_egress_get(unit, h_data_p->egress_if, &l3_egress))) {
   4062             return (BCM_E_PARAM);
   4063         }
   4064 
   4065         l3_intf.l3a_intf_id = l3_egress.intf;
   4066         if (BCM_FAILURE(bcm_esw_l3_intf_get(unit, &l3_intf))) {
   4067             return (BCM_E_PARAM);
   4068         }
   4069 
   4070         /* Get TPID */
   4071         BCM_IF_ERROR_RETURN(
   4072                        bcm_esw_vlan_control_port_get(unit,
   4073                                                      port,
   4074                                                      bcmVlanPortOuterTpidSelect,
   4075                                                      &tpid_select));
   4076         if (tpid_select == BCM_PORT_OUTER_TPID) {
   4077             BCM_IF_ERROR_RETURN(bcm_esw_port_tpid_get(unit, port, &tpid));
   4078         } else {
   4079             BCM_IF_ERROR_RETURN(
   4080                      bcm_esw_vlan_control_vlan_get(unit, l3_intf.l3a_vid, &vc));
   4081             tpid = vc.outer_tpid;
   4082         }
   4083 
   4084         sal_memcpy(l2->dst_mac, l3_egress.mac_addr, _BHH_MAC_ADDR_LENGTH);
   4085         sal_memcpy(l2->src_mac, l3_intf.l3a_mac_addr, _BHH_MAC_ADDR_LENGTH);
   4086         *lm_pdu_counter_offset += 2*_BHH_MAC_ADDR_LENGTH;
   4087         l2->vlan_tag.tpid     = tpid;
   4088         l2->vlan_tag.tci.prio = h_data_p->vlan_pri;
   4089         l2->vlan_tag.tci.cfi  = 0;
   4090         l2->vlan_tag.tci.vid  = l3_intf.l3a_vid;
   4091         *lm_pdu_counter_offset += 4;
   4092 
   4093         BCM_IF_ERROR_RETURN(bcm_esw_vlan_port_get(unit,
   4094                                                   l2->vlan_tag.tci.vid,
   4095                                                   &pbmp,
   4096                                                   &ubmp));
   4097         if (BCM_PBMP_MEMBER(ubmp, port)) {
   4098             l2->vlan_tag.tpid = 0;  /* Set to 0 to indicate untagged */
   4099         }
   4100 
   4101         if (l3_intf.l3a_inner_vlan != 0) {
   4102             BCM_IF_ERROR_RETURN(bcm_esw_port_inner_tpid_get(unit, port, &tpid));
   4103             l2->vlan_tag_inner.tpid     = tpid;
   4104             l2->vlan_tag_inner.tci.prio = h_data_p->inner_vlan_pri;
   4105             l2->vlan_tag_inner.tci.cfi  = 0;
   4106             l2->vlan_tag_inner.tci.vid  = l3_intf.l3a_inner_vlan;
   4107             *lm_pdu_counter_offset += 4;
   4108         }
   4109     }else {
   4110         sal_memcpy(l2->dst_mac, h_data_p->dst_mac_address, _BHH_MAC_ADDR_LENGTH);
   4111         sal_memcpy(l2->src_mac, h_data_p->src_mac_address, _BHH_MAC_ADDR_LENGTH);
   4112         *lm_pdu_counter_offset += 2*_BHH_MAC_ADDR_LENGTH;
   4113         if((h_data_p->type == bcmOAMEndpointTypeBhhSectionOuterVlan) ||
   4114            (h_data_p->type == bcmOAMEndpointTypeBhhSectionInnervlan) ||
   4115            (h_data_p->type == bcmOAMEndpointTypeBhhSectionOuterPlusInnerVlan)){
   4116             if (h_data_p->vlan != 0) {
   4117                 l2->vlan_tag.tpid     = h_data_p->outer_tpid;
   4118                 l2->vlan_tag.tci.prio = h_data_p->vlan_pri;
   4119                 l2->vlan_tag.tci.cfi  = 0;
   4120                 l2->vlan_tag.tci.vid  = h_data_p->vlan;
   4121                 *lm_pdu_counter_offset += 4;
   4122             }
   4123         }
   4124         if((h_data_p->type == bcmOAMEndpointTypeBhhSectionInnervlan) ||
   4125            (h_data_p->type == bcmOAMEndpointTypeBhhSectionOuterPlusInnerVlan)){
   4126             l2->vlan_tag_inner.tpid     = h_data_p->inner_tpid;
   4127             l2->vlan_tag_inner.tci.prio = h_data_p->inner_vlan_pri;
   4128             l2->vlan_tag_inner.tci.cfi  = 0;
   4129             l2->vlan_tag_inner.tci.vid  = h_data_p->inner_vlan;
   4130             *lm_pdu_counter_offset += 4;
   4131         }
   4132         etype = SHR_BHH_L2_ETYPE_MPLS_UCAST;
   4133     }
   4134     l2->etype             = etype;
   4135     *lm_pdu_counter_offset += 2;
   4136 
   4137     return (BCM_E_NONE);
   4138 }
   4139 
   4140 /*
   4141  * Function:
   4142  *      _bcm_fp_oam_encap_data_dump
   4143  * Purpose:
   4144  *      Dumps buffer contents.
   4145  * Parameters:
   4146  *      buffer  - (IN) Buffer to dump data.
   4147  *      length  - (IN) Length of buffer.
   4148  * Returns:
   4149  *      None
   4150  */
   4151 void
   4152 _bcm_fp_oam_encap_data_dump(uint8 *buffer, int length)
   4153 {   
   4154     int i;
   4155     
   4156     LOG_CLI((BSL_META("\nBHH encapsulation (length=%d):\n"), length));
   4157     
   4158     for (i = 0; i < length; i++) { 
   4159         if ((i % 16) == 0) {
   4160             LOG_CLI((BSL_META("\n")));
   4161         }
   4162         LOG_CLI((BSL_META(" %02x"), buffer[i]));
   4163     }
   4164     
   4165     LOG_CLI((BSL_META("\n")));
   4166     return;
   4167 }   
   4168 
   4169 /*
   4170  * Function:
   4171  *      _bcm_fp_oam_olp_tx_header_create
   4172  * Purpose:
   4173  *      Adds OLP Tx header packet to encapsulation.
   4174  * Parameters:
   4175  *      unit            - (IN) Unit number.
   4176  *      mod             - (IN) module Id.
   4177  *      port_id         - (IN) port Id.
   4178  *      ts_mode         - (IN) Timestamp type for DM PDU.
   4179  *      lm_pdu_counter_offset - (IN) Counter offset in LM PDU.
   4180  *      encap_data      - (OUT) Buffer returning MPLS OAM encapsulation.
   4181  *      encap_length    - (OUT) Buffer length which contains 
   4182  *                              MPLS OAM encapsulation length.
   4183  *      int_pri         - (IN) INT_PRI of OAM message.
   4184  * Returns:
   4185  *      BCM_E_XXX
   4186  * Notes:
   4187  *      The returning MPLS OAM encapsulation buffer includes 
   4188  *      OLP TX header.
   4189  */
   4190 
   4191 STATIC int
   4192 _bcm_fp_oam_olp_tx_header_create(int unit,
   4193                                  bcm_module_t mod, bcm_port_t port_id,
   4194                                  uint8 counter_size,
   4195                                  uint32  *counter_base_id,
   4196                                  uint32  *counter_offset,
   4197                                  int     *counter_action,
   4198                                  uint32  *counter_byte_offset,
   4199                                  uint8   ts_mode,
   4200                                  uint8 lm_pdu_counter_offset,
   4201                                  uint8  *encap_data,
   4202                                  uint16 *encap_length,
   4203                                  bcm_cos_t int_pri)
   4204 {
   4205     int rv = 0, i;
   4206     soc_olp_l2_hdr_t olp_l2_header;
   4207     soc_olp_tx_hdr_t olp_oam_header;
   4208     uint8 *buffer_p = encap_data;
   4209     bcm_stat_group_mode_t stat_group;
   4210     bcm_stat_object_t stat_object;
   4211     uint32 stat_mode;
   4212     uint32 stat_pool_number;
   4213     uint32 base_index;
   4214     bcm_module_t my_modid = 0;
   4215     bcm_gport_t  cpu_dglp;
   4216 
   4217 
   4218     BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_modid));
   4219     BCM_IF_ERROR_RETURN(_bcm_esw_glp_construct(unit, BCM_TRUNK_INVALID, my_modid,
   4220                                                CMIC_PORT(unit), &cpu_dglp));
   4221     /* Get OLP L2 Header for CPU port */
   4222     sal_memset(&olp_l2_header, 0, sizeof(olp_l2_header));
   4223     rv = _bcm_olp_l2_hdr_get(unit, cpu_dglp, 0, &olp_l2_header);
   4224     if (BCM_FAILURE(rv)) {
   4225         LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: "
   4226                         "OLP Header get failed.\n")));
   4227         return (rv);
   4228     }
   4229     buffer_p = _bcm_fp_oam_olp_l2_header_pack(buffer_p, &olp_l2_header);
   4230 
   4231     sal_memset(&olp_oam_header, 0, sizeof(olp_oam_header));
   4232     /* Set Port number */
   4233     SOC_OLP_TX_PORT(&olp_oam_header) = port_id;
   4234     SOC_OLP_TX_MODID(&olp_oam_header) = mod;
   4235     SOC_OLP_TX_PRI(&olp_oam_header) = int_pri;
   4236 
   4237     for (i=0; i< counter_size; i++) {
   4238  
   4239         _bcm_esw_stat_get_counter_id_info(unit, counter_base_id[i],
   4240                                           &stat_group, &stat_object,
   4241                                           &stat_mode, &stat_pool_number,
   4242                                           &base_index);
   4243         if (i == 0) {
   4244             SOC_OLP_TX_CTR1_ID(&olp_oam_header) =
   4245                 SOC_OLP_TX_CTR(stat_pool_number, 
   4246                                 (base_index + counter_offset[i]));
   4247             SOC_OLP_TX_CTR1_ACTION(&olp_oam_header) =
   4248                                        counter_action[i];
   4249             /* Counter location is Egress */
   4250             SOC_OLP_TX_CTR1_LOCATION(&olp_oam_header) = 1;
   4251         }
   4252         if (i == 1) {
   4253             SOC_OLP_TX_CTR2_ID_SET(&olp_oam_header,
   4254                 SOC_OLP_TX_CTR(stat_pool_number, 
   4255                                 (base_index + counter_offset[i])));
   4256             SOC_OLP_TX_CTR2_ACTION(&olp_oam_header) =
   4257                                        counter_action[i];
   4258             SOC_OLP_TX_CTR2_LOCATION(&olp_oam_header) = 1;
   4259         }
   4260         if (i == 2) {
   4261             SOC_OLP_TX_CTR3_ID_SET(&olp_oam_header,
   4262                 SOC_OLP_TX_CTR(stat_pool_number, 
   4263                                 (base_index + counter_offset[i])));
   4264             SOC_OLP_TX_CTR3_ACTION(&olp_oam_header) =
   4265                                        counter_action[i];
   4266             SOC_OLP_TX_CTR3_LOCATION(&olp_oam_header) = 1;
   4267         }
   4268     }
   4269     if(lm_pdu_counter_offset){
   4270         /* COUNTER OFFSET in OLP Header =
   4271          * (L2 Encap + Counter field offset in MPLS OAM Header - 14)/2 
   4272          */
   4273         SOC_OLP_TX_OAM_OFFSET(&olp_oam_header) =
   4274             (lm_pdu_counter_offset - 14) >> 1;
   4275     }
   4276 
   4277     SOC_OLP_TX_TIMESTAMP_ACTION(&olp_oam_header) = ts_mode;
   4278 
   4279     /* Pack OLP OAM Encap */
   4280     buffer_p = shr_olp_tx_header_pack(buffer_p, &olp_oam_header);
   4281     *encap_length += (buffer_p - encap_data);
   4282 
   4283 #ifdef _BHH_DEBUG_DUMP
   4284     _bcm_fp_oam_encap_data_dump(encap_data, *encap_length);
   4285 #endif
   4286     return rv;
   4287 }
   4288 
   4289 /*
   4290  * Function:
   4291  *      _bcm_fp_oam_encap_build_pack
   4292  * Purpose:
   4293  *      Builds and packs the MPLS OAM packet encapsulation for a given
   4294  *      tunnel type.
   4295  * Parameters:
   4296  *      unit            - (IN) Unit number.
   4297  *      mod             - (IN) Module.
   4298  *      port            - (IN) Port.
   4299  *      endpoint_config - (IN/OUT) Pointer to endpoint structure.
   4300  *      packet_flags    - (IN) Flags for building packet.
   4301  *      buffer          - (OUT) Buffer returning encapsulation.
   4302  *      counter_info    - (IN/OUT) Pointer to LM counter info.
   4303  *      int_pri         - (IN) INT_PRI of OAM message.
   4304  * Returns:
   4305  *      BCM_E_XXX
   4306  * Notes:
   4307  *      The returning BHH encapsulation includes only all the
   4308  *      encapsulation headers/labels and does not include
   4309  *      the BHH control packet.
   4310  */
   4311 STATIC int
   4312 _bcm_fp_oam_encap_build_pack(int unit, bcm_module_t mod, bcm_port_t port,
   4313                              _bhh_fp_oam_ep_data_t *h_data_p,
   4314                              uint32 packet_flags,
   4315                              uint8 *buffer,
   4316                              uint16 *encap_length, 
   4317                              _bhh_oam_lm_dm_info_t *counter_info,
   4318                              bcm_cos_t  int_pri, uint8 oam_exp,
   4319                              uint8 oam_ttl)
   4320 {
   4321     uint8          *cur_ptr = buffer;
   4322     uint16         etype = 0;
   4323     bcm_if_t       l3_intf_id = -1;
   4324     _ach_header_t  ach;
   4325     _mpls_label_t  mpls_gal;
   4326     _mpls_label_t  mpls_labels[_BHH_MPLS_MAX_LABELS];
   4327     _mpls_label_t  pw_label;
   4328     int            mpls_count = 0;
   4329     _l2_header_t   l2;
   4330     int i;
   4331 
   4332     /*
   4333      * Get necessary headers/labels information.
   4334      *
   4335      * Following order is important since some headers/labels
   4336      * may depend on previous header/label information.
   4337      */
   4338     if (packet_flags & _BHH_ENCAP_PKT_G_ACH) {
   4339         BCM_IF_ERROR_RETURN
   4340             (_bcm_fp_oam_ach_header_get(packet_flags, &ach));
   4341         counter_info->oam_replacement_offset += 4;
   4342     }
   4343 
   4344     if (packet_flags & _BHH_ENCAP_PKT_GAL) {
   4345         if (h_data_p->egr_label == SHR_BHH_MPLS_GAL_LABEL) {
   4346             BCM_IF_ERROR_RETURN
   4347                 (_bcm_fp_oam_mpls_gal_label_get(&mpls_gal,
   4348                                                 h_data_p->egr_label_exp));
   4349         } else {
   4350             BCM_IF_ERROR_RETURN
   4351                 (_bcm_fp_oam_mpls_gal_label_get(&mpls_gal, 0));
   4352         }
   4353         counter_info->oam_replacement_offset += 4;
   4354     }
   4355 
   4356     if (packet_flags & _BHH_ENCAP_PKT_MPLS) {
   4357         etype = SHR_BHH_L2_ETYPE_MPLS_UCAST;
   4358         BCM_IF_ERROR_RETURN
   4359             (_bcm_fp_oam_mpls_labels_get(unit, h_data_p,
   4360                                              packet_flags,    
   4361                                              _BHH_FP_OAM_MPLS_MAX_LABELS,
   4362                                              &pw_label,
   4363                                              mpls_labels, 
   4364                                              &mpls_count,
   4365                                              &l3_intf_id,
   4366                                              oam_exp, oam_ttl));
   4367         counter_info->oam_replacement_offset += (mpls_count *4);
   4368     }
   4369 
   4370     /* Always build L2 Header */
   4371     BCM_IF_ERROR_RETURN
   4372         (_bcm_fp_oam_l2_header_get(unit, 
   4373                                        h_data_p,
   4374                                        port, 
   4375                                        etype, 
   4376                                        &l2,
   4377                                        &counter_info->oam_replacement_offset));
   4378     _bcm_fp_oam_olp_tx_header_create(unit, mod, port,
   4379                                      counter_info->counter_size,
   4380                                      counter_info->counter_base_id,
   4381                                      counter_info->counter_offset,
   4382                                      counter_info->counter_action,
   4383                                      counter_info->byte_count_offset,
   4384                                      counter_info->ts_mode, 
   4385                                      counter_info->oam_replacement_offset,
   4386                                      buffer,
   4387                                      encap_length, int_pri);
   4388     /*
   4389      * Pack header/labels into given buffer (network packet format).
   4390      *
   4391      * Following packing order must be followed to correctly
   4392      * build the packet encapsulation.
   4393      */
   4394     cur_ptr = buffer + *encap_length;
   4395 
   4396     /* L2 Header is always present */
   4397     cur_ptr = _bcm_fp_oam_l2_header_pack(h_data_p->type, cur_ptr, &l2);
   4398 
   4399     if (packet_flags & _BHH_ENCAP_PKT_MPLS) {
   4400         for (i = 0;i < mpls_count;i++) {
   4401             cur_ptr = _bcm_fp_oam_mpls_label_pack(cur_ptr, &mpls_labels[i]);
   4402         }
   4403     }
   4404 
   4405     if (packet_flags & _BHH_ENCAP_PKT_GAL) {    
   4406         cur_ptr = _bcm_fp_oam_mpls_label_pack(cur_ptr, &mpls_gal);
   4407     }
   4408 
   4409     if (packet_flags & _BHH_ENCAP_PKT_G_ACH) {
   4410         cur_ptr = _bcm_fp_oam_ach_header_pack(cur_ptr, &ach);
   4411     }
   4412 
   4413 #ifdef _BHH_DEBUG_DUMP
   4414     _bcm_fp_oam_encap_data_dump(buffer, *encap_length);
   4415 #endif
   4416 
   4417     /* Set BHH encapsulation length */
   4418     *encap_length = cur_ptr - buffer;
   4419 
   4420     return (BCM_E_NONE);
   4421 }
   4422 
   4423 void
   4424 _bcm_fp_oam_bhh_hash_data_dump(int unit, _bhh_fp_oam_ep_data_t *h_data_p)
   4425 {
   4426     int i = 0;
   4427     LOG_CLI((BSL_META_U(unit,"Type = %d\r\n"),h_data_p->type));
   4428     LOG_CLI((BSL_META_U(unit,"EP ID = %d\r\n"),h_data_p->ep_id));
   4429     LOG_CLI((BSL_META_U(unit,"Remote = %d\r\n"),h_data_p->is_remote));
   4430     LOG_CLI((BSL_META_U(unit,"Name = %d\r\n"),h_data_p->name));
   4431     LOG_CLI((BSL_META_U(unit,"Level = %d\r\n"),h_data_p->level));
   4432     LOG_CLI((BSL_META_U(unit,"Outer Vlan = %d\r\n"),h_data_p->vlan));
   4433     LOG_CLI((BSL_META_U(unit,"Inner Vlan = %d\r\n"),h_data_p->inner_vlan));
   4434     LOG_CLI((BSL_META_U(unit,"Gport = %d\r\n"),h_data_p->gport));
   4435     LOG_CLI((BSL_META_U(unit,"SGLP = %d\r\n"),h_data_p->sglp));
   4436     LOG_CLI((BSL_META_U(unit,"DGLP = %d\r\n"),h_data_p->dglp));
   4437     LOG_CLI((BSL_META_U(unit,"Grp idx = %d\r\n"),h_data_p->group_index));
   4438     LOG_CLI((BSL_META_U(unit,"VP = %d\r\n"),h_data_p->vp));
   4439     LOG_CLI((BSL_META_U(unit,"Flags = 0x%x\r\n"),h_data_p->flags));
   4440     LOG_CLI((BSL_META_U(unit,"Flags2 = 0x%x\r\n"),h_data_p->flags2));
   4441     LOG_CLI((BSL_META_U(unit,"Period = %d\r\n"),h_data_p->period));
   4442     LOG_CLI((BSL_META_U(unit,"Label = 0x%x\r\n"),h_data_p->label));
   4443     LOG_CLI((BSL_META_U(unit,"Vlan Pri = %d\r\n"),h_data_p->vlan_pri));
   4444     LOG_CLI((BSL_META_U(unit,"Egress if = 0x%x\r\n"),h_data_p->egress_if));
   4445     LOG_CLI((BSL_META_U(unit,"Outer TPID = 0x%04X\r\n"),h_data_p->outer_tpid));
   4446     LOG_CLI((BSL_META_U(unit,"Inner TPID = 0x%04X\r\n"),h_data_p->inner_tpid));
   4447     LOG_CLI((BSL_META_U(unit,"Trunk ID = %d\r\n"),h_data_p->trunk_id));
   4448     LOG_CLI((BSL_META_U(unit,"Trunk Index = %d\r\n"),h_data_p->trunk_index));
   4449     LOG_CLI((BSL_META_U(unit,"Src Mac = %02X:%02X:%02X:%02X:%02X:%02X\r\n"),
   4450              h_data_p->src_mac_address[0], h_data_p->src_mac_address[1],
   4451              h_data_p->src_mac_address[2], h_data_p->src_mac_address[3],
   4452              h_data_p->src_mac_address[4], h_data_p->src_mac_address[5]));
   4453     LOG_CLI((BSL_META_U(unit,"Dst Mac = %02X:%02X:%02X:%02X:%02X:%02X\r\n"),
   4454              h_data_p->dst_mac_address[0], h_data_p->dst_mac_address[1],
   4455              h_data_p->dst_mac_address[2], h_data_p->dst_mac_address[3],
   4456              h_data_p->dst_mac_address[4], h_data_p->dst_mac_address[5]));
   4457     LOG_CLI((BSL_META_U(unit,"Inner vlan pri = %d\r\n"),
   4458                         h_data_p->inner_vlan_pri));
   4459     LOG_CLI((BSL_META_U(unit,"Vccv Type = %d\r\n"),h_data_p->vccv_type));
   4460     LOG_CLI((BSL_META_U(unit,"VPN = %d\r\n"),h_data_p->vpn));
   4461     LOG_CLI((BSL_META_U(unit,"PM profile attached = %d\r\n"),
   4462                         h_data_p->pm_profile_attached));
   4463     LOG_CLI((BSL_META_U(unit,"BHH Session Id = %u\r\n"),
   4464                         h_data_p->uc_session_id));
   4465     LOG_CLI((BSL_META_U(unit,"BHH CCM counter info :\n")));
   4466     LOG_CLI((BSL_META_U(unit,"BHH CCM counter size = %u\r\n"),
   4467                         h_data_p->ccm_tx_counter_size));
   4468     for (i=0; i< BCM_OAM_LM_COUNTER_MAX; i++)
   4469     {
   4470         LOG_CLI((BSL_META_U(unit,"BHH counter %d base Id = %u\r\n"),
   4471                     i, h_data_p->ccm_tx_update_lm_counter_base_id[i]));
   4472         LOG_CLI((BSL_META_U(unit,"BHH counter %d offset = %u\r\n"),
   4473                     i, h_data_p->ccm_tx_update_lm_counter_offset[i]));
   4474     }
   4475     LOG_CLI((BSL_META_U(unit,"BHH LM counter info :\n")));
   4476     LOG_CLI((BSL_META_U(unit,"BHH LM counter size = %u\r\n"),
   4477                         h_data_p->lm_counter_size));
   4478     for (i=0; i< BCM_OAM_LM_COUNTER_MAX; i++)
   4479     {
   4480         LOG_CLI((BSL_META_U(unit,"BHH counter %d base Id = %u\r\n"),
   4481                     i, h_data_p->lm_counter_base_id[i]));
   4482         LOG_CLI((BSL_META_U(unit,"BHH counter %d offset = %u\r\n"),
   4483                     i, h_data_p->lm_counter_offset[i]));
   4484         LOG_CLI((BSL_META_U(unit,"BHH counter %d action = %u\r\n"),
   4485                     i, h_data_p->lm_counter_action[i]));
   4486     }
   4487     LOG_CLI((BSL_META_U(unit,"BHH DM counter info :\n")));
   4488     LOG_CLI((BSL_META_U(unit,"BHH DM counter size = %u\r\n"),
   4489                         h_data_p->dm_tx_counter_size));
   4490     for (i=0; i< BCM_OAM_LM_COUNTER_MAX; i++)
   4491     {
   4492         LOG_CLI((BSL_META_U(unit,"BHH counter %d base Id = %u\r\n"),
   4493                     i, h_data_p->dm_tx_update_lm_counter_base_id[i]));
   4494         LOG_CLI((BSL_META_U(unit,"BHH counter %d offset = %u\r\n"),
   4495                     i, h_data_p->dm_tx_update_lm_counter_offset[i]));
   4496     }
   4497     LOG_CLI((BSL_META_U(unit,"BHH LB counter info :\n")));
   4498     LOG_CLI((BSL_META_U(unit,"BHH LB counter size = %u\r\n"),
   4499                         h_data_p->lb_tx_counter_size));
   4500     for (i=0; i< BCM_OAM_LM_COUNTER_MAX; i++)
   4501     {
   4502         LOG_CLI((BSL_META_U(unit,"BHH counter %d base Id = %u\r\n"),
   4503                     i, h_data_p->lb_tx_update_lm_counter_base_id[i]));
   4504         LOG_CLI((BSL_META_U(unit,"BHH counter %d offset = %u\r\n"),
   4505                     i, h_data_p->lb_tx_update_lm_counter_offset[i]));
   4506     }
   4507     LOG_CLI((BSL_META_U(unit,"HW session ID = %d\r\n"),
   4508                         h_data_p->hw_session_id));
   4509     LOG_CLI((BSL_META_U(unit,"HW no of session entries = %d\r\n"),
   4510                         h_data_p->hw_session_num_entries));
   4511     LOG_CLI((BSL_META_U(unit,"Resolved trunk gport based on trunk " 
   4512                         "index 0x%x\r\n"),
   4513                         h_data_p->resolved_trunk_gport));
   4514 }
   4515 
   4516 /*
   4517  * Function:
   4518  *      _bcm_fp_oam_bhh_encap_create
   4519  * Purpose:
   4520  *      Creates a BHH packet encapsulation.
   4521  * Parameters:
   4522  *      unit            - (IN) Unit number.
   4523  *      mod             - (IN) Module.
   4524  *      port_id         - (IN) Port.
   4525  *      endpoint_config - (IN/OUT) Pointer to endpoint structure.
   4526  *      encap_data      - (OUT) Buffer returning encapsulation.
   4527  *      counter_info    - (IN/OUT) Pointer to LM counter info.
   4528  *      int_pri         - (IN) INT_PRI of OAM message.
   4529  * Returns:
   4530  *      BCM_E_XXX
   4531  * Notes:
   4532  *      The returning BHH encapsulation buffer includes all the
   4533  *      corresponding headers/labels EXCEPT for the BHH control packet.
   4534  */
   4535 STATIC int
   4536 _bcm_fp_oam_bhh_encap_create(int unit, bcm_module_t mod, 
   4537                          bcm_port_t port_id,
   4538                          _bhh_fp_oam_ep_data_t *h_data_p,
   4539                          uint8 *encap_data,
   4540                          uint8  *encap_type,
   4541                          uint16 *encap_length,
   4542                          _bhh_oam_lm_dm_info_t *counter_info,
   4543                          bcm_cos_t int_pri, uint8 oam_exp,
   4544                          uint8 oam_ttl)
   4545 {
   4546     uint32 packet_flags;
   4547     _bcm_fp_oam_control_t *oc;
   4548 
   4549     packet_flags = 0;
   4550 
   4551     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
   4552 
   4553     /*
   4554      * Get BHH encapsulation packet format flags
   4555 
   4556      * Also, perform the following for each BHH tunnel type:
   4557      * - Check for valid parameter values
   4558      * - Set specific values required by the BHH tunnel definition 
   4559      *   (e.g. such as ttl=1,...)
   4560      */
   4561     switch (h_data_p->type) {
   4562     case bcmOAMEndpointTypeBHHMPLS:
   4563         packet_flags |=
   4564             (_BHH_ENCAP_PKT_MPLS |
   4565              _BHH_ENCAP_PKT_GAL |
   4566              _BHH_ENCAP_PKT_G_ACH);
   4567         break;
   4568 
   4569     case bcmOAMEndpointTypeBHHMPLSVccv:
   4570         switch(h_data_p->vccv_type) {
   4571 
   4572         case bcmOamBhhVccvChannelAch:
   4573             packet_flags |=
   4574                 (_BHH_ENCAP_PKT_MPLS |
   4575                  _BHH_ENCAP_PKT_PW |
   4576                  _BHH_ENCAP_PKT_G_ACH);
   4577         break;
   4578 
   4579         case bcmOamBhhVccvRouterAlert:
   4580             packet_flags |=
   4581                 (_BHH_ENCAP_PKT_MPLS |
   4582                  _BHH_ENCAP_PKT_PW |
   4583                  _BHH_ENCAP_PKT_MPLS_ROUTER_ALERT |
   4584                  _BHH_ENCAP_PKT_G_ACH); 
   4585             break;
   4586 
   4587         case bcmOamBhhVccvTtl:
   4588             packet_flags |=
   4589                 (_BHH_ENCAP_PKT_MPLS |
   4590                  _BHH_ENCAP_PKT_PW |
   4591                  _BHH_ENCAP_PKT_G_ACH); 
   4592             break;
   4593 
   4594     case bcmOamBhhVccvGal13:
   4595             packet_flags |=
   4596                 (_BHH_ENCAP_PKT_MPLS |
   4597                  _BHH_ENCAP_PKT_PW |
   4598                  _BHH_ENCAP_PKT_GAL  |
   4599                  _BHH_ENCAP_PKT_G_ACH);
   4600             break;
   4601 
   4602     default:
   4603         return (BCM_E_PARAM);
   4604         break;
   4605     }
   4606         break;
   4607 
   4608     case bcmOAMEndpointTypeBhhSection:
   4609     case bcmOAMEndpointTypeBhhSectionInnervlan:
   4610     case bcmOAMEndpointTypeBhhSectionOuterVlan:
   4611     case bcmOAMEndpointTypeBhhSectionOuterPlusInnerVlan:
   4612         packet_flags |=
   4613             (_BHH_ENCAP_PKT_GAL |
   4614              _BHH_ENCAP_PKT_G_ACH);
   4615         break;
   4616     default:
   4617         return (BCM_E_PARAM);
   4618     }
   4619 
   4620     /* Build header/labels and pack in buffer */
   4621     BCM_IF_ERROR_RETURN
   4622         (_bcm_fp_oam_encap_build_pack(unit, mod, port_id,
   4623                                       h_data_p,
   4624                                       packet_flags,
   4625                                       encap_data,
   4626                                       encap_length, counter_info, int_pri,
   4627                                       oam_exp, oam_ttl));
   4628 
   4629     /* Set encap type (indicates uC side that checksum is required) */
   4630     *encap_type = SHR_BHH_ENCAP_TYPE_RAW;
   4631 
   4632 #ifdef _BHH_DEBUG_DUMP
   4633     _bcm_fp_oam_encap_data_dump(encap_data, *encap_length);
   4634 #endif
   4635 
   4636     if (*encap_length > oc->bhh_max_encap_length) {
   4637         LOG_ERROR(BSL_LS_BCM_OAM,
   4638                 (BSL_META_U(unit,
   4639                 "OAM(unit %d) Error: Encap length greater than max,"
   4640                 "encap_length=%u max=%u\n"),
   4641                  unit, *encap_length, oc->bhh_max_encap_length));
   4642         return BCM_E_CONFIG;
   4643     }
   4644 
   4645     return (BCM_E_NONE);
   4646 }
   4647 
   4648 /*  
   4649  * Function:
   4650  *     _bhh_fp_oam_ep_hash_key_construct
   4651  * Purpose:
   4652  *     Construct hash table key for a given endpoint information.
   4653  * Parameters:
   4654  *     unit    - (IN) BCM device number
   4655  *     oc      - (IN) Pointer to OAM control structure.
   4656  *     ep_info - (IN) Pointer to endpoint information structure.
   4657  *     key     - (IN/OUT) Pointer to hash key buffer.
   4658  * Retruns:
   4659  *     None
   4660  */ 
   4661 STATIC void
   4662 _bhh_fp_oam_ep_hash_key_construct(int unit,
   4663                                _bcm_fp_oam_control_t *oc,
   4664                                bcm_oam_endpoint_info_t *ep_info,
   4665                                _bhh_fp_oam_hash_key_t *key)
   4666 {
   4667     uint8  *loc = *key;
   4668 
   4669     sal_memset(key, 0, sizeof(_bhh_fp_oam_hash_key_t));
   4670 
   4671     if (NULL != ep_info) {
   4672         _BCM_OAM_KEY_PACK(loc, &ep_info->group, sizeof(ep_info->group));
   4673     
   4674         _BCM_OAM_KEY_PACK(loc, &ep_info->name, sizeof(ep_info->name));
   4675 
   4676         _BCM_OAM_KEY_PACK(loc, &ep_info->gport, sizeof(ep_info->gport));
   4677 
   4678         _BCM_OAM_KEY_PACK(loc, &ep_info->level, sizeof(ep_info->level));
   4679     
   4680         _BCM_OAM_KEY_PACK(loc, &ep_info->vlan, sizeof(ep_info->vlan));
   4681     
   4682         _BCM_OAM_KEY_PACK(loc, &ep_info->inner_vlan, 
   4683                                           sizeof(ep_info->inner_vlan));
   4684         _BCM_OAM_KEY_PACK(loc, &ep_info->mpls_label, 
   4685                 sizeof(ep_info->mpls_label));
   4686     }
   4687 
   4688     /* End address should not exceed size of _bcm_oam_hash_key_t. */
   4689     assert ((int) (loc - *key) <= sizeof(_bhh_fp_oam_hash_key_t));
   4690 }
   4691 
   4692 #if defined(BCM_WARM_BOOT_SUPPORT)
   4693 /*
   4694  * Function:
   4695  *       _bcm_fp_oam_bhh_scache_alloc
   4696  * Purpose:
   4697  *     Allocate scache memory for BHH module
   4698  * Parameters:
   4699  *     unit - (IN) BCM device number
   4700  * Returns:
   4701  *     BCM_E_UNIT    - Invalid BCM unit number.
   4702  *     BCM_E_UNAVAIL - OAM not support on this device.
   4703  *     BCM_E_MEMORY  - Allocation failure
   4704  *     BCM_E_NONE    - Success
   4705  */
   4706 STATIC int
   4707 _bcm_fp_oam_bhh_scache_alloc(int unit) {
   4708     _bcm_fp_oam_control_t *oc;
   4709     soc_scache_handle_t scache_handle;
   4710     uint8 *oam_scache;
   4711     int alloc_sz = 0;
   4712 
   4713 
   4714     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
   4715 
   4716     /* Number of BHH groups */
   4717     alloc_sz += sizeof(int);
   4718 
   4719     alloc_sz += (sizeof(int) + sizeof(int) + sizeof(uint32) + 
   4720                  BCM_OAM_GROUP_NAME_LENGTH) * 
   4721                 oc->bhh_endpoint_count;
   4722  
   4723     /* Number of BHH endpoints */
   4724     alloc_sz += sizeof(int);
   4725 
   4726     alloc_sz += (sizeof(bcm_oam_endpoint_t) +
   4727                 sizeof(bcm_oam_endpoint_type_t) + sizeof(bcm_oam_group_t) +
   4728                 sizeof(bcm_gport_t) + sizeof(bcm_mpls_label_t) +
   4729                 sizeof(uint8) +
   4730                 sizeof(bcm_vpn_t) +
   4731                 sizeof(bcm_if_t) +
   4732                 sizeof(bcm_oam_pm_profile_t) +
   4733                 sizeof(uint8) +
   4734                 (sizeof(uint32) * BCM_OAM_LM_COUNTER_MAX) +
   4735                 (sizeof(uint32) * BCM_OAM_LM_COUNTER_MAX) +
   4736                 sizeof(uint8) +
   4737                 (sizeof(uint32) * BCM_OAM_LM_COUNTER_MAX) +
   4738                 (sizeof(uint32) * BCM_OAM_LM_COUNTER_MAX) +
   4739                 (sizeof(uint32) * BCM_OAM_LM_COUNTER_MAX) +
   4740                 sizeof(uint8) +
   4741                 (sizeof(uint32) * BCM_OAM_LM_COUNTER_MAX) +
   4742                 (sizeof(uint32) * BCM_OAM_LM_COUNTER_MAX) +
   4743                 sizeof(uint8) +
   4744                 (sizeof(uint32) * BCM_OAM_LM_COUNTER_MAX) +
   4745                 (sizeof(uint32) * BCM_OAM_LM_COUNTER_MAX)) *
   4746                 oc->bhh_endpoint_count + 
   4747                 sizeof(uint32) +
   4748                 sizeof(uint8) +
   4749                 sizeof(int) +
   4750                 /* CSF counters */
   4751                 (sizeof(uint8) +
   4752                 (sizeof(uint32) * BCM_OAM_LM_COUNTER_MAX) +
   4753                 (sizeof(uint32) * BCM_OAM_LM_COUNTER_MAX) *
   4754                  oc->bhh_endpoint_count);
   4755 
   4756     /* Allocate memory to store oam_mpls_tp_ach_channel_type */
   4757     alloc_sz += sizeof(fp_oam_mpls_tp_ach_channel_type);
   4758 
   4759     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_OAM,
   4760                           bcmFpOamWbSequenceBhh);
   4761     BCM_IF_ERROR_RETURN(_bcm_esw_scache_ptr_get(unit, scache_handle, 1,
   4762                         alloc_sz, &oam_scache, BCM_WB_BHH_DEFAULT_VERSION, NULL));
   4763     return BCM_E_NONE;
   4764 }
   4765 
   4766 /*
   4767  * Function:
   4768  *     _bcm_fp_oam_bhh_sync
   4769  * Purpose:
   4770  *     Store BHH configuration to level two storage cache memory.
   4771  * Parameters:
   4772  *     unit - (IN) Device unit number
   4773  * Returns:
   4774  *     BCM_E_XXX
   4775  */
   4776 int
   4777 _bcm_fp_oam_bhh_sync(int unit)
   4778 {
   4779     int                 rv;  /* Operation return status. */
   4780     _bcm_fp_oam_control_t  *oc;
   4781     int                 alloc_size = 0, csf_cntr_size;
   4782     int                 stable_size;
   4783     soc_scache_handle_t scache_handle;
   4784     uint8               *oam_scache;
   4785     int                 grp_idx;
   4786     _bhh_fp_oam_group_data_t *group_p;   /* Pointer to group list.         */
   4787     int                 group_count = 0, ep_count = 0;
   4788     int         idx = 0;
   4789     _bhh_fp_oam_ep_data_t *ep_data;
   4790     uint8               i = 0;
   4791 
   4792     /* Get OAM module storage size. */
   4793     SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size));
   4794 
   4795     /* If level 2 store is not configured return from here. */
   4796     if (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit) || (stable_size == 0)) {
   4797         return BCM_E_NONE;
   4798     }
   4799 
   4800     /* Get handle to control structure. */
   4801     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
   4802 
   4803     _BCM_OAM_LOCK(oc);
   4804 
   4805     if (oc->ukernel_not_ready == 0) {
   4806         /* Initialize to group array pointer. */
   4807         group_p = oc->bhh_group_data;
   4808 
   4809         for (grp_idx = 0; grp_idx < oc->bhh_endpoint_count; grp_idx++) {
   4810 
   4811             /* Check if the group is in use. */
   4812             if (BCM_E_EXISTS
   4813                     == shr_idxres_list_elem_state(oc->bhh_group_pool, grp_idx)) {
   4814                 /*Store Group ID of this group*/
   4815                 alloc_size += sizeof(int);
   4816                 /*Store LMEP ID associated with this group*/
   4817                 alloc_size += sizeof(int);
   4818                 /*Store flags associated with this group*/
   4819                 alloc_size += sizeof(uint32);
   4820                 /*Store name associated with this group*/
   4821                 alloc_size += BCM_OAM_GROUP_NAME_LENGTH;
   4822                 group_count++;
   4823             }
   4824         }
   4825         /* To store OAM group count. */
   4826         alloc_size += sizeof(int);
   4827 
   4828         ep_data = oc->bhh_ep_data;
   4829         for (idx = 0; idx < oc->bhh_endpoint_count; idx++) {
   4830 
   4831             /* Check if the EP is in use. */
   4832             if (BCM_E_EXISTS
   4833                     == shr_idxres_list_elem_state(oc->bhh_pool, idx)) {
   4834                 /*Store ID of this EP*/
   4835                 alloc_size += sizeof(bcm_oam_endpoint_t);
   4836                 /*Store type of this EP*/
   4837                 alloc_size += sizeof(bcm_oam_endpoint_type_t);
   4838                 /*Store group ID associated with this EP*/
   4839                 alloc_size += sizeof(bcm_oam_group_t);
   4840                 /*Store gport associated with this EP*/
   4841                 alloc_size += sizeof(bcm_gport_t);
   4842                 /*Store egr label associated with this EP*/
   4843                 alloc_size += sizeof(bcm_mpls_label_t);
   4844                 /*Store egr label exp associated with this EP*/
   4845                 alloc_size += sizeof(uint8);
   4846                 /*Store vpn associated with this EP*/
   4847                 alloc_size += sizeof(bcm_vpn_t);
   4848                 /*Store intf associated with this EP*/
   4849                 alloc_size += sizeof(bcm_if_t);
   4850                 /*Store PM profile associated with this EP*/
   4851                 alloc_size += sizeof(bcm_oam_pm_profile_t);
   4852                 /*Store CCM TX counter info associated with this EP*/
   4853                 /*Store CCM TX counter size*/
   4854                 alloc_size += sizeof(uint8);
   4855                 /*Store CCM TX counters base_ids*/
   4856                 alloc_size += sizeof(uint32) * ep_data[idx].ccm_tx_counter_size;
   4857                 /*Store CCM TX counters offsets*/
   4858                 alloc_size += sizeof(uint32) * ep_data[idx].ccm_tx_counter_size;
   4859                 /*Store LM TX counter info associated with this EP*/
   4860                 /*Store LM TX counter size*/
   4861                 alloc_size += sizeof(uint8);
   4862                 /*Store LM TX counters base_ids*/
   4863                 alloc_size += sizeof(uint32) * ep_data[idx].lm_counter_size;
   4864                 /*Store LM TX counters offsets*/
   4865                 alloc_size += sizeof(uint32) * ep_data[idx].lm_counter_size;
   4866                 /*Store LM TX counters actions*/
   4867                 alloc_size += sizeof(uint32) * ep_data[idx].lm_counter_size;
   4868                 /*Store LB TX counter info associated with this EP*/
   4869                 /*Store LB TX counter size*/
   4870                 alloc_size += sizeof(uint8);
   4871                 /*Store LB TX counters base_ids*/
   4872                 alloc_size += sizeof(uint32) * ep_data[idx].lb_tx_counter_size;
   4873                 /*Store LB TX counters offsets*/
   4874                 alloc_size += sizeof(uint32) * ep_data[idx].lb_tx_counter_size;
   4875                 /*Store DM TX counter info associated with this EP*/
   4876                 /*Store DM TX counter size*/
   4877                 alloc_size += sizeof(uint8);
   4878                 /*Store DM TX counters base_ids*/
   4879                 alloc_size += sizeof(uint32) * ep_data[idx].dm_tx_counter_size;
   4880                 /*Store DM TX counters offsets*/
   4881                 alloc_size += sizeof(uint32) * ep_data[idx].dm_tx_counter_size;
   4882                 /*Store HW provided session ID*/
   4883                 alloc_size += sizeof(uint32);
   4884                 /*Store HW provided number of session IDs*/
   4885                 alloc_size += sizeof(uint8);
   4886                 /*Store Trunk index */
   4887                 alloc_size += sizeof(int);
   4888                 ep_count++;
   4889             }
   4890         }
   4891         /* To store BHH EP count. */
   4892         alloc_size += (sizeof(bcm_oam_endpoint_t) * ep_count);
   4893         if (_BCM_FP_OAM_PM_BHH_DATA_COLLECTION_MODE_IS_PROCESSED(oc)) { 
   4894             alloc_size += _BCM_FP_OAM_PM_PROFILE_SCACHE_SIZE;
   4895         }
   4896 
   4897         /* Scache Version 1 */
   4898 
   4899         /* Calculate size taken to accomadate CSF counters */
   4900         csf_cntr_size = 0;
   4901         /* Store CSF TX counter size */
   4902         csf_cntr_size += sizeof(uint8);
   4903         /* Store CSF TX counters base_ids */
   4904         csf_cntr_size += sizeof(uint32) * BCM_OAM_LM_COUNTER_MAX;
   4905         /* Store CSF TX counters offsets */
   4906         csf_cntr_size += sizeof(uint32) * BCM_OAM_LM_COUNTER_MAX;
   4907         /* Counters are per-endpoint */
   4908         csf_cntr_size *= oc->bhh_endpoint_count;
   4909 
   4910         alloc_size +=  csf_cntr_size;
   4911 
   4912         /* Allocate memory to store oam_mpls_tp_ach_channel_type */
   4913         alloc_size += sizeof(fp_oam_mpls_tp_ach_channel_type);
   4914 
   4915         SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_OAM,
   4916                               bcmFpOamWbSequenceBhh);
   4917 
   4918         /* Check if memory has already been allocated */
   4919         rv = _bcm_esw_scache_ptr_get(unit,
   4920                 scache_handle,
   4921                 0,
   4922                 0,
   4923                 &oam_scache,
   4924                 BCM_WB_BHH_DEFAULT_VERSION,
   4925                 NULL
   4926                 );
   4927         if (!SOC_WARM_BOOT(unit) && (BCM_E_NOT_FOUND == rv)) {
   4928             rv = _bcm_esw_scache_ptr_get(unit,
   4929                     scache_handle,
   4930                     1,
   4931                     alloc_size,
   4932                     &oam_scache,
   4933                     BCM_WB_BHH_DEFAULT_VERSION,
   4934                     NULL
   4935                     );
   4936             if (BCM_FAILURE(rv)
   4937                     || (NULL == oam_scache)) {
   4938                 goto cleanup;
   4939             }
   4940         } else if (BCM_FAILURE(rv)) {
   4941             goto cleanup;
   4942         }
   4943         /* To store OAM group count. */
   4944         sal_memcpy(oam_scache, &group_count, sizeof(int));
   4945         oam_scache += sizeof(int);
   4946 
   4947         for (grp_idx = 0; grp_idx < oc->bhh_endpoint_count; grp_idx++)
   4948         {
   4949             /* Check if the group is in use. */
   4950             if (BCM_E_EXISTS
   4951                     == shr_idxres_list_elem_state(oc->bhh_group_pool, 
   4952                                                   grp_idx)) {
   4953 
   4954                 sal_memcpy(oam_scache, &group_p[grp_idx].group_id,
   4955                         sizeof(int));
   4956                 oam_scache += sizeof(int);
   4957                 sal_memcpy(oam_scache, &group_p[grp_idx].lmep_id,
   4958                         sizeof(int));
   4959                 oam_scache += sizeof(int);
   4960                 sal_memcpy(oam_scache, &group_p[grp_idx].flags,
   4961                         sizeof(uint32));
   4962                 oam_scache += sizeof(uint32);
   4963                 sal_memcpy(oam_scache, group_p[grp_idx].name,
   4964                         BCM_OAM_GROUP_NAME_LENGTH);
   4965                 oam_scache += BCM_OAM_GROUP_NAME_LENGTH;
   4966             }
   4967         }
   4968         /* To store BHH EP count. */
   4969         sal_memcpy(oam_scache, &ep_count, sizeof(int));
   4970         oam_scache += sizeof(int);
   4971         for (idx = 0; idx < oc->bhh_endpoint_count; idx++) {
   4972 
   4973             /* Check if the EP is in use. */
   4974             if (BCM_E_EXISTS
   4975                     == shr_idxres_list_elem_state(oc->bhh_pool, idx)) {
   4976                 sal_memcpy(oam_scache, &ep_data[idx].ep_id,
   4977                         sizeof(bcm_oam_endpoint_t));
   4978                 oam_scache += sizeof(bcm_oam_endpoint_t);
   4979                 sal_memcpy(oam_scache, &ep_data[idx].type,
   4980                         sizeof(bcm_oam_endpoint_type_t));
   4981                 oam_scache += sizeof(bcm_oam_endpoint_type_t);
   4982                 sal_memcpy(oam_scache, &ep_data[idx].group_index,
   4983                         sizeof(bcm_oam_group_t));
   4984                 oam_scache += sizeof(bcm_oam_group_t);
   4985                 sal_memcpy(oam_scache, &ep_data[idx].gport,
   4986                         sizeof(bcm_gport_t));
   4987                 oam_scache += sizeof(bcm_gport_t);
   4988                 sal_memcpy(oam_scache, &ep_data[idx].egr_label,
   4989                         sizeof(bcm_mpls_label_t));
   4990                 oam_scache += sizeof(bcm_mpls_label_t);
   4991                 sal_memcpy(oam_scache, &ep_data[idx].egr_label_exp,
   4992                         sizeof(uint8));
   4993                 oam_scache += sizeof(uint8);
   4994                 sal_memcpy(oam_scache, &ep_data[idx].vpn,
   4995                         sizeof(bcm_vpn_t));
   4996                 oam_scache += sizeof(bcm_vpn_t);
   4997                 sal_memcpy(oam_scache, &ep_data[idx].egress_if,
   4998                         sizeof(bcm_if_t));
   4999                 oam_scache += sizeof(bcm_if_t);
   5000                 sal_memcpy(oam_scache, &ep_data[idx].pm_profile_attached,
   5001                         sizeof(bcm_oam_pm_profile_t));
   5002                 oam_scache += sizeof(bcm_oam_pm_profile_t);
   5003                 /*Store CCM TX counter info associated with this EP*/
   5004                 /*Store CCM TX counter size*/
   5005                 sal_memcpy(oam_scache, &ep_data[idx].ccm_tx_counter_size,
   5006                         sizeof(uint8));
   5007                 oam_scache += sizeof(uint8);
   5008                 /*Store CCM TX counters base_ids*/
   5009                 for (i = 0; i < ep_data[idx].ccm_tx_counter_size; i++) {
   5010                     sal_memcpy(oam_scache,
   5011                                &ep_data[idx].ccm_tx_update_lm_counter_base_id[i],
   5012                                sizeof(uint32));
   5013                     oam_scache += sizeof(uint32);
   5014                 } 
   5015                 /*Store CCM TX counters offsets*/
   5016                 for (i = 0; i < ep_data[idx].ccm_tx_counter_size; i++) {
   5017                     sal_memcpy(oam_scache,
   5018                                &ep_data[idx].ccm_tx_update_lm_counter_offset[i],
   5019                                sizeof(uint32));
   5020                     oam_scache += sizeof(uint32);
   5021                 } 
   5022                 /*Store LM TX counter info associated with this EP*/
   5023                 /*Store LM TX counter size*/
   5024                 sal_memcpy(oam_scache, &ep_data[idx].lm_counter_size,
   5025                         sizeof(uint8));
   5026                 oam_scache += sizeof(uint8);
   5027                 /*Store LM TX counters base_ids*/
   5028                 for (i = 0; i < ep_data[idx].lm_counter_size; i++) {
   5029                     sal_memcpy(oam_scache,
   5030                                &ep_data[idx].lm_counter_base_id[i],
   5031                                sizeof(uint32));
   5032                     oam_scache += sizeof(uint32);
   5033                 } 
   5034                 /*Store LM TX counters offsets*/
   5035                 for (i = 0; i < ep_data[idx].lm_counter_size; i++) {
   5036                     sal_memcpy(oam_scache,
   5037                                &ep_data[idx].lm_counter_offset[i],
   5038                                sizeof(uint32));
   5039                     oam_scache += sizeof(uint32);
   5040                 }
   5041                 /*Store LM TX counters actions*/
   5042                 for (i = 0; i < ep_data[idx].lm_counter_size; i++) {
   5043                     sal_memcpy(oam_scache,
   5044                                &ep_data[idx].lm_counter_action[i],
   5045                                sizeof(uint32));
   5046                     oam_scache += sizeof(uint32);
   5047                 }
   5048                 /*Store LB TX counter info associated with this EP*/
   5049                 /*Store LB TX counter size*/
   5050                 sal_memcpy(oam_scache, &ep_data[idx].lb_tx_counter_size,
   5051                         sizeof(uint8));
   5052                 oam_scache += sizeof(uint8);
   5053                 /*Store LB TX counters base_ids*/
   5054                 for (i = 0; i < ep_data[idx].lb_tx_counter_size; i++) {
   5055                     sal_memcpy(oam_scache,
   5056                                &ep_data[idx].lb_tx_update_lm_counter_base_id[i],
   5057                                sizeof(uint32));
   5058                     oam_scache += sizeof(uint32);
   5059                 } 
   5060                 /*Store LB TX counters offsets*/
   5061                 for (i = 0; i < ep_data[idx].lb_tx_counter_size; i++) {
   5062                     sal_memcpy(oam_scache,
   5063                                &ep_data[idx].lb_tx_update_lm_counter_offset[i],
   5064                                sizeof(uint32));
   5065                     oam_scache += sizeof(uint32);
   5066                 }  
   5067                 /*Store DM TX counter info associated with this EP*/
   5068                 /*Store DM TX counter size*/
   5069                 sal_memcpy(oam_scache, &ep_data[idx].dm_tx_counter_size,
   5070                         sizeof(uint8));
   5071                 oam_scache += sizeof(uint8);
   5072                 /*Store DM TX counters base_ids*/
   5073                 for (i = 0; i < ep_data[idx].dm_tx_counter_size; i++) {
   5074                     sal_memcpy(oam_scache,
   5075                                &ep_data[idx].dm_tx_update_lm_counter_base_id[i],
   5076                                sizeof(uint32));
   5077                     oam_scache += sizeof(uint32);
   5078                 } 
   5079                 /*Store DM TX counters offsets*/
   5080                 for (i = 0; i < ep_data[idx].dm_tx_counter_size; i++) {
   5081                     sal_memcpy(oam_scache,
   5082                                &ep_data[idx].dm_tx_update_lm_counter_offset[i],
   5083                                sizeof(uint32));
   5084                     oam_scache += sizeof(uint32);
   5085                 }
   5086                 /*Store HW session ID*/
   5087                 sal_memcpy(oam_scache, &ep_data[idx].hw_session_id,
   5088                         sizeof(uint32));
   5089                 oam_scache += sizeof(uint32);
   5090                 /*Store HW number of session IDs*/
   5091                 sal_memcpy(oam_scache, &ep_data[idx].hw_session_num_entries,
   5092                         sizeof(uint8));
   5093                 oam_scache += sizeof(uint8);
   5094                 sal_memcpy(oam_scache, &ep_data[idx].trunk_index,
   5095                         sizeof(int));
   5096                 oam_scache += sizeof(int);
   5097             }
   5098         }
   5099         if (_BCM_FP_OAM_PM_BHH_DATA_COLLECTION_MODE_IS_PROCESSED(oc)) {
   5100             /* Store pm profile */
   5101             int itr;
   5102             _bcm_fp_oam_pm_profile_control_t *pmc = NULL;
   5103             
   5104             pmc = pm_profile_control[unit];
   5105             if (!pmc) {
   5106                 goto cleanup;
   5107             }
   5108             for(itr = 0; itr < _BCM_OAM_MAX_PM_PROFILES; itr++) {
   5109                 sal_memcpy(oam_scache,
   5110                         &(pmc->profile_info[itr]), sizeof(_bcm_fp_oam_pm_profile_int_info_t));
   5111                 oam_scache += sizeof(_bcm_fp_oam_pm_profile_int_info_t);
   5112             }
   5113         }
   5114 
   5115         for (idx = 0; idx < oc->bhh_endpoint_count; idx++) {
   5116             /* Check if the EP is in use. */
   5117             if (BCM_E_EXISTS != shr_idxres_list_elem_state(oc->bhh_pool, idx)) {
   5118                 continue;
   5119             }
   5120             /* Store CSF TX counter info associated with this EP */
   5121             /* Store CSF TX counter size */
   5122             sal_memcpy(oam_scache, &ep_data[idx].csf_tx_counter_size,
   5123                        sizeof(uint8));
   5124             oam_scache += sizeof(uint8);
   5125 
   5126             /* Store CSF TX counters base_ids */
   5127             for (i = 0; i < BCM_OAM_LM_COUNTER_MAX; i++) {
   5128                 sal_memcpy(oam_scache,
   5129                            &ep_data[idx].csf_tx_update_lm_counter_base_id[i],
   5130                            sizeof(uint32));
   5131                 oam_scache += sizeof(uint32);
   5132             }
   5133 
   5134             /* Store CSF TX counters offsets */
   5135             for (i = 0; i < BCM_OAM_LM_COUNTER_MAX; i++) {
   5136                 sal_memcpy(oam_scache,
   5137                            &ep_data[idx].csf_tx_update_lm_counter_offset[i],
   5138                            sizeof(uint32));
   5139                 oam_scache += sizeof(uint32);
   5140             }
   5141         }
   5142         for (idx = 0; idx < oc->bhh_endpoint_count; idx++) {
   5143             /* Check if the EP is in use. */
   5144             if (BCM_E_EXISTS != shr_idxres_list_elem_state(oc->bhh_pool, idx)) {
   5145                 continue;
   5146             }
   5147             sal_memcpy(oam_scache, &ep_data[idx].egr_label_ttl,
   5148                     sizeof(uint8));
   5149             oam_scache += sizeof(uint8);
   5150         }
   5151         sal_memcpy(oam_scache, &fp_oam_mpls_tp_ach_channel_type,
   5152                    sizeof(fp_oam_mpls_tp_ach_channel_type));
   5153         oam_scache += sizeof(fp_oam_mpls_tp_ach_channel_type);
   5154     }
   5155 
   5156 cleanup:
   5157     _BCM_OAM_UNLOCK(oc);
   5158     return (BCM_E_NONE);
   5159 }
   5160 
   5161 /*
   5162  * Function:
   5163  *     _bcm_fp_oam_wb_group_recover
   5164  * Purpose:
   5165  *     Recover OAM group configuration.
   5166  * Parameters:
   5167  *     unit        - (IN) BCM device number
   5168  *     stable_size - (IN) OAM module Level2 storage size.
   5169  *     oam_scache  - (IN) Pointer to scache address pointer.
   5170  * Returns:
   5171  *     BCM_E_XXX
   5172  */
   5173 STATIC int
   5174 _bcm_fp_oam_wb_group_recover(int unit, int stable_size, uint8 **oam_scache)
   5175 {
   5176     int                    index;                    /* Hw table index.     */
   5177     _bhh_fp_oam_group_data_t  *group_p;              /* Group info pointer. */
   5178     _bcm_fp_oam_control_t     *oc;                   /* Pointer to Control  */
   5179                                                      /* structure.          */
   5180     int                     rv;                      /* Operation return    */
   5181                                                      /* status.             */
   5182     uint32              group_count;                 /* Stored OAM group count*/
   5183     int bhh_group_idx = 0, group_id = 0;
   5184 
   5185     /* Control lock taken by calling routine. */
   5186     /* Get OAM control structure. */
   5187     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
   5188 
   5189     /* Recover the OAM groups */
   5190     sal_memcpy(&group_count, *oam_scache, sizeof(int));
   5191     *oam_scache = (*oam_scache + sizeof(int));
   5192 
   5193     for (index = 0; index < group_count; index++) {
   5194 
   5195         /* Get the group id from stored info. */
   5196         sal_memcpy(&group_id, *oam_scache, 
   5197                 sizeof(int));
   5198         *oam_scache = (*oam_scache + sizeof(int));
   5199 
   5200         bhh_group_idx = BCM_OAM_BHH_GET_UKERNEL_GROUP(group_id);
   5201         /* Reserve the group index. */
   5202         rv = shr_idxres_list_reserve(oc->bhh_group_pool, bhh_group_idx,
   5203                                      bhh_group_idx);
   5204         if (BCM_FAILURE(rv)) {
   5205             LOG_ERROR(BSL_LS_BCM_OAM,
   5206                     (BSL_META_U(unit,
   5207                                 "OAM(unit %d) Error: (GID=%d) Index reserve "
   5208                                 " failed  - %s.\n"), unit, index, 
   5209                                 bcm_errmsg(rv)));
   5210             rv = (rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv;
   5211             goto cleanup;
   5212         }
   5213         /* Get the group memory pointer. */
   5214         group_p = &oc->bhh_group_data[bhh_group_idx];
   5215         if (1 == group_p->in_use) {
   5216             rv = BCM_E_INTERNAL;
   5217             goto cleanup;
   5218         }
   5219 
   5220         group_p->group_id = group_id;
   5221         sal_memcpy(&group_p->lmep_id, *oam_scache, 
   5222                 sizeof(int));
   5223         *oam_scache = (*oam_scache + sizeof(int));
   5224         sal_memcpy(&group_p->flags, *oam_scache, 
   5225                 sizeof(uint32));
   5226         *oam_scache = (*oam_scache + sizeof(uint32));
   5227 
   5228         sal_memcpy(group_p->name, *oam_scache, 
   5229                 BCM_OAM_GROUP_NAME_LENGTH);
   5230         *oam_scache = (*oam_scache + BCM_OAM_GROUP_NAME_LENGTH);
   5231         group_p->in_use = 1;
   5232     }
   5233 
   5234     return (BCM_E_NONE);
   5235 
   5236 cleanup:
   5237 
   5238     if (BCM_E_EXISTS
   5239         == shr_idxres_list_elem_state(oc->group_pool, bhh_group_idx)) {
   5240         shr_idxres_list_free(oc->group_pool, bhh_group_idx);
   5241     }
   5242 
   5243     return (rv);
   5244 
   5245 }
   5246 
   5247 
   5248 /*
   5249  * Function:
   5250  *     _bcm_fp_oam_endpoint_alloc
   5251  * Purpose:
   5252  *     Allocate an endpoint memory element.
   5253  * Parameters:
   5254  *     ep_pp - (IN/OUT) Pointer to endpoint address pointer.
   5255  * Returns:
   5256  *     BCM_E_XXX
   5257  */
   5258 STATIC int
   5259 _bcm_fp_oam_endpoint_alloc(bcm_oam_endpoint_info_t **ep_pp)
   5260 {
   5261     bcm_oam_endpoint_info_t *ep_p = NULL;
   5262 
   5263     _BCM_OAM_ALLOC(ep_p, bcm_oam_endpoint_info_t,
   5264                    sizeof(bcm_oam_endpoint_info_t), "Endpoint info");
   5265     if (NULL == ep_p) {
   5266         return (BCM_E_MEMORY);
   5267     }
   5268 
   5269     *ep_pp = ep_p;
   5270 
   5271     return (BCM_E_NONE);
   5272 
   5273 }
   5274 
   5275 /*
   5276  * Function:
   5277  *     _bcm_fp_oam_mpls_entry_label_lookup
   5278  * Purpose:
   5279  *     Finds  a MPLS_ENTRY corresponding to a MPLS label.
   5280  * Parameters:
   5281  *     unit        - (IN) BCM device number
   5282  *     label       - (IN) label to which MPLS_ENTRY object to found
   5283  *     label       - (IN) index in MPLS_ENTRY object to found
   5284  *     found_entry - (OUT) Pointer to MPLS_ENTRY object.
   5285  * Returns:
   5286  *     BCM_E_XXX
   5287  */
   5288 STATIC int
   5289 _bcm_fp_oam_mpls_entry_label_lookup(int unit, bcm_mpls_label_t label,
   5290                                      int *mpls_index,
   5291                                      mpls_entry_entry_t *found_entry)
   5292 {
   5293 #if defined(INCLUDE_L3)
   5294     mpls_entry_entry_t mpls_key_entry;
   5295     int rv = BCM_E_NONE;
   5296 
   5297     sal_memset(&mpls_key_entry, 0, sizeof(mpls_key_entry));
   5298 
   5299     soc_MPLS_ENTRYm_field32_set(unit, &mpls_key_entry, MPLS_LABELf, label);
   5300     soc_MPLS_ENTRYm_field32_set(unit, &mpls_key_entry, VALIDf, 1);
   5301 
   5302     BCM_IF_ERROR_RETURN(bcm_tr_mpls_lock(unit));
   5303     rv = soc_mem_search(unit, MPLS_ENTRYm, MEM_BLOCK_ANY, mpls_index,
   5304                         &mpls_key_entry, found_entry, 0);
   5305     bcm_tr_mpls_unlock(unit);
   5306 
   5307     return rv;
   5308 #endif /* INCLUDE_L3 */
   5309     return BCM_E_UNAVAIL;
   5310 }
   5311 
   5312 /*
   5313  * Function:
   5314  *     _bcm_fp_oam_wb_endpoints_recover
   5315  * Purpose:
   5316  *     Recover OAM endpoint configuration for DownMEPS.
   5317  * Parameters:
   5318  *     unit        - (IN) BCM device number
   5319  *     stable_size - OAM module Level2 memory size.
   5320  *     oam_scache  - Pointer to secondary storage buffer pointer.
   5321  * Returns:
   5322  *     BCM_E_XXX
   5323  */
   5324 STATIC int
   5325 _bcm_fp_oam_wb_endpoints_recover(int unit,
   5326                                  int stable_size,
   5327                                  uint8 **oam_scache)
   5328 {
   5329     _bhh_fp_oam_ep_data_t *h_data_p = NULL; /* Endpoint hash data pointer. */
   5330     _bcm_fp_oam_control_t      *oc;       /* Pointer to control structure.   */
   5331     int                     rv;           /* Operation return status.        */
   5332     int                     ep_id, ep_count;/* Endpoint ID.                  */
   5333     _bhh_fp_oam_hash_key_t  hash_key;     /* Hash key buffer for lookup.     */
   5334     bcm_oam_endpoint_info_t *ep_info = NULL;  /* Endpoint information.        */
   5335     _bhh_fp_oam_group_data_t *group_p;        /* Group info pointer. */
   5336     int                     idx      = 0, i = 0;
   5337     bcm_oam_endpoint_t      bhh_endpoint_index = 0;
   5338     bhh_sdk_msg_ctrl_sess_get_t msg;
   5339     mpls_entry_entry_t mpls_entry;
   5340     uint16 buffer_len, reply_len;
   5341     uint8 *buffer, *buffer_ptr;
   5342     int mpls_index = -1;
   5343     bcm_l3_egress_t l3_egress;
   5344     bcm_l3_intf_t l3_intf;
   5345     uint8*  encap_data = NULL;
   5346     soc_olp_l2_hdr_t olp_l2_header;
   5347     soc_olp_tx_hdr_t olp_oam_tx_header;
   5348     int bhh_group_idx = 0;
   5349     int                  sglp = 0;          /* Source global logical port.  */
   5350     int                  dglp = 0;          /* Dest global logical port.    */
   5351     bcm_gport_t          dgpp = 0;
   5352     bcm_trunk_t          trunk_id = BCM_TRUNK_INVALID;
   5353     bcm_trunk_member_t   trunk_member;
   5354 
   5355     LOG_DEBUG(BSL_LS_BCM_OAM,
   5356               (BSL_META_U(unit,
   5357                           "OAM(unit %d) Info: "
   5358                           "_bcm_fp_oam_wb_endpoints_recover.\n"), unit));
   5359     /*
   5360      * Get OAM control structure.
   5361      *     Note: Lock taken by calling routine.
   5362      */
   5363     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
   5364 
   5365     /* Recover the OAM endpoint count */
   5366     sal_memcpy(&ep_count, *oam_scache, sizeof(int));
   5367     *oam_scache = (*oam_scache + sizeof(int));
   5368 
   5369     for (idx = 0; idx < ep_count; idx++) {
   5370 
   5371         sal_memcpy(&ep_id, *oam_scache, sizeof(bcm_oam_endpoint_t));
   5372         *oam_scache = (*oam_scache + sizeof(bcm_oam_endpoint_t));
   5373 
   5374         bhh_endpoint_index = BCM_OAM_BHH_GET_UKERNEL_EP(ep_id);
   5375 
   5376         h_data_p = &oc->bhh_ep_data[bhh_endpoint_index];
   5377         if (1 == h_data_p->in_use) {
   5378             return (BCM_E_INTERNAL);
   5379         }
   5380         rv = shr_idxres_list_reserve(oc->bhh_pool, bhh_endpoint_index,
   5381                 bhh_endpoint_index);
   5382         if (BCM_FAILURE(rv)) {
   5383             rv = (rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv;
   5384             LOG_ERROR(BSL_LS_BCM_OAM,
   5385                     (BSL_META_U(unit,
   5386                                 "BHH(unit %d) Error: Endpoint reserve (EP=%d) - %s.\n"),
   5387                      unit, bhh_endpoint_index, bcm_errmsg(rv)));
   5388             goto cleanup;
   5389         }
   5390 
   5391         _BHH_FP_OAM_HASH_DATA_CLEAR(h_data_p);
   5392         h_data_p->remote_index = _BCM_OAM_INVALID_INDEX;
   5393         h_data_p->trunk_id =  BCM_TRUNK_INVALID;
   5394 
   5395         h_data_p->ep_id = ep_id;
   5396         h_data_p->uc_session_id = bhh_endpoint_index;
   5397  
   5398         sal_memcpy(&h_data_p->type, *oam_scache, 
   5399                    sizeof(bcm_oam_endpoint_type_t));
   5400         *oam_scache = (*oam_scache + sizeof(bcm_oam_endpoint_type_t));
   5401         sal_memcpy(&h_data_p->group_index, *oam_scache, 
   5402                    sizeof(bcm_oam_group_t));
   5403         *oam_scache = (*oam_scache + sizeof(bcm_oam_group_t));
   5404         sal_memcpy(&h_data_p->gport, *oam_scache, 
   5405                    sizeof(bcm_gport_t));
   5406         *oam_scache = (*oam_scache + sizeof(bcm_gport_t));
   5407         sal_memcpy(&h_data_p->egr_label, *oam_scache, 
   5408                    sizeof(bcm_mpls_label_t));
   5409         *oam_scache = (*oam_scache + sizeof(bcm_mpls_label_t));
   5410         sal_memcpy(&h_data_p->egr_label_exp, *oam_scache, 
   5411                    sizeof(uint8));
   5412         *oam_scache = (*oam_scache + sizeof(uint8));
   5413         sal_memcpy(&h_data_p->vpn, *oam_scache, 
   5414                    sizeof(bcm_vpn_t));
   5415         *oam_scache = (*oam_scache + sizeof(bcm_vpn_t));
   5416 
   5417         sal_memcpy(&h_data_p->egress_if, *oam_scache, 
   5418                    sizeof(bcm_if_t));
   5419         *oam_scache = (*oam_scache + sizeof(bcm_if_t));
   5420         sal_memcpy(&h_data_p->pm_profile_attached, *oam_scache, 
   5421                    sizeof(bcm_oam_pm_profile_t));
   5422         *oam_scache = (*oam_scache + sizeof(bcm_oam_pm_profile_t));
   5423         sal_memcpy(&h_data_p->ccm_tx_counter_size, *oam_scache, 
   5424                    sizeof(uint8));
   5425         *oam_scache = (*oam_scache + sizeof(uint8));
   5426         for (i = 0; i < h_data_p->ccm_tx_counter_size; i++) {
   5427             sal_memcpy(&h_data_p->ccm_tx_update_lm_counter_base_id[i],
   5428                        *oam_scache,
   5429                     sizeof(uint32));
   5430             *oam_scache = (*oam_scache + sizeof(uint32));
   5431         }
   5432         for (i = 0; i < h_data_p->ccm_tx_counter_size; i++) {
   5433             sal_memcpy(&h_data_p->ccm_tx_update_lm_counter_offset[i],
   5434                        *oam_scache,
   5435                     sizeof(uint32));
   5436             *oam_scache = (*oam_scache + sizeof(uint32));
   5437         }
   5438         sal_memcpy(&h_data_p->lm_counter_size, *oam_scache, 
   5439                    sizeof(uint8));
   5440         *oam_scache = (*oam_scache + sizeof(uint8));
   5441         for (i = 0; i < h_data_p->lm_counter_size; i++) {
   5442             sal_memcpy(&h_data_p->lm_counter_base_id[i],
   5443                        *oam_scache,
   5444                     sizeof(uint32));
   5445             *oam_scache = (*oam_scache + sizeof(uint32));
   5446         }
   5447         for (i = 0; i < h_data_p->lm_counter_size; i++) {
   5448             sal_memcpy(&h_data_p->lm_counter_offset[i],
   5449                        *oam_scache,
   5450                     sizeof(uint32));
   5451             *oam_scache = (*oam_scache + sizeof(uint32));
   5452         }
   5453         for (i = 0; i < h_data_p->lm_counter_size; i++) {
   5454             sal_memcpy(&h_data_p->lm_counter_action[i],
   5455                        *oam_scache,
   5456                     sizeof(uint32));
   5457             *oam_scache = (*oam_scache + sizeof(uint32));
   5458         }
   5459         sal_memcpy(&h_data_p->lb_tx_counter_size, *oam_scache, 
   5460                    sizeof(uint8));
   5461         *oam_scache = (*oam_scache + sizeof(uint8));
   5462         for (i = 0; i < h_data_p->lb_tx_counter_size; i++) {
   5463             sal_memcpy(&h_data_p->lb_tx_update_lm_counter_base_id[i],
   5464                        *oam_scache,
   5465                     sizeof(uint32));
   5466             *oam_scache = (*oam_scache + sizeof(uint32));
   5467         }
   5468         for (i = 0; i < h_data_p->lb_tx_counter_size; i++) {
   5469             sal_memcpy(&h_data_p->lb_tx_update_lm_counter_offset[i],
   5470                        *oam_scache,
   5471                     sizeof(uint32));
   5472             *oam_scache = (*oam_scache + sizeof(uint32));
   5473         }
   5474         sal_memcpy(&h_data_p->dm_tx_counter_size, *oam_scache, 
   5475                    sizeof(uint8));
   5476         *oam_scache = (*oam_scache + sizeof(uint8));
   5477         for (i = 0; i < h_data_p->dm_tx_counter_size; i++) {
   5478             sal_memcpy(&h_data_p->dm_tx_update_lm_counter_base_id[i],
   5479                        *oam_scache,
   5480                     sizeof(uint32));
   5481             *oam_scache = (*oam_scache + sizeof(uint32));
   5482         }
   5483         for (i = 0; i < h_data_p->dm_tx_counter_size; i++) {
   5484             sal_memcpy(&h_data_p->dm_tx_update_lm_counter_offset[i],
   5485                        *oam_scache,
   5486                     sizeof(uint32));
   5487             *oam_scache = (*oam_scache + sizeof(uint32));
   5488         }
   5489         sal_memcpy(&h_data_p->hw_session_id, *oam_scache, 
   5490                    sizeof(uint32));
   5491         *oam_scache = (*oam_scache + sizeof(uint32));
   5492         sal_memcpy(&h_data_p->hw_session_num_entries, *oam_scache, 
   5493                    sizeof(uint8));
   5494         *oam_scache = (*oam_scache + sizeof(uint8));
   5495         sal_memcpy(&h_data_p->trunk_index, *oam_scache, 
   5496                    sizeof(int));
   5497         *oam_scache = (*oam_scache + sizeof(int));
   5498 
   5499         h_data_p->level = _BCM_OAM_EP_LEVEL_MAX;
   5500         /* Get the endpoint parameters from firmware */
   5501         rv = _bcm_fp_oam_msg_send_receive(unit,
   5502                 MOS_MSG_CLASS_BHH, 
   5503                 MOS_MSG_SUBCLASS_BHH_SESS_GET,
   5504                 bhh_endpoint_index, 0,
   5505                 MOS_MSG_SUBCLASS_BHH_SESS_GET_REPLY,
   5506                 &reply_len);
   5507         if (BCM_FAILURE(rv)) {
   5508             LOG_ERROR(BSL_LS_BCM_OAM,
   5509                     (BSL_META_U(unit,
   5510                                 "BHH(unit %d) Error: ukernel msg " 
   5511                                 "failed for"
   5512                                 " EP=%d %s.\n"), unit, 
   5513                      bhh_endpoint_index, 
   5514                      bcm_errmsg(rv)));
   5515             goto cleanup;
   5516         }
   5517 
   5518         buffer = oc->bhh_dma_buffer;
   5519         buffer_ptr = bhh_sdk_msg_ctrl_sess_get_unpack(buffer, &msg);
   5520         buffer_len = buffer_ptr - buffer;
   5521 
   5522         if (reply_len != buffer_len) {
   5523             rv = BCM_E_INTERNAL;
   5524             LOG_ERROR(BSL_LS_BCM_OAM,
   5525                     (BSL_META_U(unit,
   5526                                 "BHH(unit %d) Error: ukernel msg " 
   5527                                 "failed for"
   5528                                 " EP=%d %s.\n"), unit, 
   5529                      bhh_endpoint_index, 
   5530                      bcm_errmsg(rv)));
   5531             goto cleanup;
   5532         }
   5533 
   5534         h_data_p->name = msg.mep_id;
   5535         h_data_p->period = msg.local_period;
   5536         h_data_p->label = msg.mpls_label;
   5537         /* Set the flags */
   5538         if (msg.flags & SHR_BHH_SESS_SET_F_MIP)
   5539             h_data_p->flags |= BCM_OAM_ENDPOINT_INTERMEDIATE;
   5540 
   5541         if (!BHH_EP_MPLS_SECTION_TYPE(h_data_p)) {
   5542             /* port value from l3_egress_if*/
   5543             bcm_l3_egress_t_init(&l3_egress);
   5544             if (BCM_FAILURE (bcm_esw_l3_egress_get(unit,
   5545                             h_data_p->egress_if, &l3_egress))) {
   5546                 LOG_ERROR(BSL_LS_BCM_OAM,
   5547                         (BSL_META_U(unit,
   5548                                     "BHH(unit %d) Error: Failed to get L3 "
   5549                                     "egress object EP=%d egress_if=%d %s.\n"),
   5550                                     unit, bhh_endpoint_index,
   5551                          h_data_p->egress_if, bcm_errmsg(rv)));
   5552                 goto cleanup;
   5553             }
   5554 
   5555             l3_intf.l3a_intf_id = l3_egress.intf;
   5556             if (BCM_FAILURE(bcm_esw_l3_intf_get(unit, &l3_intf))) {
   5557                 LOG_ERROR(BSL_LS_BCM_OAM,
   5558                         (BSL_META_U(unit,
   5559                                     "BHH(unit %d) Error: Failed to get L3 "
   5560                                     " interface EP=%d l3a_intf_id=%d %s.\n"),
   5561                                     unit, bhh_endpoint_index,
   5562                          l3_intf.l3a_intf_id, bcm_errmsg(rv)));
   5563                 goto cleanup;
   5564             }
   5565             sal_memcpy(h_data_p->dst_mac_address, l3_egress.mac_addr,
   5566                        _BHH_MAC_ADDR_LENGTH);
   5567             sal_memcpy(h_data_p->src_mac_address, l3_intf.l3a_mac_addr,
   5568                        _BHH_MAC_ADDR_LENGTH);
   5569 
   5570             h_data_p->sglp = l3_egress.port;
   5571             h_data_p->dglp = l3_egress.port;
   5572             h_data_p->vlan = l3_intf.l3a_vid;
   5573         } else {
   5574             encap_data = msg.encap_data;
   5575             encap_data = _bcm_fp_oam_olp_l2_header_unpack(encap_data, 
   5576                                                           &olp_l2_header);
   5577             encap_data = shr_olp_tx_header_unpack(encap_data,
   5578                                                   &olp_oam_tx_header);
   5579             h_data_p->int_pri = SOC_OLP_TX_PRI_GET(&olp_oam_tx_header);
   5580             sal_memcpy(h_data_p->dst_mac_address, encap_data,
   5581                        _BHH_MAC_ADDR_LENGTH);
   5582             encap_data += _BHH_MAC_ADDR_LENGTH;
   5583 
   5584             sal_memcpy(h_data_p->src_mac_address, encap_data,
   5585                        _BHH_MAC_ADDR_LENGTH);
   5586             encap_data += _BHH_MAC_ADDR_LENGTH;
   5587             if((h_data_p->type == bcmOAMEndpointTypeBhhSectionOuterVlan) ||
   5588                (h_data_p->type == bcmOAMEndpointTypeBhhSectionInnervlan) ||
   5589                 (h_data_p->type == 
   5590                            bcmOAMEndpointTypeBhhSectionOuterPlusInnerVlan)){
   5591                  encap_data += SHR_BHH_L2_ETYPE_LENGTH;
   5592                  sal_memcpy(&h_data_p->vlan, encap_data, 
   5593                        SHR_BHH_L2_VLAN_HEADER_LENGTH);
   5594                  h_data_p->vlan = (h_data_p->vlan & _BHH_VLAN_MASK); 
   5595                  encap_data += SHR_BHH_L2_VLAN_HEADER_LENGTH;
   5596             }
   5597             if(h_data_p->type == 
   5598                          bcmOAMEndpointTypeBhhSectionOuterPlusInnerVlan){
   5599                  sal_memcpy(&h_data_p->inner_vlan, encap_data, 
   5600                        SHR_BHH_L2_VLAN_HEADER_LENGTH);
   5601                  h_data_p->inner_vlan = (h_data_p->vlan & _BHH_VLAN_MASK);
   5602                  encap_data += SHR_BHH_L2_VLAN_HEADER_LENGTH;
   5603             }
   5604         }
   5605         bhh_group_idx = BCM_OAM_BHH_GET_UKERNEL_GROUP(h_data_p->group_index);
   5606         /* Get the group memory pointer. */
   5607         group_p = &oc->bhh_group_data[bhh_group_idx];
   5608         if(msg.fault_flags & BHH_BTE_EVENT_CCM_TIMEOUT){
   5609             group_p->faults |= BCM_OAM_BHH_FAULT_CCM_TIMEOUT;
   5610         }
   5611         if(msg.fault_flags & BHH_BTE_EVENT_CCM_RDI){
   5612             group_p->faults |= BCM_OAM_BHH_FAULT_CCM_RDI;
   5613         }
   5614         if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_LEVEL){
   5615             group_p->faults |=
   5616                 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEG_LEVEL;
   5617         }
   5618         if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_ID){
   5619             group_p->faults |=
   5620                 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEG_ID;
   5621         }
   5622         if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_MEP_ID){
   5623             group_p->faults |=
   5624                 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEP_ID;
   5625         }
   5626         if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_PERIOD){
   5627             group_p->faults |=
   5628                 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_PERIOD;
   5629         }
   5630         if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_PRIORITY){
   5631             group_p->faults |=
   5632                 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_PRIORITY;
   5633         }
   5634 
   5635         if (h_data_p->type == bcmOAMEndpointTypeBHHMPLSVccv) {
   5636             /* get vccv_type from MPLS_ENTRY */
   5637             rv = _bcm_fp_oam_mpls_entry_label_lookup(unit, h_data_p->label,
   5638                     &mpls_index,
   5639                     &mpls_entry);
   5640             if(rv != BCM_E_NONE) {
   5641                 /* Not found or some other error */
   5642                 LOG_ERROR(BSL_LS_BCM_OAM,
   5643                         (BSL_META_U(unit,
   5644                                     "BHH(unit %d) Error: (Label=%u) - %s.\n"),
   5645                          unit, h_data_p->label, bcm_errmsg(rv)));
   5646                 goto cleanup;
   5647             }
   5648             h_data_p->vccv_type = soc_MPLS_ENTRYm_field32_get(unit, &mpls_entry,
   5649                                                               PW_CC_TYPEf);
   5650             h_data_p->vccv_type--;
   5651         }
   5652         rv = _bcm_fp_oam_endpoint_alloc(&ep_info);
   5653         if (BCM_FAILURE(rv)) {
   5654             goto cleanup;
   5655         }
   5656 
   5657         bcm_oam_endpoint_info_t_init(ep_info);
   5658 
   5659         /* Set up endpoint information for key construction. */
   5660         ep_info->group = h_data_p->group_index;
   5661         ep_info->name = h_data_p->name;
   5662         ep_info->gport = h_data_p->gport;
   5663         ep_info->level = h_data_p->level;
   5664         ep_info->vlan = h_data_p->vlan;
   5665         ep_info->inner_vlan = h_data_p->inner_vlan;
   5666         ep_info->mpls_label = h_data_p->label;
   5667         ep_info->type       = h_data_p->type;
   5668         ep_info->trunk_index = h_data_p->trunk_index;
   5669         ep_info->ccm_period = h_data_p->period;
   5670 
   5671         /* Resolve given endpoint gport value to SGLP and DGLP values. */
   5672         rv = _bcm_fp_oam_endpoint_gport_resolve(unit, ep_info,
   5673                                                 &sglp, &dglp, &dgpp,
   5674                                                 &trunk_id, &trunk_member);
   5675         if (BCM_FAILURE(rv)) {
   5676             LOG_ERROR(BSL_LS_BCM_OAM,
   5677                       (BSL_META_U(unit,
   5678                           "OAM(unit %d) Error: Gport resolve (EP=%d) - %s.\n"),
   5679                        unit, h_data_p->ep_id, bcm_errmsg(rv)));
   5680             _BCM_OAM_UNLOCK(oc);
   5681             return (rv);
   5682         }
   5683         if (BCM_TRUNK_INVALID != trunk_id) {
   5684             h_data_p->trunk_id = trunk_id;
   5685             h_data_p->resolved_trunk_gport = trunk_member.gport;
   5686         }
   5687         /*
   5688          * Calculate hash key for hash table insert
   5689          * operation.
   5690          */
   5691         _bhh_fp_oam_ep_hash_key_construct(unit, oc, ep_info, &hash_key);
   5692 
   5693         sal_free(ep_info);
   5694 
   5695         rv = shr_htb_insert(oc->bhh_mep_htbl, hash_key, h_data_p);
   5696         if (BCM_FAILURE(rv)) {
   5697             LOG_ERROR(BSL_LS_BCM_OAM,
   5698                     (BSL_META_U(unit,
   5699                                 "BHH(unit %d) Error: Hash table insert"
   5700                                 "(EP=%d) failed - %s.\n"), unit,
   5701                      h_data_p->ep_id, bcm_errmsg(rv)));
   5702             goto cleanup;
   5703         } else {
   5704             LOG_DEBUG(BSL_LS_BCM_OAM,
   5705                     (BSL_META_U(unit,
   5706                                 "BHH(unit %d) Info: Hash Tbl (EP=%d)"
   5707                                 " inserted  - %s.\n"), unit, h_data_p->ep_id,
   5708                      bcm_errmsg(rv)));
   5709         }
   5710         h_data_p->in_use = 1;
   5711     } /* end of for loop */
   5712 
   5713     LOG_DEBUG(BSL_LS_BCM_OAM,
   5714               (BSL_META_U(unit,
   5715                           "OAM(unit %d) Info: _bcm_fp_oam_wb_endpoints_recover"
   5716                            " - done.\n"), unit));
   5717     return (BCM_E_NONE);
   5718 
   5719 cleanup:
   5720 
   5721     if (NULL != ep_info) {
   5722         sal_free(ep_info);
   5723     }
   5724 
   5725     if (BCM_E_EXISTS
   5726          == shr_idxres_list_elem_state(oc->bhh_pool,bhh_endpoint_index)) {
   5727             shr_idxres_list_free(oc->bhh_pool,bhh_endpoint_index);
   5728     }
   5729 
   5730     _BHH_FP_OAM_HASH_DATA_CLEAR(h_data_p);
   5731 
   5732     LOG_DEBUG(BSL_LS_BCM_OAM,
   5733               (BSL_META_U(unit,
   5734                           "OAM(unit %d) Info: _bcm_fp_oam_wb_endpoints_recover"
   5735                            " - error_done.\n"), unit));
   5736     return (rv);
   5737 
   5738 }
   5739 
   5740 /*
   5741  * Function:
   5742  *     _bcm_fp_oam_wb_csf_recover
   5743  * Purpose:
   5744  *     Recover BHH OAM CSF configuration
   5745  * Parameters:
   5746  *     unit        - (IN) BCM device number
   5747  *     stable_size - OAM module Level2 memory size.
   5748  *     oam_scache  - Pointer to secondary storage buffer pointer.
   5749  * Returns:
   5750  *     BCM_E_XXX
   5751  */
   5752 STATIC int
   5753 _bcm_fp_oam_bhh_wb_csf_recover(int unit, int stable_size, uint8 **oam_scache)
   5754 {
   5755     _bhh_fp_oam_ep_data_t  *h_data_p = NULL;
   5756     _bcm_fp_oam_control_t  *oc;
   5757     int                     idx, i;
   5758 
   5759 
   5760     LOG_DEBUG(BSL_LS_BCM_OAM,
   5761               (BSL_META_U(unit,
   5762                           "OAM(unit %d) Info: "
   5763                           "_bcm_fp_oam_bhh_wb_csf_recover.\n"), unit));
   5764     /*
   5765      * Get OAM control structure.
   5766      *     Note: Lock taken by calling routine.
   5767      */
   5768     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
   5769 
   5770     for (idx = 0; idx < oc->bhh_endpoint_count; idx++) {
   5771 
   5772         h_data_p = &oc->bhh_ep_data[idx];
   5773         if (!h_data_p->in_use) {
   5774             continue;
   5775         }
   5776 
   5777         sal_memcpy(&h_data_p->csf_tx_counter_size, *oam_scache, sizeof(uint8));
   5778         *oam_scache += sizeof(uint8);
   5779 
   5780         for (i = 0; i < BCM_OAM_LM_COUNTER_MAX; i++) {
   5781             sal_memcpy(&h_data_p->csf_tx_update_lm_counter_base_id[i],
   5782                        *oam_scache, sizeof(uint32));
   5783             *oam_scache += sizeof(uint32);
   5784         }
   5785         for (i = 0; i < BCM_OAM_LM_COUNTER_MAX; i++) {
   5786             sal_memcpy(&h_data_p->csf_tx_update_lm_counter_offset[i],
   5787                        *oam_scache, sizeof(uint32));
   5788             *oam_scache += sizeof(uint32);
   5789         }
   5790     }
   5791     return BCM_E_NONE;
   5792 }
   5793 
   5794 /*
   5795  * Function:
   5796  *     _bcm_fp_oam_bhh_reinit
   5797  * Purpose:
   5798  *     Reconstruct BHH software state.
   5799  * Parameters:
   5800  *     unit - (IN) BCM device number
   5801  * Retruns:
   5802  *     BCM_E_XXX
   5803  */
   5804 STATIC int
   5805 _bcm_fp_oam_bhh_reinit(int unit)
   5806 {
   5807     int                 stable_size;       /* Secondary storage size.   */
   5808     uint8               *oam_scache = NULL;/* Pointer to scache memory. */
   5809     soc_scache_handle_t scache_handle;     /* Scache memory handler.    */
   5810     _bcm_fp_oam_control_t  *oc;            /* Pointer to OAM control structure*/
   5811     int                 rv = BCM_E_NONE;   /* Operation return status.     */
   5812     uint16              recovered_ver = 0;
   5813     uint16              csf_cntr_size = 0;
   5814     uint32              realloc_size = 0;
   5815     uint16              ttl_cntr_size = 0;
   5816 
   5817     LOG_DEBUG(BSL_LS_BCM_OAM,
   5818               (BSL_META_U(unit,
   5819                           "OAM(unit %d) Info: OAM warm boot recovery.....\n"),
   5820                unit));
   5821 
   5822     SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size));
   5823 
   5824     /* Get OAM control structure. */
   5825     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
   5826 
   5827     _BCM_OAM_LOCK(oc);
   5828 
   5829     if (oc->ukernel_not_ready) {
   5830         _BCM_OAM_UNLOCK(oc);
   5831         return BCM_E_NONE;
   5832     }
   5833     if (!SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit) && (stable_size > 0)) {
   5834 
   5835         SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_OAM,
   5836                               bcmFpOamWbSequenceBhh);
   5837 
   5838         rv = _bcm_esw_scache_ptr_get(unit, scache_handle, 0, 0,
   5839                                      &oam_scache, BCM_WB_BHH_DEFAULT_VERSION,
   5840                                      &recovered_ver);
   5841         if (BCM_E_NOT_FOUND == rv) {
   5842             /* Upgrading from SDK release that does not have warmboot state */
   5843             _bcm_fp_oam_bhh_scache_alloc(unit);
   5844             rv = BCM_E_NONE;
   5845             goto cleanup;
   5846         } else if (BCM_FAILURE(rv)) {
   5847             goto cleanup;
   5848         }
   5849     } else {
   5850         rv = BCM_E_NONE;
   5851         goto cleanup;
   5852     }
   5853 
   5854     rv = _bcm_fp_oam_wb_group_recover(unit, stable_size, &oam_scache);
   5855     if (BCM_FAILURE(rv)) {
   5856         LOG_ERROR(BSL_LS_BCM_OAM,
   5857                   (BSL_META_U(unit,
   5858                               "OAM(unit %d) Error: Group recovery failed  - "
   5859                               "%s.\n"),
   5860                    unit, bcm_errmsg(rv)));
   5861         goto cleanup;
   5862     }
   5863 
   5864     rv = _bcm_fp_oam_wb_endpoints_recover(unit, stable_size, &oam_scache);
   5865     if (BCM_FAILURE(rv)) {
   5866         LOG_ERROR(BSL_LS_BCM_OAM,
   5867                   (BSL_META_U(unit,
   5868                               "OAM(unit %d) Error: Endpoint recovery failed  "
   5869                               "- %s.\n"),
   5870                    unit, bcm_errmsg(rv)));
   5871         goto cleanup;
   5872     }
   5873     if (_BCM_FP_OAM_PM_BHH_DATA_COLLECTION_MODE_IS_PROCESSED(oc)) {
   5874         int itr;
   5875         _bcm_fp_oam_pm_profile_control_t *pmc = NULL;
   5876 
   5877         pmc = pm_profile_control[unit];
   5878         if (!pmc) {
   5879             rv = BCM_E_INIT;
   5880             goto cleanup;
   5881         }
   5882         for(itr = 0; itr < _BCM_OAM_MAX_PM_PROFILES; itr++) {
   5883             sal_memcpy(&(pmc->profile_info[itr]), oam_scache,
   5884                        sizeof(_bcm_fp_oam_pm_profile_int_info_t));
   5885             oam_scache += sizeof(_bcm_fp_oam_pm_profile_int_info_t);
   5886         }
   5887     }
   5888 
   5889     if (recovered_ver >= BCM_BHH_WB_VERSION_1_2) {
   5890         int idx = 0;
   5891         _bhh_fp_oam_ep_data_t *h_data_p = NULL; /* Endpoint hash data pointer. */
   5892         for (idx = 0; idx < oc->bhh_endpoint_count; idx++) {
   5893             h_data_p = &oc->bhh_ep_data[idx];
   5894             if (!h_data_p->in_use) {
   5895                 continue;
   5896             }
   5897 
   5898             sal_memcpy(&h_data_p->egr_label_ttl, oam_scache,
   5899                     sizeof(uint8));
   5900             oam_scache = (oam_scache + sizeof(uint8));
   5901             ttl_cntr_size += sizeof(uint8);
   5902         }
   5903     }
   5904 
   5905     if (recovered_ver >= BCM_BHH_WB_VERSION_1_1) {
   5906         rv = _bcm_fp_oam_bhh_wb_csf_recover(unit, stable_size, &oam_scache);
   5907         if (BCM_FAILURE(rv)) {
   5908             LOG_ERROR(BSL_LS_BCM_OAM,
   5909                       (BSL_META_U(unit,
   5910                                   "OAM(unit %d) Error: CSF recovery failed  "
   5911                                   "- %s.\n"),
   5912                        unit, bcm_errmsg(rv)));
   5913             goto cleanup;
   5914         }
   5915     }
   5916 
   5917     if (recovered_ver >= BCM_BHH_WB_VERSION_1_3) {
   5918         sal_memcpy(&fp_oam_mpls_tp_ach_channel_type, oam_scache,
   5919                    sizeof(fp_oam_mpls_tp_ach_channel_type));
   5920         oam_scache += sizeof(fp_oam_mpls_tp_ach_channel_type);
   5921     }
   5922 
   5923     /* Increase scache size, in case of upgrading from older version */
   5924     if (recovered_ver < BCM_BHH_WB_VERSION_1_1) {
   5925         /* v1.1 add csf counters to scache */
   5926 
   5927         /* Calculate size taken to accomadate CSF counters */
   5928         csf_cntr_size = 0;
   5929         /* Store CSF TX counter size */
   5930         csf_cntr_size += sizeof(uint8);
   5931         /* Store CSF TX counters base_ids */
   5932         csf_cntr_size += sizeof(uint32) * BCM_OAM_LM_COUNTER_MAX;
   5933         /* Store CSF TX counters offsets */
   5934         csf_cntr_size += sizeof(uint32) * BCM_OAM_LM_COUNTER_MAX;
   5935         /* Counters are per-endpoint */
   5936         csf_cntr_size *= oc->bhh_endpoint_count;
   5937 
   5938         realloc_size +=  csf_cntr_size;
   5939     }
   5940 
   5941     /* Increase scache size, in case of upgrading from older version */
   5942     if (recovered_ver < BCM_BHH_WB_VERSION_1_2) {
   5943         /* v1.2 add csf counters to scache */
   5944         realloc_size +=  ttl_cntr_size;
   5945     }
   5946 
   5947     if (recovered_ver < BCM_BHH_WB_VERSION_1_3) {
   5948         /* Store the BHH ACH Channel Type */
   5949         realloc_size += sizeof(fp_oam_mpls_tp_ach_channel_type);
   5950     }
   5951 
   5952     if (realloc_size > 0) {
   5953         SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_OAM,
   5954                               bcmFpOamWbSequenceBhh);
   5955         rv = soc_scache_realloc(unit, scache_handle, realloc_size);
   5956         if (SOC_FAILURE(rv)) {
   5957             LOG_ERROR(BSL_LS_BCM_OAM,
   5958                     (BSL_META_U(unit,"OAM Error: scache alloc failed  - %s.\n"),
   5959                      bcm_errmsg(rv)));
   5960             goto cleanup;
   5961         }
   5962     }
   5963 
   5964 cleanup:
   5965     _BCM_OAM_UNLOCK(oc);
   5966     return (rv);
   5967 }
   5968 
   5969 #endif
   5970 
   5971 STATIC uint8
   5972 bcm_fp_oam_bhh_get_oam_exp_from_encap(_bhh_fp_oam_ep_data_t *h_data_p,
   5973                                       uint8 *encap_data, uint16 encap_length)
   5974 {
   5975     uint16        oam_label_offset = 0;
   5976     _mpls_label_t label;
   5977 
   5978     if (BHH_EP_MPLS_SECTION_TYPE(h_data_p)) {
   5979         /* Go back ACH and GAL */
   5980         oam_label_offset = encap_length -
   5981                            (SHR_BHH_ACH_LENGTH + SHR_BHH_MPLS_LABEL_LENGTH);
   5982     } else if (BHH_EP_LSP_TYPE(h_data_p)) {
   5983         /* Go back ACH + GAL + OAM label */
   5984         oam_label_offset = encap_length -
   5985                           (SHR_BHH_ACH_LENGTH + (SHR_BHH_MPLS_LABEL_LENGTH * 2));
   5986     } else { /* PW */
   5987         if (h_data_p->vccv_type == bcmOamBhhVccvGal13) {
   5988             /* Go back ACH + GAL + PW label */
   5989             oam_label_offset = encap_length -
   5990                           (SHR_BHH_ACH_LENGTH + (SHR_BHH_MPLS_LABEL_LENGTH * 2));
   5991         } else {
   5992             /* Go back ACH and PW label */
   5993             oam_label_offset = encap_length -
   5994                                (SHR_BHH_ACH_LENGTH + SHR_BHH_MPLS_LABEL_LENGTH);
   5995         }
   5996     }
   5997 
   5998     _bcm_fp_oam_mpls_label_unpack(&(encap_data[oam_label_offset]), &label);
   5999     return label.exp;
   6000 }
   6001 /*
   6002  * Function:
   6003  *     _bcm_fp_oam_bhh_group_create
   6004  * Purpose:
   6005  *     Create or replace a BHH group object
   6006  * Parameters:
   6007  *     unit       - (IN) BCM device number
   6008  *     group_info - (IN/OUT) Pointer to an OAM group information.
   6009  * Returns:
   6010  *     BCM_E_XXX
   6011  */
   6012 int
   6013 _bcm_fp_oam_bhh_group_create(int unit, bcm_oam_group_info_t *group_info)
   6014 {
   6015     _bcm_fp_oam_control_t *oc = NULL;           /* OAM control structure */
   6016     _bhh_fp_oam_group_data_t *oam_group = NULL; /* OAM Group being created */
   6017     int rv = 0;                                 /* return value */
   6018     int bhh_group_idx = 0;
   6019     uint32 session_flags = 0;
   6020     bhh_sdk_msg_ctrl_sess_set_t msg_sess;
   6021     uint16 buffer_len, reply_len;
   6022     uint8 *buffer = NULL;
   6023     uint8 *buffer_ptr = NULL;
   6024 
   6025     /* Validate input parameter. */
   6026     if (NULL == group_info) {
   6027         return (BCM_E_PARAM);
   6028     }
   6029 
   6030     /* Get OAM control structure handle. */
   6031     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
   6032     if (oc->ukernel_not_ready == 1){
   6033         LOG_ERROR(BSL_LS_BCM_OAM,
   6034                 (BSL_META_U(unit,
   6035                             "OAM(unit %d) Error: BTE(ukernel) "
   6036                             "not ready.\n"), unit));
   6037         return (BCM_E_INIT);
   6038     }
   6039     /* Validate group id. */
   6040     if (group_info->flags & BCM_OAM_GROUP_WITH_ID) {
   6041         _BCM_FP_OAM_BHH_GROUP_INDEX_VALIDATE(group_info->id);
   6042     }
   6043 
   6044     _BCM_OAM_LOCK(oc);
   6045 
   6046     /*
   6047      * If MA group create is called with replace flag bit set.
   6048      *  - Check and return error if a group does not exist with the ID.
   6049      */
   6050     if (group_info->flags & BCM_OAM_GROUP_REPLACE) {
   6051         if (group_info->flags & BCM_OAM_GROUP_WITH_ID) {
   6052             bhh_group_idx = BCM_OAM_BHH_GET_UKERNEL_GROUP(group_info->id);
   6053             /* Search the list with the MA Group ID value. */
   6054             rv = shr_idxres_list_elem_state(oc->bhh_group_pool, bhh_group_idx);
   6055             if (BCM_E_EXISTS != rv) {
   6056                 _BCM_OAM_UNLOCK(oc);
   6057                 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit,
   6058                           "OAM Error: Group does not exist.\n")));
   6059                 return (BCM_E_PARAM);
   6060             }
   6061         } else {
   6062             _BCM_OAM_UNLOCK(oc);
   6063             LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit,
   6064                       "OAM Error: Replace command needs a valid Group ID.\n")));
   6065             return (BCM_E_PARAM);
   6066         }
   6067     } else if (group_info->flags & BCM_OAM_GROUP_WITH_ID) {
   6068         bhh_group_idx = BCM_OAM_BHH_GET_UKERNEL_GROUP(group_info->id);
   6069         /*
   6070          * If MA group create is called with ID flag bit set.
   6071          *  - Check and return error if the ID is already in use.
   6072          */
   6073         rv = shr_idxres_list_reserve(oc->bhh_group_pool, bhh_group_idx,
   6074                                      bhh_group_idx);
   6075         if (BCM_FAILURE(rv)) {
   6076             _BCM_OAM_UNLOCK(oc);
   6077             return ((rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv);
   6078         }
   6079     } else {
   6080         /* Reserve the next available group index. */
   6081          rv = shr_idxres_list_alloc(oc->bhh_group_pool,
   6082                                     (shr_idxres_element_t *) &bhh_group_idx);
   6083         if (BCM_FAILURE(rv)) {
   6084             _BCM_OAM_UNLOCK(oc);
   6085             LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit,
   6086                       "OAM Error: Group allocation (GID=%d) %s\n"),
   6087                       group_info->id, bcm_errmsg(rv)));
   6088             return (rv);
   6089         }
   6090         group_info->id = BCM_OAM_BHH_GET_SDK_GROUP(bhh_group_idx);
   6091     }
   6092 
   6093     /* Get this group memory to store group information. */
   6094     oam_group = &(oc->bhh_group_data[bhh_group_idx]);
   6095     
   6096     /* Store the group name. */
   6097     sal_memcpy(oam_group->name, group_info->name,
   6098             BCM_OAM_GROUP_NAME_LENGTH);
   6099 
   6100     /* Store the group flags. */
   6101     oam_group->flags = group_info->flags;
   6102 
   6103     /* Set LMEP as not configured */
   6104     oam_group->lmep_id = _BHH_FP_OAM_INVALID_LMEP_ID;
   6105 
   6106     oam_group->group_id = group_info->id;
   6107 
   6108     oam_group->in_use = 1;
   6109 
   6110     if (group_info->flags & BCM_OAM_GROUP_REPLACE) {
   6111         /* Send message to uC to set the Soft RDI   */
   6112         if (group_info->flags & BCM_OAM_GROUP_REMOTE_DEFECT_TX) {
   6113 
   6114             /* Set the RDI flag in session bits */
   6115             session_flags |= SHR_BHH_SESS_SET_F_RDI;
   6116 
   6117             /* Get the session is from endpoint */
   6118             msg_sess.sess_id =
   6119                 BCM_OAM_BHH_GET_UKERNEL_EP(oam_group->lmep_id);
   6120 
   6121             /* Pack control message data into DMA buffer */
   6122             msg_sess.flags = session_flags;
   6123 
   6124             buffer     = oc->bhh_dma_buffer;
   6125             buffer_ptr =
   6126                 bhh_sdk_msg_ctrl_sess_set_pack(buffer, &msg_sess);
   6127             buffer_len = buffer_ptr - buffer;
   6128 
   6129             /* Send BHH Session Update message to uC */
   6130             rv =  _bcm_fp_oam_msg_send_receive(unit,
   6131                     MOS_MSG_CLASS_BHH, 
   6132                     MOS_MSG_SUBCLASS_BHH_SESS_SET,
   6133                     buffer_len, 0,
   6134                     MOS_MSG_SUBCLASS_BHH_SESS_SET_REPLY,
   6135                     &reply_len);
   6136             if (BCM_FAILURE(rv)) {
   6137                 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit,
   6138                                 "OAM(unit %d) Error: ukernel msg failed for"
   6139                                 "%s.\n"), unit, bcm_errmsg(rv)));
   6140                 _BCM_OAM_UNLOCK(oc);
   6141                 return (BCM_E_INTERNAL);
   6142             }
   6143         }
   6144     }
   6145 
   6146     _BCM_OAM_UNLOCK(oc);
   6147     return rv;
   6148 }
   6149 
   6150 /*
   6151  * Function:
   6152  *     _bcm_fp_oam_bhh_group_get
   6153  * Purpose:
   6154  *     Get a BHH group object.
   6155  * Parameters:
   6156  *     unit       - (IN) BCM device number
   6157  *     group_info - (IN/OUT) Pointer to an OAM group Id.
   6158  * Returns:
   6159  *     BCM_E_XXX
   6160  */
   6161 int
   6162 _bcm_fp_oam_bhh_group_get(int unit, bcm_oam_group_info_t *group_info) {
   6163 
   6164     _bcm_fp_oam_control_t *oc = NULL;           /* OAM control structure */
   6165     _bhh_fp_oam_group_data_t *group_p;          /* Handle to S/w Group Data */
   6166     int rv = 0;                                 /* Return Value */
   6167     uint16 buffer_len, reply_len;
   6168     uint8 *buffer = NULL;
   6169     uint8 *buffer_ptr = NULL;
   6170     bhh_sdk_msg_ctrl_sess_get_t msg;
   6171     int bhh_group_idx = 0;
   6172     int sess_id = 0;
   6173 
   6174     /* Get OAM control structure handle. */
   6175     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
   6176 
   6177 
   6178     bhh_group_idx = BCM_OAM_BHH_GET_UKERNEL_GROUP(group_info->id);
   6179     /* Get Handle to Local DB */
   6180     group_p = &(oc->bhh_group_data[bhh_group_idx]);
   6181     if (!(group_p->in_use)) {
   6182         return BCM_E_NOT_FOUND;
   6183     }
   6184 
   6185     if (group_p->lmep_id != _BHH_FP_OAM_INVALID_LMEP_ID) {
   6186         sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(group_p->lmep_id);
   6187         rv = _bcm_fp_oam_msg_send_receive(unit,
   6188                 MOS_MSG_CLASS_BHH, 
   6189                 MOS_MSG_SUBCLASS_BHH_SESS_GET,
   6190                 sess_id, 0,
   6191                 MOS_MSG_SUBCLASS_BHH_SESS_GET_REPLY,
   6192                 &reply_len);
   6193         if (BCM_FAILURE(rv)) {
   6194             LOG_ERROR(BSL_LS_BCM_OAM,
   6195                     (BSL_META_U(unit,
   6196                                 "OAM(unit %d) Error: ukernel msg failed for"
   6197                                 " EP=%d %s.\n"), unit, group_p->lmep_id, 
   6198                      bcm_errmsg(rv)));
   6199             return (rv);
   6200         }
   6201 
   6202         /* Pack control message data into DMA buffer */
   6203         buffer = oc->bhh_dma_buffer;
   6204         buffer_ptr = bhh_sdk_msg_ctrl_sess_get_unpack(buffer, &msg);
   6205         buffer_len = buffer_ptr - buffer;
   6206 
   6207         if (reply_len != buffer_len) {
   6208             rv = BCM_E_INTERNAL;
   6209             LOG_ERROR(BSL_LS_BCM_OAM,
   6210                     (BSL_META_U(unit,
   6211                                 "OAM(unit %d) Error: ukernel msg failed for"
   6212                                 " EP=%d %s.\n"), unit, group_p->lmep_id, 
   6213                      bcm_errmsg(rv)));
   6214             return (rv);
   6215         } else {
   6216 
   6217             if(msg.fault_flags & BHH_BTE_EVENT_CCM_TIMEOUT){
   6218                 group_info->faults |= BCM_OAM_BHH_FAULT_CCM_TIMEOUT;
   6219             }  
   6220             if(msg.fault_flags & BHH_BTE_EVENT_CCM_RDI){
   6221                 group_info->faults |= BCM_OAM_BHH_FAULT_CCM_RDI;
   6222             }  
   6223             if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_LEVEL){
   6224                 group_info->faults |= 
   6225                     BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEG_LEVEL;
   6226             }  
   6227             if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_ID){
   6228                 group_info->faults |= 
   6229                     BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEG_ID;
   6230             }  
   6231             if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_MEP_ID){
   6232                 group_info->faults |= 
   6233                     BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEP_ID;
   6234             }  
   6235             if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_PERIOD){
   6236                 group_info->faults |= 
   6237                     BCM_OAM_BHH_FAULT_CCM_UNKNOWN_PERIOD;
   6238             }  
   6239             if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_PRIORITY){
   6240                 group_info->faults |= 
   6241                     BCM_OAM_BHH_FAULT_CCM_UNKNOWN_PRIORITY;
   6242             }  
   6243             if(msg.fault_flags & BHH_BTE_EVENT_CSF_LOS) {
   6244                 group_info->faults |= BCM_OAM_ENDPOINT_BHH_FAULT_CSF_LOS;
   6245             }
   6246             if(msg.fault_flags & BHH_BTE_EVENT_CSF_FDI) {
   6247                 group_info->faults |= BCM_OAM_ENDPOINT_BHH_FAULT_CSF_FDI;
   6248             }
   6249             if(msg.fault_flags & BHH_BTE_EVENT_CSF_RDI) {
   6250                 group_info->faults |= BCM_OAM_ENDPOINT_BHH_FAULT_CSF_RDI;
   6251             }
   6252         }
   6253     }
   6254     sal_memcpy(group_info->name, group_p->name, BCM_OAM_GROUP_NAME_LENGTH);
   6255     group_info->flags = group_p->flags;
   6256 
   6257     return rv;
   6258 }
   6259 
   6260 #define _BCM_FP_OAM_MAX_CCM_INTERVALS 8
   6261 /*  
   6262  * FP OAM CCM intervals array initialization..
   6263  */ 
   6264 STATIC uint32 _fp_oam_ccm_intervals[] =
   6265 {
   6266     BCM_OAM_ENDPOINT_CCM_PERIOD_DISABLED,
   6267     BCM_OAM_ENDPOINT_CCM_PERIOD_3MS,
   6268     BCM_OAM_ENDPOINT_CCM_PERIOD_10MS,
   6269     BCM_OAM_ENDPOINT_CCM_PERIOD_100MS,
   6270     BCM_OAM_ENDPOINT_CCM_PERIOD_1S,
   6271     BCM_OAM_ENDPOINT_CCM_PERIOD_10S,
   6272     BCM_OAM_ENDPOINT_CCM_PERIOD_1M,
   6273     BCM_OAM_ENDPOINT_CCM_PERIOD_10M,
   6274     _BCM_OAM_ENDPOINT_CCM_PERIOD_UNDEFINED
   6275 };
   6276 
   6277 
   6278 /*
   6279  * Function:
   6280  *     _bcm_fp_oam_period_validate
   6281  * Purpose:
   6282  *     Validates whether OAM period is in allowed range or not .
   6283  * Parameters:
   6284  *     period -  (IN) OAM PDU interval in milli seconds.
   6285  * Returns:
   6286  *      BCM_E_XXX
   6287  */
   6288 STATIC int
   6289 _bcm_fp_oam_period_validate(int period)
   6290 {
   6291     int q_period = 0; /* OAM period value. */
   6292 
   6293     /* Find whether requested period is matching with supported period or not */
   6294     for (q_period = 0; q_period <
   6295             _BCM_FP_OAM_MAX_CCM_INTERVALS; q_period++) {
   6296         if (period ==  _fp_oam_ccm_intervals[q_period]) {
   6297             return BCM_E_NONE; 
   6298         }
   6299     }
   6300 
   6301     return BCM_E_PARAM;
   6302 }
   6303 
   6304 /*
   6305  * Function:
   6306  *      _bcm_fp_oam_bhh_appl_callback
   6307  * Purpose:
   6308  *      Update FW BHH appl state
   6309  * Parameters:
   6310  *      unit  - (IN) Unit number.
   6311  *      uC    - (IN) core number.
   6312  *      stage - (IN) core reset stage.
   6313  *      user_data - (IN) data pointer.
   6314  * Returns:
   6315  *      BCM_E_XXX
   6316  * Notes:
   6317  */
   6318 
   6319 int _bcm_fp_oam_bhh_appl_callback(int unit,
   6320                                     int uC,
   6321                                     soc_cmic_uc_shutdown_stage_t stage,
   6322                                     void *user_data) {
   6323     _bcm_fp_oam_control_t *oc;
   6324 
   6325     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
   6326     _BCM_OAM_LOCK(oc);
   6327     oc->ukernel_not_ready = 1;
   6328 
   6329     _BCM_OAM_UNLOCK(oc);
   6330 
   6331     return BCM_E_NONE;
   6332 }
   6333 
   6334 /*
   6335  *  * Function:
   6336  *      _bcm_fp_oam_bhh_endpoint_create
   6337  * Purpose:
   6338  *      Create or replace a BHH FP OAM endpoint object
   6339  * Parameters:
   6340  *      unit - (IN) Unit number.
   6341  *      endpoint_info - (IN/OUT) Pointer to endpoint information buffer.
   6342  * Returns:
   6343  *      BCM_E_XXX
   6344  * Notes:
   6345  */
   6346 int
   6347 _bcm_fp_oam_bhh_endpoint_create(int unit, 
   6348                                 bcm_oam_endpoint_info_t *endpoint_info)
   6349 {
   6350     _bcm_fp_oam_control_t *oc;
   6351     _bhh_fp_oam_ep_data_t *hash_data = NULL;/* Endpoint hash data pointer.  */
   6352     _bhh_fp_oam_ep_data_t h_stored_data;    /* dummy Endpoint hash data     */
   6353     _bhh_fp_oam_group_data_t *group_p;      /* Pointer to group data.       */
   6354     _bhh_fp_oam_hash_key_t  hash_key;       /* Hash Key buffer.             */
   6355     int                  rv = BCM_E_NONE;   /* Operation return status.     */
   6356     int                  is_remote = 0;     /* Remote endpoint status.      */
   6357     int                  is_replace;
   6358     int                  is_local = 0;         
   6359     int                  sglp = 0;          /* Source global logical port.  */
   6360     int                  dglp = 0;          /* Dest global logical port.    */
   6361     bcm_gport_t          dgpp = 0;
   6362     bcm_module_t         module_id;         /* Module ID                    */
   6363     bcm_port_t           port_id;
   6364     bcm_trunk_t          trunk_id = BCM_TRUNK_INVALID;
   6365     int                  local_id;
   6366     bhh_sdk_msg_ctrl_rmep_create_t msg_rmep_create;
   6367     uint8 *buffer, *buffer_ptr;
   6368     uint16 buffer_len, reply_len;
   6369     uint32 session_flags;
   6370     int bhh_pool_ep_idx = 0;
   6371     int bhh_group_idx = 0;
   6372     int i = 0;
   6373     bcm_trunk_member_t   trunk_member;
   6374     _bhh_oam_lm_dm_info_t counter_info;
   6375     uint8 lm_pdu_counter_offset = 0;
   6376     _l2_header_t l2_hdr;
   6377     bcm_stat_group_mode_t stat_group;
   6378     bcm_stat_object_t stat_object;
   6379     uint32 stat_mode;
   6380     uint32 stat_pool_number;
   6381     uint32 base_index;
   6382 
   6383     LOG_DEBUG(BSL_LS_BCM_OAM,
   6384               (BSL_META_U(unit,
   6385                           "BHH(unit %d) Info: _bcm_fp_oam_bhh_endpoint_create"
   6386                            "Endpoint ID=%d.\n"), unit, endpoint_info->id));
   6387 
   6388     _BCM_OAM_BHH_IS_VALID(unit);
   6389 
   6390     /* Validate input parameter. */
   6391     if (NULL == endpoint_info) {
   6392         return (BCM_E_PARAM);
   6393     }
   6394 
   6395     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
   6396     _BCM_FP_OAM_BHH_GROUP_INDEX_VALIDATE(endpoint_info->group);
   6397     _BCM_OAM_LOCK(oc);
   6398 
   6399     if (oc->ukernel_not_ready == 1){
   6400         LOG_ERROR(BSL_LS_BCM_OAM,
   6401                 (BSL_META_U(unit,
   6402                             "OAM(unit %d) Error: BTE(ukernel) "
   6403                             "not ready.\n"), unit));
   6404         _BCM_OAM_UNLOCK(oc);
   6405         return (BCM_E_INIT);
   6406     }
   6407 
   6408     /* Perform BHH specific validation checks */
   6409     /* BHH EP can only be at the MAX Level */
   6410     if (endpoint_info->level != _BCM_OAM_EP_LEVEL_MAX ) {
   6411         LOG_ERROR(BSL_LS_BCM_OAM,
   6412                   (BSL_META_U(unit,
   6413                    "OAM(unit %d) Error: EP Level should be equal to %d\n"),
   6414                    unit, _BCM_OAM_EP_LEVEL_MAX));
   6415         _BCM_OAM_UNLOCK(oc);
   6416         return (BCM_E_PARAM);
   6417     }
   6418 
   6419 
   6420     /* For replace operation, endpoint ID is required. */
   6421     if ((endpoint_info->flags & BCM_OAM_ENDPOINT_REPLACE)
   6422         && !(endpoint_info->flags & BCM_OAM_ENDPOINT_WITH_ID)) {
   6423         _BCM_OAM_UNLOCK(oc);
   6424         return (BCM_E_PARAM);
   6425     }
   6426 
   6427     bhh_group_idx = BCM_OAM_BHH_GET_UKERNEL_GROUP(endpoint_info->group);
   6428     rv = shr_idxres_list_elem_state(oc->bhh_group_pool, bhh_group_idx);
   6429     if (BCM_E_EXISTS != rv) {
   6430         LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: "
   6431                   "Group (GID:%d) does not exist.\n"), endpoint_info->group));
   6432         _BCM_OAM_UNLOCK(oc);
   6433         return (BCM_E_PARAM);
   6434     }
   6435 
   6436     /*Validate CCM period */
   6437     rv = _bcm_fp_oam_period_validate(endpoint_info->ccm_period);
   6438     if (BCM_FAILURE(rv)) {
   6439         LOG_ERROR(BSL_LS_BCM_OAM,
   6440                   (BSL_META_U(unit, "OAM Error:  Invalid CCM period : %d \n"),
   6441                                       endpoint_info->ccm_period));
   6442         _BCM_OAM_UNLOCK(oc);
   6443         return rv;
   6444     }
   6445 
   6446     group_p = &(oc->bhh_group_data[bhh_group_idx]);
   6447     if (!(endpoint_info->flags & BCM_OAM_ENDPOINT_REMOTE)) {
   6448 
   6449         /* Only One LMEP should be configured per group */
   6450         if (group_p->lmep_id != _FP_OAM_INVALID_LMEP_ID) {
   6451             LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: "
   6452               "LMEP already existst for the group\n")));
   6453             _BCM_OAM_UNLOCK(oc);
   6454             return (BCM_E_EXISTS);
   6455         }
   6456         /*Atleast one valid session entry should be present for endpoint*/
   6457         if (endpoint_info->session_num_entries ==
   6458                 _BCM_FP_OAM_INVALID_NUM_SESSION_ENTRIES) {
   6459             LOG_ERROR(BSL_LS_BCM_OAM,
   6460                     (BSL_META_U(unit,
   6461                                 "OAM(unit %d) Error: number of session entries "
   6462                                 "cannot be zero for EP\n"), unit));
   6463             _BCM_OAM_UNLOCK(oc);
   6464             return (BCM_E_PARAM);
   6465         }
   6466     }
   6467 
   6468     /* Calculate the hash key for given enpoint input parameters. */
   6469     _bhh_fp_oam_ep_hash_key_construct(unit, oc, endpoint_info, &hash_key);
   6470     rv = shr_htb_find(oc->bhh_mep_htbl, hash_key,
   6471                       (shr_htb_data_t *)&h_stored_data, 0);
   6472     if (BCM_SUCCESS(rv)
   6473         && !(endpoint_info->flags & BCM_OAM_ENDPOINT_REPLACE)) {
   6474 
   6475         LOG_ERROR(BSL_LS_BCM_OAM,
   6476                   (BSL_META_U(unit,
   6477                               "OAM(unit %d) Error: Endpoint ID=%d %s.\n"),
   6478                    unit, endpoint_info->id, bcm_errmsg(BCM_E_EXISTS)));
   6479 
   6480         /* Endpoint must not be in use expect for Replace operation. */
   6481         _BCM_OAM_UNLOCK(oc);
   6482         return (BCM_E_EXISTS);
   6483 
   6484     } else {
   6485 
   6486         LOG_DEBUG(BSL_LS_BCM_OAM,
   6487                   (BSL_META_U(unit,
   6488                               "OAM(unit %d) Info: Endpoint ID=%d "
   6489                               "Available. %s.\n"),
   6490                    unit, endpoint_info->id, bcm_errmsg(rv)));
   6491 
   6492     }
   6493 
   6494 
   6495     /* Get MEP remote endpoint status. */
   6496     is_remote = (endpoint_info->flags & BCM_OAM_ENDPOINT_REMOTE) ? 1 : 0;
   6497 
   6498     is_replace = ((endpoint_info->flags & BCM_OAM_ENDPOINT_REPLACE) != 0);
   6499 
   6500     /* Validate EP Id if BCM_OAM_ENDPOINT_WITH_ID flag is set */
   6501     if (endpoint_info->flags & BCM_OAM_ENDPOINT_WITH_ID) {
   6502         if((endpoint_info->id < oc->bhh_base_endpoint_id) ||
   6503            (endpoint_info->id >= (oc->bhh_base_endpoint_id 
   6504                                   + oc->bhh_endpoint_count))) {
   6505             _BCM_OAM_UNLOCK(oc);
   6506             return (BCM_E_PARAM);
   6507         }
   6508     }
   6509 
   6510     /* Validate remote EP Id if BCM_OAM_ENDPOINT_REMOTE flag is set */
   6511     if (is_remote) {
   6512         if((endpoint_info->local_id < oc->bhh_base_endpoint_id) ||
   6513            (endpoint_info->local_id >= (oc->bhh_base_endpoint_id
   6514                                         + oc->bhh_endpoint_count))) {
   6515             _BCM_OAM_UNLOCK(oc);
   6516             return (BCM_E_PARAM);
   6517         }
   6518     }
   6519 
   6520     /* Validate if the gport is an MPLS port for PW MEP */
   6521     if (endpoint_info->type == bcmOAMEndpointTypeBHHMPLSVccv) {
   6522         if (-1 == BCM_GPORT_MPLS_PORT_ID_GET(endpoint_info->gport)) {
   6523             _BCM_OAM_UNLOCK(oc);
   6524             return BCM_E_PARAM;
   6525         }
   6526     }
   6527 
   6528     if (is_replace) {
   6529         if (is_remote) {
   6530             LOG_ERROR(BSL_LS_BCM_OAM,
   6531                     (BSL_META_U(unit,
   6532                                 "OAM(unit %d) Error: Replace is "
   6533                                 " not allowed on remote endpoint\n"),
   6534                          unit));
   6535             _BCM_OAM_UNLOCK(oc);
   6536             return (BCM_E_PARAM);
   6537         }
   6538         bhh_pool_ep_idx = BCM_OAM_BHH_GET_UKERNEL_EP(endpoint_info->id);
   6539         hash_data = &oc->bhh_ep_data[bhh_pool_ep_idx];
   6540         if (!hash_data->in_use) {
   6541             _BCM_OAM_UNLOCK(oc);
   6542             return (BCM_E_NOT_FOUND);
   6543         }
   6544         if(!BHH_EP_MPLS_SECTION_TYPE(hash_data)){
   6545             if ((hash_data->egress_if != endpoint_info->intf_id) ||
   6546                 (hash_data->label != endpoint_info->mpls_label) ||
   6547                 (hash_data->egr_label != endpoint_info->egress_label.label) ||
   6548                 (hash_data->gport != endpoint_info->gport) ||
   6549                 (hash_data->period != endpoint_info->ccm_period) ||
   6550                 (hash_data->vccv_type != endpoint_info->vccv_type) ||
   6551                 (hash_data->vpn  != endpoint_info->vpn) ||
   6552                 (hash_data->name != endpoint_info->name) || 
   6553                 (hash_data->level != endpoint_info->level) ||
   6554                 (hash_data->type != endpoint_info->type) ||
   6555                 (hash_data->ep_id != endpoint_info->id) ||
   6556                 (hash_data->group_index != endpoint_info->group)) {
   6557                 LOG_ERROR(BSL_LS_BCM_OAM,
   6558                         (BSL_META_U(unit,
   6559                                     "OAM(unit %d) Error: Parameters passed are "
   6560                                     " not valid to replace\n"),
   6561                          unit));
   6562                 _BCM_OAM_UNLOCK(oc);
   6563                 return (BCM_E_PARAM);
   6564             }
   6565         } else {
   6566             if ((hash_data->gport != endpoint_info->gport) ||
   6567                 (hash_data->period != endpoint_info->ccm_period) ||
   6568                 (hash_data->name != endpoint_info->name) ||
   6569                 (hash_data->level != endpoint_info->level) ||
   6570                 (hash_data->type != endpoint_info->type) ||
   6571                 (hash_data->ep_id != endpoint_info->id) ||
   6572                 (hash_data->group_index != endpoint_info->group) ||
   6573                 (hash_data->vlan != endpoint_info->vlan) ||
   6574                 (hash_data->inner_vlan != endpoint_info->inner_vlan) ||
   6575                 (hash_data->outer_tpid != endpoint_info->outer_tpid) ||
   6576                 (hash_data->inner_tpid != endpoint_info->inner_tpid) ||
   6577                 (hash_data->vlan_pri != endpoint_info->pkt_pri) ||
   6578                 (hash_data->inner_vlan_pri != endpoint_info->inner_pkt_pri)) {
   6579                 LOG_ERROR(BSL_LS_BCM_OAM,
   6580                         (BSL_META_U(unit,
   6581                                     "OAM(unit %d) Error: Parameters passed are"
   6582                                     " not valid to replace\n"),
   6583                          unit));
   6584                 _BCM_OAM_UNLOCK(oc);
   6585                 return (BCM_E_PARAM);
   6586             }
   6587         }   
   6588     }
   6589 
   6590     /* Interface validation check */
   6591     if(!BHH_EP_MPLS_SECTION_TYPE(endpoint_info)){
   6592         if ((!BCM_XGS3_L3_EGRESS_IDX_VALID(unit, endpoint_info->intf_id)) && 
   6593              (!BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, endpoint_info->intf_id))) { 
   6594             LOG_ERROR(BSL_LS_BCM_OAM,
   6595                     (BSL_META_U(unit,
   6596                                 "OAM(unit %d) Error: intf type"
   6597                                 " not valid. It should be DVP_EGRESS or "
   6598                                 "L3_EGRESS type.\n"),
   6599                      unit));
   6600             _BCM_OAM_UNLOCK(oc);
   6601             return (BCM_E_PARAM);
   6602         }
   6603     }
   6604     /* Now that we passed the validation checks
   6605      * Create a new endpoint with the requested ID. */
   6606     if ( !is_remote && (endpoint_info->flags & BCM_OAM_ENDPOINT_WITH_ID) ) {
   6607         
   6608         bhh_pool_ep_idx = BCM_OAM_BHH_GET_UKERNEL_EP(endpoint_info->id);
   6609 
   6610         hash_data = &oc->bhh_ep_data[bhh_pool_ep_idx];
   6611 
   6612         if (!is_replace && hash_data->in_use) {
   6613             _BCM_OAM_UNLOCK(oc);
   6614             return (BCM_E_EXISTS);
   6615         }
   6616 
   6617         if(!is_replace) {
   6618             rv = shr_idxres_list_reserve(oc->bhh_pool, bhh_pool_ep_idx,
   6619                                      bhh_pool_ep_idx);
   6620             if (BCM_FAILURE(rv)) {
   6621                 rv = (rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv;
   6622                 LOG_ERROR(BSL_LS_BCM_OAM,
   6623                           (BSL_META_U(unit,
   6624                                       "BHH(unit %d) Error: Endpoint reserve (EP=%d) - %s.\n"),
   6625                            unit, endpoint_info->id, bcm_errmsg(rv)));
   6626                 _BCM_OAM_UNLOCK(oc);
   6627                 return (rv);
   6628             }
   6629         }
   6630     } else {
   6631 
   6632         /* BHH uses local and remote same index */
   6633         if(endpoint_info->flags & BCM_OAM_ENDPOINT_REMOTE) {
   6634             bhh_pool_ep_idx = BCM_OAM_BHH_GET_UKERNEL_EP
   6635                               (endpoint_info->local_id);
   6636         }
   6637         else {
   6638             /* Allocate the next available endpoint index. */
   6639             rv = shr_idxres_list_alloc(oc->bhh_pool,
   6640                                    (shr_idxres_element_t *)&bhh_pool_ep_idx);
   6641             if (BCM_FAILURE(rv)) {
   6642                 rv = (rv == BCM_E_RESOURCE) ? (BCM_E_FULL) : rv;
   6643                 LOG_ERROR(BSL_LS_BCM_OAM,
   6644                           (BSL_META_U(unit,
   6645                                       "BHH(unit %d) Error: Endpoint alloc failed - %s.\n"),
   6646                            unit, bcm_errmsg(rv)));
   6647                 _BCM_OAM_UNLOCK(oc);
   6648                 return (rv);
   6649             }
   6650         }
   6651         endpoint_info->id = BCM_OAM_BHH_GET_SDK_EP(bhh_pool_ep_idx);
   6652     }
   6653 
   6654     /* Get the hash data pointer where the data is to be stored. */
   6655     hash_data = &oc->bhh_ep_data[bhh_pool_ep_idx];
   6656 
   6657     if (is_remote) {
   6658 
   6659         if (!hash_data->in_use) {
   6660             _BCM_OAM_UNLOCK(oc);
   6661             return (BCM_E_NOT_FOUND);
   6662         } else if (hash_data->flags & BCM_OAM_ENDPOINT_REMOTE) {
   6663             _BCM_OAM_UNLOCK(oc);
   6664             return (BCM_E_EXISTS);
   6665         }
   6666             msg_rmep_create.sess_id = bhh_pool_ep_idx;
   6667             msg_rmep_create.flags = 0;
   6668             msg_rmep_create.enable = 1;
   6669             msg_rmep_create.remote_mep_id = endpoint_info->name;
   6670             msg_rmep_create.period = endpoint_info->ccm_period;
   6671 
   6672             /* Pack control message data into DMA buffer */
   6673             buffer     = oc->bhh_dma_buffer;
   6674             buffer_ptr = bhh_sdk_msg_ctrl_rmep_create_pack(buffer,
   6675                                                            &msg_rmep_create);
   6676             buffer_len = buffer_ptr - buffer;
   6677 
   6678             /* Send BHH Session Update message to uC */
   6679             rv = _bcm_fp_oam_msg_send_receive(unit,
   6680                     MOS_MSG_CLASS_BHH, 
   6681                     MOS_MSG_SUBCLASS_BHH_RMEP_CREATE,
   6682                     buffer_len, 0,
   6683                     MOS_MSG_SUBCLASS_BHH_RMEP_CREATE_REPLY,
   6684                     &reply_len);
   6685             if (BCM_FAILURE(rv) || (reply_len != 0)) {
   6686                 LOG_ERROR(BSL_LS_BCM_OAM,
   6687                         (BSL_META_U(unit,
   6688                                     "BHH(unit %d) Error: Endpoint create " 
   6689                                     "(EP=%d) - %s.\n"),
   6690                          unit, endpoint_info->id, bcm_errmsg(rv)));
   6691                 _BCM_OAM_UNLOCK(oc);
   6692                 return (BCM_E_INTERNAL);
   6693             }
   6694     } else {
   6695         /* Resolve given endpoint gport value to SGLP and DGLP values. */
   6696         rv = _bcm_fp_oam_endpoint_gport_resolve(unit, endpoint_info,
   6697                                                 &sglp, &dglp, &dgpp,
   6698                                                 &trunk_id, &trunk_member);
   6699         if (BCM_FAILURE(rv)) {
   6700             LOG_ERROR(BSL_LS_BCM_OAM,
   6701                       (BSL_META_U(unit,
   6702                                   "OAM(unit %d) Error: Gport resolve (EP=%d) - %s.\n"),
   6703                        unit, endpoint_info->id, bcm_errmsg(rv)));
   6704             _BCM_OAM_UNLOCK(oc);
   6705             /* Return ID back to free MEP ID pool.*/
   6706             rv = shr_idxres_list_free(oc->bhh_pool, bhh_pool_ep_idx);
   6707             return (rv);
   6708         }
   6709 
   6710         /* Clear the hash data element contents before storing the values. */
   6711         _BHH_FP_OAM_HASH_DATA_CLEAR(hash_data);
   6712         hash_data->type = endpoint_info->type;
   6713         hash_data->ep_id = endpoint_info->id;
   6714         hash_data->group_index = endpoint_info->group;
   6715         hash_data->level = endpoint_info->level;
   6716         hash_data->vlan = endpoint_info->vlan;
   6717         hash_data->inner_vlan = endpoint_info->inner_vlan;
   6718         hash_data->outer_tpid = endpoint_info->outer_tpid;
   6719         hash_data->inner_tpid = endpoint_info->inner_tpid;
   6720         hash_data->vlan_pri = endpoint_info->pkt_pri;
   6721         hash_data->inner_vlan_pri = endpoint_info->inner_pkt_pri;
   6722         hash_data->gport = endpoint_info->gport;
   6723         hash_data->sglp = sglp;
   6724         hash_data->dglp = dglp;
   6725         hash_data->flags = endpoint_info->flags;
   6726         hash_data->flags2 = endpoint_info->flags2;
   6727         hash_data->int_pri = endpoint_info->int_pri;
   6728         hash_data->period = endpoint_info->ccm_period;
   6729         hash_data->vccv_type = endpoint_info->vccv_type;
   6730         hash_data->vpn  = endpoint_info->vpn;
   6731         hash_data->name      = endpoint_info->name;
   6732         hash_data->egress_if = endpoint_info->intf_id;
   6733         hash_data->label     = endpoint_info->mpls_label;
   6734         hash_data->egr_label     = endpoint_info->egress_label.label;
   6735         hash_data->egr_label_exp = endpoint_info->egress_label.exp;
   6736         hash_data->egr_label_ttl = endpoint_info->egress_label.ttl;
   6737         hash_data->trunk_index = endpoint_info->trunk_index;
   6738         hash_data->hw_session_id = endpoint_info->session_id;
   6739         hash_data->hw_session_num_entries = endpoint_info->session_num_entries;
   6740         
   6741         sal_memcpy(hash_data->dst_mac_address, endpoint_info->dst_mac_address, 
   6742                    _BHH_MAC_ADDR_LENGTH);
   6743         sal_memcpy(hash_data->src_mac_address, endpoint_info->src_mac_address, 
   6744                    _BHH_MAC_ADDR_LENGTH);
   6745         hash_data->trunk_id = trunk_id;
   6746         
   6747         hash_data->pm_profile_attached = _BCM_OAM_INVALID_INDEX;
   6748         hash_data->in_use = 1;
   6749         group_p->lmep_id = endpoint_info->id;
   6750        
   6751         if (BCM_TRUNK_INVALID != trunk_id) {
   6752             endpoint_info->gport = trunk_member.gport;
   6753             hash_data->resolved_trunk_gport = trunk_member.gport;
   6754         }
   6755         /* Get the Trunk, Port and Modid info for this Gport */
   6756         rv = _bcm_esw_gport_resolve(unit,
   6757                 endpoint_info->gport, &module_id, &port_id, 
   6758                 &trunk_id, &local_id);
   6759 
   6760         if (BCM_FAILURE(rv)) {
   6761             LOG_ERROR(BSL_LS_BCM_OAM,
   6762                       (BSL_META_U(unit,
   6763                                   "BHH(unit %d) Error: Gport resolve (EP=%d) -"
   6764                                   " %s.\n"),
   6765                        unit, endpoint_info->id, bcm_errmsg(rv)));
   6766             /* Return ID back to free MEP ID pool.*/
   6767             rv = shr_idxres_list_free(oc->bhh_pool, bhh_pool_ep_idx);
   6768             _BCM_OAM_UNLOCK(oc);
   6769             return (rv);
   6770         }
   6771 
   6772         /* Get local port used for TX BHH packet */
   6773         rv = _bcm_esw_modid_is_local(unit, module_id, &is_local);
   6774         if(BCM_FAILURE(rv)) {
   6775             LOG_ERROR(BSL_LS_BCM_OAM,
   6776                       (BSL_META_U(unit,
   6777                                   "BHH(unit %d) Error: local port for "
   6778                                   "BHH TX failed(ep=%d) - %s.\n"),
   6779                        unit, endpoint_info->id, bcm_errmsg(rv)));
   6780             /* Return ID back to free MEP ID pool.*/
   6781             rv = shr_idxres_list_free(oc->bhh_pool, bhh_pool_ep_idx);
   6782             _BCM_OAM_UNLOCK(oc);
   6783             return (rv);
   6784         }
   6785 
   6786         if (!is_local) {    /* HG port */
   6787             rv = bcm_esw_stk_modport_get(unit, module_id, &port_id);
   6788             if(BCM_FAILURE(rv)) {
   6789                 LOG_ERROR(BSL_LS_BCM_OAM,
   6790                           (BSL_META_U(unit,
   6791                                       "BHH(unit %d) Error: HG port get failed "
   6792                                       "(EP=%d) - %s.\n"),
   6793                            unit, endpoint_info->id, bcm_errmsg(rv)));
   6794                 /* Return ID back to free MEP ID pool.*/
   6795                 rv = shr_idxres_list_free(oc->bhh_pool, bhh_pool_ep_idx);
   6796                 _BCM_OAM_UNLOCK(oc);
   6797                 return (rv);
   6798             }
   6799         }
   6800         /* Set Endpoint config entry */
   6801         hash_data->uc_session_id = bhh_pool_ep_idx;
   6802 
   6803         sal_memset(&counter_info, 0, sizeof(counter_info));
   6804         counter_info.counter_size = 
   6805                                   endpoint_info->ccm_tx_update_lm_counter_size;
   6806         hash_data->ccm_tx_counter_size = 
   6807                                   endpoint_info->ccm_tx_update_lm_counter_size;
   6808         for (i=0; i< BCM_OAM_LM_COUNTER_MAX; i++)
   6809         {
   6810             counter_info.counter_base_id[i] = 
   6811                              endpoint_info->ccm_tx_update_lm_counter_base_id[i];
   6812             hash_data->ccm_tx_update_lm_counter_base_id[i] = 
   6813                        endpoint_info->ccm_tx_update_lm_counter_base_id[i];
   6814             counter_info.counter_offset[i] = 
   6815                              endpoint_info->ccm_tx_update_lm_counter_offset[i];
   6816             hash_data->ccm_tx_update_lm_counter_offset[i] =
   6817                              endpoint_info->ccm_tx_update_lm_counter_offset[i]; 
   6818             counter_info.counter_action[i] = bcmOamCounterActionIncrement;
   6819             counter_info.byte_count_offset[i] = 0;
   6820         }
   6821         counter_info.ts_mode = BCM_PKT_TIMESTAMP_MODE_NONE;
   6822         counter_info.oam_replacement_offset = SHR_BHH_LM_OFFSET_INSIDE_CCM_PDU;
   6823 
   6824         session_flags = (is_replace) ? 0 : SHR_BHH_SESS_SET_F_CREATE;
   6825         if(!is_replace) {
   6826 
   6827             bhh_sdk_msg_ctrl_sess_set_t msg_sess;
   6828             uint16 encap_length = 0;
   6829 
   6830             sal_memset(&msg_sess, 0, sizeof(msg_sess));
   6831             /*
   6832              * Set the BHH encapsulation data
   6833              *
   6834              * The function _bcm_fp_oam_bhh_encap_create() is called first
   6835              * since this sets some fields in 'hash_data' which are
   6836              * used in the message.
   6837              */
   6838             rv = _bcm_fp_oam_bhh_encap_create(unit,
   6839                     module_id,
   6840                     port_id, 
   6841                     hash_data,
   6842                     msg_sess.encap_data,
   6843                     &msg_sess.encap_type,
   6844                     &encap_length,
   6845                     &counter_info, hash_data->int_pri,
   6846                     hash_data->egr_label_exp,
   6847                     hash_data->egr_label_ttl);
   6848 
   6849             if(BCM_FAILURE(rv))
   6850             {
   6851                 LOG_ERROR(BSL_LS_BCM_OAM,
   6852                         (BSL_META_U(unit,
   6853                                     "BHH(unit %d) Error: Encap create failed "
   6854                                     "(EP=%d) - %s.\n"),
   6855                          unit, endpoint_info->id, bcm_errmsg(rv)));
   6856                 /* Return ID back to free MEP ID pool.*/
   6857                 rv = shr_idxres_list_free(oc->bhh_pool, bhh_pool_ep_idx);
   6858                 _BCM_OAM_UNLOCK(oc);
   6859                 return (rv);
   6860             }
   6861 
   6862             rv = _bcm_fp_oam_l2_header_get(unit,    hash_data,
   6863                                            port_id, SHR_BHH_L2_ETYPE_MPLS_UCAST,
   6864                                            &l2_hdr, &lm_pdu_counter_offset);
   6865             if (BCM_FAILURE(rv)) {
   6866                 _BCM_OAM_UNLOCK(oc);
   6867                 return rv;
   6868             }
   6869             session_flags |= SHR_BHH_SESS_SET_F_CCM;
   6870 
   6871             if (endpoint_info->flags & BCM_OAM_ENDPOINT_INTERMEDIATE)
   6872                 session_flags |= SHR_BHH_SESS_SET_F_MIP;
   6873 
   6874             if (group_p->flags & BCM_OAM_GROUP_REMOTE_DEFECT_TX) {
   6875                 session_flags |= SHR_BHH_SESS_SET_F_RDI;
   6876             }
   6877 
   6878             msg_sess.encap_length = encap_length;
   6879             msg_sess.sess_id = bhh_pool_ep_idx;
   6880             msg_sess.flags   = session_flags;
   6881 
   6882             msg_sess.mel     = hash_data->level;
   6883             msg_sess.mep_id  = hash_data->name;
   6884             sal_memcpy(msg_sess.meg_id, group_p->name, 
   6885                        BCM_OAM_GROUP_NAME_LENGTH);
   6886             msg_sess.period = endpoint_info->ccm_period;
   6887             msg_sess.if_num  = endpoint_info->intf_id;
   6888             msg_sess.tx_port = port_id;
   6889             msg_sess.num_session_entries = endpoint_info->session_num_entries;
   6890             _bcm_esw_stat_get_counter_id_info(unit, endpoint_info->session_id,
   6891                     &stat_group, &stat_object,
   6892                     &stat_mode, &stat_pool_number,
   6893                     &base_index);
   6894             msg_sess.lm_counter_index = SOC_OLP_TX_CTR(stat_pool_number,
   6895                                                           base_index);
   6896 
   6897             if (!BHH_EP_MPLS_SECTION_TYPE(endpoint_info)) {
   6898                 msg_sess.mpls_label = endpoint_info->mpls_label;
   6899             } else {
   6900                 msg_sess.mpls_label = SHR_BHH_MPLS_GAL_LABEL;
   6901             }
   6902 
   6903             if (0 != l2_hdr.vlan_tag_inner.tpid) {
   6904                 msg_sess.inner_vlan = l2_hdr.vlan_tag_inner.tci.vid;
   6905             }
   6906 
   6907             if (0 != l2_hdr.vlan_tag.tpid) {
   6908                 msg_sess.outer_vlan = l2_hdr.vlan_tag.tci.vid;
   6909             }
   6910 
   6911             switch (endpoint_info->type) {
   6912             case bcmOAMEndpointTypeBHHMPLS:
   6913                 msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_LSP;
   6914                 msg_sess.priority   = endpoint_info->mpls_exp;
   6915                 break;
   6916 
   6917             case bcmOAMEndpointTypeBHHMPLSVccv:
   6918                 switch(endpoint_info->vccv_type) {
   6919 
   6920                 case bcmOamBhhVccvChannelAch:
   6921                     msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_PW_VCCV_1;
   6922                     msg_sess.priority   = endpoint_info->mpls_exp;
   6923                     break;
   6924 
   6925                 case bcmOamBhhVccvRouterAlert:
   6926                     msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_PW_VCCV_2;
   6927                     msg_sess.priority   = endpoint_info->mpls_exp;
   6928                     break;
   6929 
   6930                 case bcmOamBhhVccvTtl:
   6931                     msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_PW_VCCV_3;
   6932                     msg_sess.priority   = endpoint_info->mpls_exp;
   6933                     break;
   6934 
   6935                 case bcmOamBhhVccvGal13:
   6936                     msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_PW_VCCV_4;
   6937                     msg_sess.priority   = endpoint_info->mpls_exp;
   6938                     break;
   6939 
   6940                 default:
   6941                     return BCM_E_PARAM;
   6942                     break;
   6943                 }
   6944                 break;
   6945 
   6946             case bcmOAMEndpointTypeBhhSection:
   6947                 msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_PORT_SECTION;
   6948                 msg_sess.priority   = 0;
   6949                 break;
   6950             case bcmOAMEndpointTypeBhhSectionInnervlan:
   6951                 msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_PORT_SECTION_INNERVLAN;
   6952                 msg_sess.priority   = endpoint_info->inner_pkt_pri;
   6953                 break;
   6954             case bcmOAMEndpointTypeBhhSectionOuterVlan:
   6955                 msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_PORT_SECTION_OUTERVLAN;
   6956                 msg_sess.priority   = endpoint_info->pkt_pri;
   6957                 break;
   6958             case bcmOAMEndpointTypeBhhSectionOuterPlusInnerVlan:
   6959                 msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_PORT_SECTION_OUTER_PLUS_INNERVLAN;
   6960                 msg_sess.priority   = endpoint_info->pkt_pri;
   6961                 break;
   6962 
   6963             default:
   6964                 return BCM_E_PARAM;
   6965             }
   6966 
   6967             /* Pack control message data into DMA buffer */
   6968             buffer     = oc->bhh_dma_buffer;
   6969             buffer_ptr = bhh_sdk_msg_ctrl_sess_set_pack(buffer, &msg_sess);
   6970             buffer_len = buffer_ptr - buffer;
   6971 
   6972             /* Send BHH Session Update message to uC */
   6973             rv = _bcm_fp_oam_msg_send_receive(unit,
   6974                     MOS_MSG_CLASS_BHH, 
   6975                     MOS_MSG_SUBCLASS_BHH_SESS_SET,
   6976                     buffer_len, 0,
   6977                     MOS_MSG_SUBCLASS_BHH_SESS_SET_REPLY,
   6978                     &reply_len);
   6979             if (BCM_FAILURE(rv) || (reply_len != 0)) {
   6980                 LOG_ERROR(BSL_LS_BCM_OAM,
   6981                         (BSL_META_U(unit,
   6982                                     "BHH(unit %d) Error: Session SET failed "
   6983                                     "(EP=%d) - %s.\n"),
   6984                          unit, endpoint_info->id, bcm_errmsg(rv)));
   6985                 /* Return ID back to free MEP ID pool.*/
   6986                 rv = shr_idxres_list_free(oc->bhh_pool, bhh_pool_ep_idx);
   6987                 _BCM_OAM_UNLOCK(oc);
   6988                 return (rv);
   6989             }
   6990 
   6991             /* hash collision */
   6992             rv = shr_htb_insert(oc->bhh_mep_htbl, hash_key, hash_data);
   6993             if (BCM_FAILURE(rv)) {
   6994                 LOG_ERROR(BSL_LS_BCM_OAM,
   6995                         (BSL_META_U(unit,
   6996                                     "OAM(unit %d) Error: Hash table insert "
   6997                                     "failed EP=%d %s.\n"),
   6998                          unit, endpoint_info->id, bcm_errmsg(rv)));
   6999                 /* Return ID back to free MEP ID pool.*/
   7000                 rv = shr_idxres_list_free(oc->bhh_pool, bhh_pool_ep_idx);
   7001                 _BCM_OAM_UNLOCK(oc);
   7002                 return (rv);
   7003             }
   7004 
   7005             hash_data->in_use = 1;
   7006         } else {
   7007             bhh_sdk_msg_session_update_t msg_sess;
   7008             uint8   encap_type;/* dummy*/
   7009 
   7010             sal_memset(&msg_sess, 0, sizeof(msg_sess));
   7011             msg_sess.sess_id = bhh_pool_ep_idx;
   7012             msg_sess.rdi = (group_p->flags & BCM_OAM_GROUP_REMOTE_DEFECT_TX);
   7013             msg_sess.msg_type = BHH_CCM_MSG;
   7014 
   7015             rv = _bcm_fp_oam_bhh_encap_create(unit,
   7016                     module_id,
   7017                     port_id, 
   7018                     hash_data,
   7019                     msg_sess.encap_data,
   7020                     &encap_type,
   7021                     &msg_sess.encap_length,
   7022                     &counter_info, hash_data->int_pri,
   7023                     hash_data->egr_label_exp,
   7024                     hash_data->egr_label_ttl);
   7025 
   7026             if(BCM_FAILURE(rv))
   7027             {
   7028                 LOG_ERROR(BSL_LS_BCM_OAM,
   7029                         (BSL_META_U(unit,
   7030                                     "BHH(unit %d) Error: Encap create failed "
   7031                                     "(EP=%d) - %s.\n"),
   7032                          unit, endpoint_info->id, bcm_errmsg(rv)));
   7033                 _BCM_OAM_UNLOCK(oc);
   7034                 return (rv);
   7035             }
   7036             /* Pack control message data into DMA buffer */
   7037             buffer     = oc->bhh_dma_buffer;
   7038             buffer_ptr = bhh_sdk_msg_ctrl_session_update_pack(buffer, &msg_sess);
   7039             buffer_len = buffer_ptr - buffer;
   7040 
   7041 
   7042             /* Send BHH Session Update message to uC */
   7043             rv = _bcm_fp_oam_msg_send_receive(unit,
   7044                     MOS_MSG_CLASS_BHH, 
   7045                     MOS_MSG_SUBCLASS_BHH_SESS_UPDATE,
   7046                     buffer_len, 0,
   7047                     MOS_MSG_SUBCLASS_BHH_SESS_UPDATE_REPLY,
   7048                     &reply_len);
   7049             if (BCM_FAILURE(rv) || (reply_len != 0)) {
   7050                 LOG_ERROR(BSL_LS_BCM_OAM,
   7051                         (BSL_META_U(unit,
   7052                                     "BHH(unit %d) Error: Session Update failed "
   7053                                     "(EP=%d) - %s.\n"),
   7054                          unit, endpoint_info->id, bcm_errmsg(rv)));
   7055                 _BCM_OAM_UNLOCK(oc);
   7056                 return (rv);
   7057             }
   7058         }
   7059     } 
   7060     _BCM_OAM_UNLOCK(oc);
   7061     return (rv);
   7062 }
   7063 
   7064 /*
   7065  * Function:
   7066  *      _bcm_fp_oam_bhh_endpoint_get
   7067  * Purpose:
   7068  *      Get an OAM endpoint object
   7069  * Parameters:
   7070  *     unit          - (IN) BCM device number
   7071  *     endpoint_info - (OUT) Pointer to OAM endpoint information buffer.
   7072  * Returns:
   7073  *     BCM_E_XXX
   7074  */
   7075 int
   7076 _bcm_fp_oam_bhh_endpoint_get(int unit, bcm_oam_endpoint_info_t *endpoint_info)
   7077 {
   7078     _bhh_fp_oam_ep_data_t *h_data_p;     /* Pointer to endpoint hash data.    */
   7079     int                  rv = BCM_E_NONE;/* Operation return status.          */
   7080     _bcm_fp_oam_control_t   *oc;         /* Pointer to OAM control structure. */
   7081     bhh_sdk_msg_ctrl_sess_get_t msg;
   7082     uint8 *buffer, *buffer_ptr;
   7083     uint16 buffer_len, reply_len;
   7084     int sess_id = 0, i = 0;
   7085     bcm_l3_egress_t l3_egress;
   7086     bcm_l3_intf_t l3_intf;
   7087     
   7088 
   7089     if (NULL == endpoint_info) {
   7090         return (BCM_E_PARAM);
   7091     }
   7092 
   7093     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
   7094 
   7095 
   7096     sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(endpoint_info->id);
   7097     h_data_p =  &oc->bhh_ep_data[sess_id];
   7098 
   7099     if (0 == h_data_p->in_use) {
   7100         LOG_ERROR(BSL_LS_BCM_OAM,
   7101                 (BSL_META_U(unit,
   7102                             "OAM(unit %d) Error: h_data_p not in use EP=%d\n"),
   7103                  unit, endpoint_info->id));
   7104         return (BCM_E_NOT_FOUND);
   7105     }
   7106 
   7107     rv = _bcm_fp_oam_msg_send_receive(unit,
   7108             MOS_MSG_CLASS_BHH, 
   7109             MOS_MSG_SUBCLASS_BHH_SESS_GET,
   7110             sess_id, 0,
   7111             MOS_MSG_SUBCLASS_BHH_SESS_GET_REPLY,
   7112             &reply_len);
   7113     if (BCM_FAILURE(rv)) {
   7114         LOG_ERROR(BSL_LS_BCM_OAM,
   7115                 (BSL_META_U(unit,
   7116                             "OAM(unit %d) Error: ukernel msg failed for"
   7117                             " EP=%d %s.\n"), unit, endpoint_info->id, 
   7118                  bcm_errmsg(rv)));
   7119         return (rv);
   7120     }
   7121 
   7122     /* Pack control message data into DMA buffer */
   7123     buffer = oc->bhh_dma_buffer;
   7124     buffer_ptr = bhh_sdk_msg_ctrl_sess_get_unpack(buffer, &msg);
   7125     buffer_len = buffer_ptr - buffer;
   7126 
   7127     if (reply_len != buffer_len) {
   7128         rv = BCM_E_INTERNAL;
   7129         LOG_ERROR(BSL_LS_BCM_OAM,
   7130                 (BSL_META_U(unit,
   7131                             "OAM(unit %d) Error: ukernel msg failed for"
   7132                             " EP=%d %s.\n"), unit, endpoint_info->id, 
   7133                  bcm_errmsg(rv)));
   7134         return (rv);
   7135     } else {
   7136         endpoint_info->int_pri = msg.tx_cos;
   7137         endpoint_info->pkt_pri = msg.tx_pri;
   7138         endpoint_info->mpls_exp = msg.priority;
   7139 
   7140         if(endpoint_info->flags & BCM_OAM_ENDPOINT_REMOTE){
   7141             endpoint_info->name       = msg.remote_mep_id;
   7142             endpoint_info->ccm_period = msg.remote_period;
   7143         } else {
   7144             endpoint_info->name       = msg.mep_id;
   7145             endpoint_info->ccm_period = msg.local_period;
   7146         }
   7147 
   7148         if(msg.fault_flags & BHH_BTE_EVENT_CCM_TIMEOUT){
   7149             endpoint_info->faults |= BCM_OAM_BHH_FAULT_CCM_TIMEOUT;
   7150         }  
   7151         if(msg.fault_flags & BHH_BTE_EVENT_CCM_RDI){
   7152             endpoint_info->faults |= BCM_OAM_BHH_FAULT_CCM_RDI;
   7153         }  
   7154         if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_LEVEL){
   7155             endpoint_info->faults |= 
   7156                 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEG_LEVEL;
   7157         }  
   7158         if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_ID){
   7159             endpoint_info->faults |= 
   7160                 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEG_ID;
   7161         }  
   7162         if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_MEP_ID){
   7163             endpoint_info->faults |= 
   7164                 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEP_ID;
   7165         }  
   7166         if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_PERIOD){
   7167             endpoint_info->faults |= 
   7168                 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_PERIOD;
   7169         }  
   7170         if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_PRIORITY){
   7171             endpoint_info->faults |= 
   7172                 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_PRIORITY;
   7173         }  
   7174         if(msg.fault_flags & BHH_BTE_EVENT_CSF_LOS) {
   7175             endpoint_info->faults |= BCM_OAM_ENDPOINT_BHH_FAULT_CSF_LOS;
   7176         }
   7177         if(msg.fault_flags & BHH_BTE_EVENT_CSF_FDI) {
   7178             endpoint_info->faults |= BCM_OAM_ENDPOINT_BHH_FAULT_CSF_FDI;
   7179         }
   7180         if(msg.fault_flags & BHH_BTE_EVENT_CSF_RDI) {
   7181             endpoint_info->faults |= BCM_OAM_ENDPOINT_BHH_FAULT_CSF_RDI;
   7182         }
   7183     }
   7184 
   7185     endpoint_info->intf_id    = h_data_p->egress_if;
   7186     endpoint_info->mpls_label = h_data_p->label;
   7187     endpoint_info->gport      = h_data_p->gport;
   7188     endpoint_info->vpn        = h_data_p->vpn;
   7189     endpoint_info->trunk_index = h_data_p->trunk_index;
   7190     if(endpoint_info->flags & BCM_OAM_ENDPOINT_REMOTE){
   7191         endpoint_info->name = msg.remote_mep_id;
   7192         endpoint_info->local_id = endpoint_info->id;
   7193     }
   7194     if(!BHH_EP_MPLS_SECTION_TYPE(h_data_p)){
   7195         /*
   7196          * Get MAC address
   7197          */
   7198         bcm_l3_egress_t_init(&l3_egress);
   7199         bcm_l3_intf_t_init(&l3_intf);
   7200 
   7201         if (BCM_FAILURE
   7202                 (bcm_esw_l3_egress_get(unit, h_data_p->egress_if, &l3_egress))) {
   7203             return (BCM_E_INTERNAL);
   7204         }
   7205 
   7206         l3_intf.l3a_intf_id = l3_egress.intf;
   7207         if (BCM_FAILURE(bcm_esw_l3_intf_get(unit, &l3_intf))) {
   7208             return (BCM_E_INTERNAL);
   7209         }
   7210 
   7211         sal_memcpy(endpoint_info->src_mac_address, l3_intf.l3a_mac_addr, 
   7212                 _BHH_MAC_ADDR_LENGTH);
   7213     }else {
   7214         sal_memcpy(endpoint_info->src_mac_address, h_data_p->src_mac_address,
   7215                 _BHH_MAC_ADDR_LENGTH);
   7216     }
   7217 
   7218 
   7219 
   7220     endpoint_info->group = h_data_p->group_index;
   7221 
   7222     endpoint_info->vlan = h_data_p->vlan;
   7223     endpoint_info->inner_vlan = h_data_p->inner_vlan;
   7224     endpoint_info->level = h_data_p->level;
   7225     endpoint_info->gport = h_data_p->gport;
   7226     endpoint_info->flags |= h_data_p->flags;
   7227     endpoint_info->flags &= ~(BCM_OAM_ENDPOINT_WITH_ID);
   7228     endpoint_info->flags2 = h_data_p->flags2;
   7229     endpoint_info->type = h_data_p->type;
   7230     endpoint_info->vccv_type  = h_data_p->vccv_type;
   7231     endpoint_info->outer_tpid = h_data_p->outer_tpid;
   7232     endpoint_info->inner_tpid = h_data_p->inner_tpid;
   7233     endpoint_info->egress_label.label = h_data_p->egr_label;
   7234     endpoint_info->egress_label.exp = h_data_p->egr_label_exp;
   7235     endpoint_info->egress_label.ttl = h_data_p->egr_label_ttl;
   7236     for (i=0; i< BCM_OAM_LM_COUNTER_MAX; i++)
   7237     {
   7238         endpoint_info->ccm_tx_update_lm_counter_base_id[i] = 
   7239                         h_data_p->ccm_tx_update_lm_counter_base_id[i];
   7240         endpoint_info->ccm_tx_update_lm_counter_offset[i] = 
   7241                         h_data_p->ccm_tx_update_lm_counter_offset[i];
   7242         endpoint_info->ccm_tx_update_lm_counter_action[i] = 
   7243                         bcmOamCounterActionIncrement; 
   7244     }
   7245     
   7246     endpoint_info->session_id = h_data_p->hw_session_id;
   7247     
   7248     endpoint_info->session_num_entries = h_data_p->hw_session_num_entries;
   7249     
   7250     endpoint_info->ccm_tx_update_lm_counter_size = 
   7251         h_data_p->ccm_tx_counter_size;
   7252     return (BCM_E_NONE);
   7253 }
   7254 
   7255 
   7256 /*
   7257  * Function:
   7258  *     _bcm_fp_oam_bhh_endpoint_destroy
   7259  * Purpose:
   7260  *     Delete an endpoint and free all its allocated resources.
   7261  * Parameters:
   7262  *     unit   - (IN) BCM device number
   7263  *     ep_id  - (IN) Endpoint ID value.
   7264  * Retruns:
   7265  *     BCM_E_XXX
   7266  */
   7267 STATIC int
   7268 _bcm_fp_oam_bhh_endpoint_destroy(int unit,
   7269                               bcm_oam_endpoint_t ep_id)
   7270 {
   7271     _bcm_fp_oam_control_t    *oc;        /* Pointer to OAM control structure. */
   7272     _bhh_fp_oam_ep_data_t    *h_data_p;  /* Pointer to endpoint data.         */
   7273     _bhh_fp_oam_hash_key_t   hash_key;   /* Hash key buffer for lookup.       */
   7274     bcm_oam_endpoint_info_t ep_info;    /* Endpoint information.             */
   7275     _bhh_fp_oam_ep_data_t    h_data;     /* Pointer to endpoint data.         */
   7276     _bhh_fp_oam_group_data_t *group_p;   /* Pointer to group data.       */
   7277     uint16 reply_len;
   7278     bcm_oam_endpoint_t bhh_pool_ep_id;
   7279     int                  rv = BCM_E_NONE;/* Operation return status.          */
   7280     int bhh_group_idx = 0;
   7281 
   7282     /* Lock already taken by the calling routine. */
   7283     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
   7284 
   7285     bhh_pool_ep_id = BCM_OAM_BHH_GET_UKERNEL_EP(ep_id);
   7286     /* Get the hash data pointer. */
   7287     h_data_p = &oc->bhh_ep_data[bhh_pool_ep_id];
   7288     if(0 == h_data_p->in_use){
   7289         return BCM_E_NOT_FOUND; 
   7290     } 
   7291     bhh_group_idx = BCM_OAM_BHH_GET_UKERNEL_GROUP(h_data_p->group_index);
   7292     group_p = &(oc->bhh_group_data[bhh_group_idx]);
   7293     if (h_data_p->is_remote) {
   7294         /*
   7295          * BHH uses same index for local and remote.  
   7296          * So, delete always goes through
   7297          * local endpoint destory
   7298          */
   7299         return (BCM_E_NONE);
   7300     } else {
   7301 
   7302         if (!SOC_WARM_BOOT(unit)) {
   7303             /*Send BHH Session Delete message to uC.Error response is not an
   7304               during switch re-init as uKernel is reloaded and its state is
   7305               cleared before oam init. As such endpoint wont exist during 
   7306               oam init*/
   7307             rv = _bcm_fp_oam_msg_send_receive(unit,
   7308                     MOS_MSG_CLASS_BHH, 
   7309                     MOS_MSG_SUBCLASS_BHH_SESS_DELETE,
   7310                     (int)bhh_pool_ep_id, 0,
   7311                     MOS_MSG_SUBCLASS_BHH_SESS_DELETE_REPLY,
   7312                     &reply_len);
   7313             if (BCM_FAILURE(rv)) {
   7314                 LOG_ERROR(BSL_LS_BCM_OAM,
   7315                         (BSL_META_U(unit,
   7316                                     "OAM(unit %d) Error: ukernel msg "
   7317                                     "failed forEP=%d %s.\n"), unit, ep_id,
   7318                          bcm_errmsg(rv)));
   7319                 return (rv);
   7320             }
   7321 
   7322         }
   7323 
   7324         h_data_p->in_use = 0;
   7325 
   7326         /* Return ID back to free MEP ID pool.*/
   7327         BCM_IF_ERROR_RETURN(shr_idxres_list_free(oc->bhh_pool, 
   7328                     bhh_pool_ep_id));
   7329 
   7330         /* Set up endpoint information for key construction. */
   7331         ep_info.group = h_data_p->group_index;
   7332         ep_info.name = h_data_p->name;
   7333         ep_info.gport = h_data_p->gport;
   7334         ep_info.level = h_data_p->level;
   7335         ep_info.vlan = h_data_p->vlan;
   7336         ep_info.inner_vlan = h_data_p->inner_vlan;
   7337         ep_info.flags = h_data_p->flags;
   7338         ep_info.mpls_label = h_data_p->label;
   7339         ep_info.type       = h_data_p->type;
   7340 
   7341         /* Construct hash key for lookup + delete operation. */
   7342         _bhh_fp_oam_ep_hash_key_construct(unit, oc, &ep_info, &hash_key);
   7343 
   7344         /* Remove entry from hash table. */
   7345         BCM_IF_ERROR_RETURN(shr_htb_find(oc->bhh_mep_htbl, hash_key,
   7346                     (shr_htb_data_t *)&h_data,
   7347                     1));
   7348 
   7349         /* Clear the hash data memory previously occupied by this endpoint*/
   7350         _BHH_FP_OAM_HASH_DATA_CLEAR(h_data_p);
   7351  
   7352         group_p->lmep_id = _BHH_FP_OAM_INVALID_LMEP_ID;
   7353 
   7354     }
   7355     
   7356     return (BCM_E_NONE);
   7357 }
   7358 
   7359 /*
   7360  * Function:
   7361  *     _bcm_fp_oam_bhh_group_destroy
   7362  * Purpose:
   7363  *     Delete a BHH group object. All OAM endpoints associated with the
   7364  *     group will also be destroyed.
   7365  * Parameters:
   7366  *     unit       - (IN) BCM device number
   7367  *     group_id - (IN/OUT) Pointer to an OAM group Id.
   7368  * Returns:
   7369  *     BCM_E_XXX
   7370  */
   7371 int
   7372 _bcm_fp_oam_bhh_group_destroy(int unit, bcm_oam_group_t group_id)
   7373 {
   7374     _bcm_fp_oam_control_t *oc = NULL;           /* OAM control structure */
   7375     _bhh_fp_oam_group_data_t *group_p;          /* Handle to S/w Group Data */
   7376     int rv = 0;                                 /* Return Value */
   7377     int bhh_group_idx = 0;
   7378 
   7379     /* Get OAM control structure handle. */
   7380     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
   7381 
   7382     bhh_group_idx = BCM_OAM_BHH_GET_UKERNEL_GROUP(group_id);
   7383     /* Get Handle to Local DB */
   7384     group_p = &(oc->bhh_group_data[bhh_group_idx]);
   7385     if (!(group_p->in_use)) {
   7386         return BCM_E_NOT_FOUND;
   7387     }
   7388 
   7389     if (group_p->lmep_id != _BHH_FP_OAM_INVALID_LMEP_ID) {
   7390         rv = _bcm_fp_oam_bhh_endpoint_destroy(unit, group_p->lmep_id);
   7391         if (BCM_FAILURE(rv)) {
   7392             LOG_ERROR(BSL_LS_BCM_OAM,
   7393                     (BSL_META_U(unit,
   7394                                 "OAM(unit %d) Error: EP destroy failed for " 
   7395                                 "(EP=%d) - %s.\n"), unit, 
   7396                      group_p->lmep_id, bcm_errmsg(rv)));
   7397             return (rv);
   7398         }
   7399     }
   7400     sal_memset(group_p, 0, sizeof(_bhh_fp_oam_group_data_t));
   7401     group_p->lmep_id = _BHH_FP_OAM_INVALID_LMEP_ID;
   7402     /* Return Group ID back to free group pool. */
   7403     rv = shr_idxres_list_free(oc->bhh_group_pool, bhh_group_idx);
   7404     if (BCM_FAILURE(rv)) {
   7405         LOG_ERROR(BSL_LS_BCM_OAM,
   7406                 (BSL_META_U(unit,
   7407                             "OAM(unit %d) Error: Free of group "
   7408                             "index failed for group=%d %s.\n"), unit,
   7409                  group_id,
   7410                  bcm_errmsg(rv)));
   7411 
   7412         return (rv);
   7413     }
   7414     return rv;
   7415 }
   7416 
   7417 /*
   7418  * Function:
   7419  *     _bcm_fp_oam_bhh_endpoint_destroy_all
   7420  * Purpose:
   7421  *     Delete all endpointans associated with group and free all its allocated
   7422  *     resources.
   7423  * Parameters:
   7424  *     unit   - (IN) BCM device number
   7425  *     ep_id  - (IN) Endpoint ID value.
   7426  * Retruns:
   7427  *     BCM_E_XXX
   7428  */
   7429 
   7430 int
   7431 _bcm_fp_oam_bhh_endpoint_destroy_all(int unit, bcm_oam_group_t group_id)
   7432 {
   7433     _bcm_fp_oam_control_t *oc = NULL;           /* OAM control structure */
   7434     _bhh_fp_oam_group_data_t *group_p;          /* Handle to S/w Group Data */
   7435     int rv = 0;                                 /* Return Value */
   7436     int bhh_group_idx = 0;
   7437 
   7438     /* Get OAM control structure handle. */
   7439     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
   7440 
   7441     bhh_group_idx = BCM_OAM_BHH_GET_UKERNEL_GROUP(group_id);
   7442     /* Get Handle to Local DB */
   7443     group_p = &(oc->bhh_group_data[bhh_group_idx]);
   7444     if (!(group_p->in_use)) {
   7445         return BCM_E_NOT_FOUND;
   7446     }
   7447 
   7448     if (group_p->lmep_id != _BHH_FP_OAM_INVALID_LMEP_ID) {
   7449         rv = _bcm_fp_oam_bhh_endpoint_destroy(unit, group_p->lmep_id);
   7450         if (BCM_FAILURE(rv)) {
   7451             LOG_ERROR(BSL_LS_BCM_OAM,
   7452                     (BSL_META_U(unit,
   7453                                 "OAM(unit %d) Error: EP destroy failed for " 
   7454                                 "(EP=%d) - %s.\n"), unit, 
   7455                      group_p->lmep_id, bcm_errmsg(rv)));
   7456             return rv;
   7457         }
   7458     }
   7459     group_p->lmep_id = _BHH_FP_OAM_INVALID_LMEP_ID;
   7460 
   7461     return rv;
   7462 }
   7463 
   7464 /*
   7465  * Function:
   7466  *     _bcm_fp_oam_bhh_endpoint_traverse
   7467  * Purpose:
   7468  *     Traverse the entire set of BHH endpoints associated with group,
   7469  *     calling a specified callback for each one
   7470  * Parameters:
   7471  *     unit  - (IN) BCM device number
   7472  *     group     - (IN) Group ID of endpoints associated.
   7473  *     cb        - (IN) Pointer to call back function.
   7474  *     user_data - (IN) Pointer to user supplied data.
   7475  * Returns:
   7476  *     BCM_E_XXX
   7477  */
   7478 int
   7479 _bcm_fp_oam_bhh_endpoint_traverse(int unit, bcm_oam_group_t group,
   7480                            bcm_oam_endpoint_traverse_cb cb,
   7481                            void *user_data)
   7482 {
   7483     _bcm_fp_oam_control_t    *oc;        /* OAM control structure pointer. */
   7484     bcm_oam_endpoint_info_t endpoint_info; /* Group information to be set.   */
   7485     _bhh_fp_oam_group_data_t *group_p;          /* Handle to S/w Group Data */
   7486     int rv = 0;                                 /* Return Value */
   7487     int bhh_group_idx = 0;
   7488 
   7489     if (NULL == cb) {
   7490         return (BCM_E_PARAM);
   7491     }
   7492 
   7493     /* Get device OAM control structure handle. */
   7494     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
   7495 
   7496     bhh_group_idx = BCM_OAM_BHH_GET_UKERNEL_GROUP(group);
   7497     /* Get Handle to Local DB */
   7498     group_p = &(oc->bhh_group_data[bhh_group_idx]);
   7499     if (!(group_p->in_use)) {
   7500         return BCM_E_NOT_FOUND;
   7501     }
   7502     if (group_p->lmep_id != _BHH_FP_OAM_INVALID_LMEP_ID) {
   7503         sal_memset(&endpoint_info, 0, sizeof(endpoint_info));
   7504         endpoint_info.id = group_p->lmep_id;
   7505         rv = _bcm_fp_oam_bhh_endpoint_get(unit, &endpoint_info);
   7506 
   7507         /* Call the user call back routine with group information. */
   7508         rv = cb(unit, &endpoint_info, user_data);
   7509         if (BCM_FAILURE(rv)) {
   7510             LOG_ERROR(BSL_LS_BCM_OAM,
   7511                     (BSL_META_U(unit,
   7512                                 "OAM(unit %d) Error: User call back " 
   7513                                 "routine (EP=%d) - %s.\n"), unit, 
   7514                      endpoint_info.id, bcm_errmsg(rv)));
   7515             return (rv);
   7516         }
   7517     }
   7518 
   7519     return BCM_E_NONE;
   7520 }
   7521 
   7522 /* BHH Event Handler */
   7523 typedef struct _event_handler_s {
   7524     struct _event_handler_s *next;
   7525     bcm_oam_event_types_t event_types;
   7526     bcm_oam_event_cb cb;
   7527     void *user_data;
   7528 } _event_handler_t;
   7529 
   7530 /*
   7531  * Function:
   7532  *      _bcm_fp_oam_bhh_event_mask_set
   7533  * Purpose:
   7534  *      Set the BHH Events mask.
   7535  *      Events are set per BHH module.
   7536  * Parameters:
   7537  *      unit        - (IN) Unit number.
   7538  * Returns:
   7539  *      BCM_E_NONE Operation completed successfully
   7540  *      BCM_E_XXX  Operation failed
   7541  * Notes:
   7542  */
   7543 STATIC int
   7544 _bcm_fp_oam_bhh_event_mask_set(int unit)
   7545 {
   7546     _bcm_fp_oam_control_t *oc;
   7547     _bcm_oam_event_handler_t *event_handler_p;
   7548     uint32 event_mask = 0;
   7549     uint16 reply_len;
   7550     int rv = BCM_E_NONE;
   7551 
   7552     /* Lock already taken by the calling routine. */
   7553     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
   7554 
   7555     /* Get event mask from all callbacks */
   7556     for (event_handler_p = oc->event_handler_list_p;
   7557          event_handler_p != NULL;
   7558          event_handler_p = event_handler_p->next_p) {
   7559 
   7560         if (SHR_BITGET(event_handler_p->event_types.w,
   7561                        bcmOAMEventBHHLBTimeout)) {
   7562             event_mask |= BHH_BTE_EVENT_LB_TIMEOUT;
   7563         }
   7564         if (SHR_BITGET(event_handler_p->event_types.w,
   7565                        bcmOAMEventBHHLBDiscoveryUpdate)) {
   7566             event_mask |= BHH_BTE_EVENT_LB_DISCOVERY_UPDATE;
   7567         }
   7568         if (SHR_BITGET(event_handler_p->event_types.w,
   7569                        bcmOAMEventBHHCCMTimeout)) {
   7570             event_mask |= BHH_BTE_EVENT_CCM_TIMEOUT;
   7571         }
   7572         if (SHR_BITGET(event_handler_p->event_types.w,
   7573                        bcmOAMEventBHHCCMTimeoutClear)) {
   7574             event_mask |= BHH_BTE_EVENT_CCM_TIMEOUT_CLEAR;
   7575         }
   7576         if (SHR_BITGET(event_handler_p->event_types.w,
   7577                        bcmOAMEventBHHCCMState)) {
   7578             event_mask |= BHH_BTE_EVENT_STATE;
   7579         }
   7580         if (SHR_BITGET(event_handler_p->event_types.w,
   7581                        bcmOAMEventBHHCCMRdi)) {
   7582             event_mask |= BHH_BTE_EVENT_CCM_RDI;
   7583         }
   7584         if (SHR_BITGET(event_handler_p->event_types.w,
   7585                        bcmOAMEventBHHCCMUnknownMegLevel)) {
   7586             event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_MEG_LEVEL;
   7587         }
   7588         if (SHR_BITGET(event_handler_p->event_types.w,
   7589                        bcmOAMEventBHHCCMUnknownMegId)) {
   7590             event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_MEG_ID;
   7591         }
   7592         if (SHR_BITGET(event_handler_p->event_types.w,
   7593                        bcmOAMEventBHHCCMUnknownMepId)) {
   7594             event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_MEP_ID;
   7595         }
   7596         if (SHR_BITGET(event_handler_p->event_types.w,
   7597                        bcmOAMEventBHHCCMUnknownPeriod)) {
   7598             event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_PERIOD;
   7599         }
   7600         if (SHR_BITGET(event_handler_p->event_types.w,
   7601                        bcmOAMEventBHHCCMUnknownPriority)) {
   7602             event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_PRIORITY;
   7603         }
   7604         if (SHR_BITGET(event_handler_p->event_types.w,
   7605                        bcmOAMEventBHHCCMRdiClear)) {
   7606             event_mask |= BHH_BTE_EVENT_CCM_RDI_CLEAR;
   7607         }
   7608         if (SHR_BITGET(event_handler_p->event_types.w,
   7609                        bcmOAMEventBHHCCMUnknownMegLevelClear)) {
   7610             event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_MEG_LEVEL_CLEAR;
   7611         }
   7612         if (SHR_BITGET(event_handler_p->event_types.w,
   7613                        bcmOAMEventBHHCCMUnknownMegIdClear)) {
   7614             event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_MEG_ID_CLEAR;
   7615         }
   7616         if (SHR_BITGET(event_handler_p->event_types.w,
   7617                        bcmOAMEventBHHCCMUnknownMepIdClear)) {
   7618             event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_MEP_ID_CLEAR;
   7619         }
   7620         if (SHR_BITGET(event_handler_p->event_types.w,
   7621                        bcmOAMEventBHHCCMUnknownPeriodClear)) {
   7622             event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_PERIOD_CLEAR;
   7623         }
   7624         if (SHR_BITGET(event_handler_p->event_types.w,
   7625                        bcmOAMEventBHHCCMUnknownPriorityClear)) {
   7626             event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_PRIORITY_CLEAR;
   7627         }
   7628         if (SHR_BITGET(event_handler_p->event_types.w,
   7629                     bcmOAMEventBhhPmCounterRollover)) {
   7630             event_mask |= BHH_BTE_EVENT_PM_STATS_COUNTER_ROLLOVER;
   7631         }
   7632         if (SHR_BITGET(event_handler_p->event_types.w, bcmOAMEventCsfLos)) {
   7633             event_mask |= BHH_BTE_EVENT_CSF_LOS;
   7634         }
   7635         if (SHR_BITGET(event_handler_p->event_types.w, bcmOAMEventCsfFdi)) {
   7636             event_mask |= BHH_BTE_EVENT_CSF_FDI;
   7637         }
   7638         if (SHR_BITGET(event_handler_p->event_types.w, bcmOAMEventCsfRdi)) {
   7639             event_mask |= BHH_BTE_EVENT_CSF_RDI;
   7640         }
   7641         if (SHR_BITGET(event_handler_p->event_types.w, bcmOAMEventCsfDci)) {
   7642             event_mask |= BHH_BTE_EVENT_CSF_DCI;
   7643         }
   7644     }
   7645 
   7646     /* Update BHH event mask in uKernel */
   7647     if (event_mask != oc->bhh_event_mask) {
   7648         /* Send BHH Event Mask message to uC */
   7649         rv = _bcm_fp_oam_msg_send_receive
   7650                 (unit,
   7651                  MOS_MSG_CLASS_BHH, 
   7652                  MOS_MSG_SUBCLASS_BHH_EVENT_MASK_SET,
   7653                  0, event_mask,
   7654                  MOS_MSG_SUBCLASS_BHH_EVENT_MASK_SET_REPLY,
   7655                  &reply_len);
   7656 
   7657         if(BCM_SUCCESS(rv) && (reply_len != 0)) {
   7658             rv = BCM_E_INTERNAL;
   7659         }
   7660     }
   7661 
   7662     oc->bhh_event_mask = event_mask;
   7663 
   7664     return (rv);
   7665 }
   7666 
   7667 /*
   7668  * Function:
   7669  *     bcm_fp_oam_loopback_add
   7670  * Purpose:
   7671  *     
   7672  * Parameters:
   7673  *     unit - Device unit number
   7674  * Returns:
   7675  *     None
   7676  */
   7677 int
   7678 bcm_fp_oam_loopback_add(int unit, bcm_oam_loopback_t *loopback_p)
   7679 {
   7680     _bcm_fp_oam_control_t *oc;
   7681     _bhh_fp_oam_ep_data_t *h_data_p;
   7682     int rv = BCM_E_NONE;
   7683     bhh_sdk_msg_ctrl_loopback_add_t msg;
   7684     uint8 *buffer, *buffer_ptr, encap_type;
   7685     uint16 buffer_len, reply_len;
   7686     uint32 flags = 0;
   7687     int sess_id = 0, i = 0;
   7688     _bhh_oam_lm_dm_info_t counter_info;
   7689     bcm_module_t         module_id;
   7690     bcm_port_t           port_id;
   7691     bcm_trunk_t          trunk_id;
   7692     int                  local_id;
   7693 
   7694     /* Get OAM Control Structure. */
   7695     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
   7696 
   7697     _BCM_OAM_LOCK(oc);
   7698 
   7699     BCM_OAM_BHH_VALIDATE_EP(loopback_p->id);
   7700 
   7701     sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(loopback_p->id);
   7702 
   7703     /* Check endpoint status. */
   7704     rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id);
   7705     if ((BCM_E_EXISTS != rv)) {
   7706         /* Endpoint not in use. */
   7707         LOG_ERROR(BSL_LS_BCM_OAM,
   7708                   (BSL_META_U(unit,
   7709                               "OAM(unit %d) Error: Endpoint EP=%d %s.\n"),
   7710                    unit, loopback_p->id, bcm_errmsg(rv)));
   7711         _BCM_OAM_UNLOCK(oc);
   7712         return (rv);
   7713     }
   7714 
   7715     /*Validate LB period */
   7716     rv = _bcm_fp_oam_period_validate(loopback_p->period);
   7717     if (BCM_FAILURE(rv)) {
   7718         LOG_ERROR(BSL_LS_BCM_OAM,
   7719                   (BSL_META_U(unit,
   7720                               "OAM(unit %d) Error: Invalid period : %d\n"),
   7721                    unit, loopback_p->period));
   7722         _BCM_OAM_UNLOCK(oc);
   7723         return (rv);
   7724     }
   7725 
   7726     h_data_p = &oc->bhh_ep_data[sess_id];
   7727 
   7728     h_data_p->lb_tx_counter_size = loopback_p->lb_tx_update_lm_counter_size;  
   7729     sal_memset(&counter_info, 0, sizeof(counter_info));
   7730     counter_info.counter_size = loopback_p->lb_tx_update_lm_counter_size; 
   7731     for (i=0; i< BCM_OAM_LM_COUNTER_MAX; i++)
   7732     {
   7733         h_data_p->lb_tx_update_lm_counter_base_id[i] =
   7734         loopback_p->lb_tx_update_lm_counter_base_id[i];
   7735         h_data_p->lb_tx_update_lm_counter_offset[i] =
   7736         loopback_p->lb_tx_update_lm_counter_offset[i];
   7737         counter_info.counter_base_id[i] = 
   7738         loopback_p->lb_tx_update_lm_counter_base_id[i];
   7739         counter_info.counter_offset[i] = 
   7740         loopback_p->lb_tx_update_lm_counter_offset[i];
   7741         counter_info.counter_action[i] = bcmOamCounterActionIncrement;
   7742         counter_info.byte_count_offset[i] = 0;
   7743     }
   7744     counter_info.ts_mode = BCM_PKT_TIMESTAMP_MODE_NONE;
   7745 
   7746     /*
   7747      * Convert host space flags to uKernel space flags
   7748      */
   7749 
   7750     if (loopback_p->flags & BCM_OAM_LOOPBACK_TX_ENABLE) {
   7751         flags |= BCM_BHH_TX_ENABLE;
   7752     }
   7753 
   7754     if (loopback_p->flags & BCM_OAM_BHH_INC_REQUESTING_MEP_TLV) {
   7755         flags |= BCM_BHH_INC_REQUESTING_MEP_TLV;
   7756     }
   7757 
   7758     if (loopback_p->flags & BCM_OAM_BHH_LBM_INGRESS_DISCOVERY_MEP_TLV) {
   7759         flags |= BCM_BHH_LBM_INGRESS_DISCOVERY_MEP_TLV;
   7760     } else if (loopback_p->flags & 
   7761             BCM_OAM_BHH_LBM_EGRESS_DISCOVERY_MEP_TLV) {
   7762         flags |= BCM_BHH_LBM_EGRESS_DISCOVERY_MEP_TLV;
   7763     } else if (loopback_p->flags & BCM_OAM_BHH_LBM_ICC_MEP_TLV) {
   7764         flags |= BCM_BHH_LBM_ICC_MEP_TLV;
   7765     } else if (loopback_p->flags & BCM_OAM_BHH_LBM_ICC_MIP_TLV) {
   7766         flags |= BCM_BHH_LBM_ICC_MIP_TLV;
   7767     } else {
   7768         flags |= BCM_BHH_LBM_ICC_MEP_TLV; /* Default */
   7769     }
   7770 
   7771     if (loopback_p->flags & BCM_OAM_BHH_LBR_ICC_MEP_TLV) {
   7772         flags |= BCM_BHH_LBR_ICC_MEP_TLV;
   7773     } else if (loopback_p->flags & BCM_OAM_BHH_LBR_ICC_MIP_TLV) {
   7774         flags |= BCM_BHH_LBR_ICC_MIP_TLV;
   7775     }
   7776 
   7777     sal_memset(&msg, 0, sizeof(msg));
   7778     msg.flags   = flags;
   7779     msg.sess_id = sess_id;
   7780     msg.int_pri = loopback_p->int_pri;
   7781     msg.pkt_pri = loopback_p->pkt_pri;
   7782 
   7783     /*
   7784      * Set period
   7785      */
   7786     msg.period  = loopback_p->period;
   7787 
   7788     /*
   7789      * Check TTL
   7790      */
   7791     if (loopback_p->ttl == 0 || loopback_p->ttl > 255) {
   7792         _BCM_OAM_UNLOCK(oc);
   7793         return BCM_E_PARAM;
   7794     }
   7795     /* Check for default usage of int_pri */
   7796     if (loopback_p->int_pri == -1) {
   7797         loopback_p->int_pri = 7; /*Use default */
   7798     }
   7799     /* Check for default usage of pkt_pri */
   7800     if (loopback_p->pkt_pri == 0xff) {
   7801         loopback_p->pkt_pri = 7; /*Use default */
   7802     }
   7803     if (BHH_EP_MPLS_SECTION_TYPE(h_data_p) ||
   7804             (h_data_p->type == bcmOAMEndpointTypeBHHMPLSVccv &&
   7805              h_data_p->vccv_type == bcmOamBhhVccvTtl)) {
   7806 
   7807         msg.ttl = 1; /* Only TTL 1 is valid */
   7808     } else {
   7809         msg.ttl = loopback_p->ttl;
   7810     }
   7811     if (h_data_p->trunk_id == BCM_TRUNK_INVALID) {
   7812         rv = _bcm_esw_gport_resolve(unit,
   7813                 h_data_p->gport, &module_id, &port_id, &trunk_id, &local_id);
   7814     } else {
   7815         rv = _bcm_esw_gport_resolve(unit,
   7816                 h_data_p->resolved_trunk_gport, &module_id, &port_id, 
   7817                 &trunk_id, &local_id);
   7818         
   7819     }
   7820 
   7821     if (BCM_FAILURE(rv)) {
   7822         LOG_ERROR(BSL_LS_BCM_OAM,
   7823                 (BSL_META_U(unit,
   7824                             "BHH(unit %d) Error: Gport resolve - %s.\n"),
   7825                  unit, bcm_errmsg(rv)));
   7826         _BCM_OAM_UNLOCK(oc);
   7827         return (rv);
   7828     }
   7829 
   7830         
   7831     /*
   7832      * Set the BHH encapsulation data
   7833      *
   7834      * The function _bcm_fp_oam_bhh_encap_create() is called first
   7835      * since this sets some fields in 'hash_data' which are
   7836      * used in the message.
   7837      */
   7838     rv = _bcm_fp_oam_bhh_encap_create(unit,
   7839             module_id,
   7840             port_id, 
   7841             h_data_p,
   7842             msg.encap_data,
   7843             &encap_type,
   7844             &msg.encap_length,
   7845             &counter_info, loopback_p->int_pri, loopback_p->pkt_pri,
   7846             loopback_p->ttl);
   7847     if(BCM_FAILURE(rv))
   7848     {
   7849         LOG_ERROR(BSL_LS_BCM_OAM,
   7850                 (BSL_META_U(unit,
   7851                             "BHH(unit %d) Error: Encap create failed "
   7852                             " - %s.\n"),
   7853                  unit, bcm_errmsg(rv)));
   7854         _BCM_OAM_UNLOCK(oc);
   7855         return (rv);
   7856     }
   7857     /* Pack control message data into DMA buffer */
   7858     buffer     = oc->bhh_dma_buffer;
   7859     buffer_ptr = bhh_sdk_msg_ctrl_loopback_add_pack(buffer, &msg);
   7860     buffer_len = buffer_ptr - buffer;
   7861 
   7862     /* Send BHH Session Update message to uC */
   7863     rv = _bcm_fp_oam_msg_send_receive(unit,
   7864             MOS_MSG_CLASS_BHH, 
   7865             MOS_MSG_SUBCLASS_BHH_LOOPBACK_ADD,
   7866             buffer_len, 0,
   7867             MOS_MSG_SUBCLASS_BHH_LOOPBACK_ADD_REPLY,
   7868             &reply_len);
   7869 
   7870     if(BCM_SUCCESS(rv) && (reply_len != 0)) {
   7871         rv =  BCM_E_INTERNAL;
   7872     }
   7873 
   7874 
   7875     _BCM_OAM_UNLOCK(oc);
   7876     return (rv);
   7877 }
   7878 
   7879 /*
   7880  * Function:
   7881  *     bcm_fp_oam_loopback_get
   7882  * Purpose:
   7883  *     
   7884  * Parameters:
   7885  *     unit - Device unit number
   7886  * Returns:
   7887  *     None
   7888  */
   7889 int
   7890 bcm_fp_oam_loopback_get(int unit, bcm_oam_loopback_t *loopback_p)
   7891 {
   7892     _bcm_fp_oam_control_t *oc;
   7893     int rv = BCM_E_NONE;
   7894     bhh_sdk_msg_ctrl_loopback_get_t msg;
   7895     _bhh_fp_oam_ep_data_t *h_data_p;
   7896     uint8 *buffer, *buffer_ptr;
   7897     uint16 buffer_len, reply_len;
   7898     int sess_id = 0, i = 0;
   7899     uint8*  encap_data = NULL;
   7900     soc_olp_l2_hdr_t olp_l2_header;
   7901     soc_olp_tx_hdr_t olp_oam_tx_header;
   7902 
   7903     /* Get OAM Control Structure. */
   7904     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
   7905 
   7906     _BCM_OAM_LOCK(oc);
   7907 
   7908     BCM_OAM_BHH_VALIDATE_EP(loopback_p->id);
   7909 
   7910     sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(loopback_p->id);
   7911 
   7912     /* Check endpoint status. */
   7913     rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id);
   7914     if ((BCM_E_EXISTS != rv)) {
   7915         /* Endpoint not in use. */
   7916         LOG_ERROR(BSL_LS_BCM_OAM,
   7917                 (BSL_META_U(unit,
   7918                             "OAM(unit %d) Error: Endpoint EP=%d %s.\n"),
   7919                  unit, loopback_p->id, bcm_errmsg(rv)));
   7920         _BCM_OAM_UNLOCK(oc);
   7921         return (rv);
   7922     }
   7923 
   7924     h_data_p = &oc->bhh_ep_data[sess_id];
   7925 
   7926 
   7927     sal_memset(&msg, 0, sizeof(msg));
   7928     /* Send BHH Session Update message to uC */
   7929     rv = _bcm_fp_oam_msg_send_receive(unit,
   7930             MOS_MSG_CLASS_BHH, 
   7931             MOS_MSG_SUBCLASS_BHH_LOOPBACK_GET,
   7932             sess_id, 0,
   7933             MOS_MSG_SUBCLASS_BHH_LOOPBACK_GET_REPLY,
   7934             &reply_len);
   7935     if(BCM_FAILURE(rv)) {
   7936         LOG_ERROR(BSL_LS_BCM_OAM,
   7937                 (BSL_META_U(unit,
   7938                             "OAM(unit %d) Error: Endpoint EP=%d %s.\n"),
   7939                  unit, loopback_p->id, bcm_errmsg(rv)));
   7940         _BCM_OAM_UNLOCK(oc);
   7941         return (rv);
   7942     }
   7943 
   7944     /* Pack control message data into DMA buffer */
   7945     buffer     = oc->bhh_dma_buffer;
   7946     buffer_ptr = bhh_sdk_msg_ctrl_loopback_get_unpack(buffer, &msg);
   7947     buffer_len = buffer_ptr - buffer;
   7948 
   7949 
   7950     if (reply_len != buffer_len) {
   7951         rv =  BCM_E_INTERNAL;
   7952     } else {
   7953         /*
   7954          * Convert kernel space flags to host space flags
   7955          */
   7956         if (msg.flags & BCM_BHH_INC_REQUESTING_MEP_TLV) {
   7957             loopback_p->flags |= BCM_OAM_BHH_INC_REQUESTING_MEP_TLV;
   7958         }
   7959 
   7960         if (msg.flags & BCM_BHH_LBM_INGRESS_DISCOVERY_MEP_TLV) {
   7961             loopback_p->flags |= BCM_OAM_BHH_LBM_INGRESS_DISCOVERY_MEP_TLV;
   7962         } else if (msg.flags & BCM_BHH_LBM_EGRESS_DISCOVERY_MEP_TLV) {
   7963             loopback_p->flags |= BCM_OAM_BHH_LBM_EGRESS_DISCOVERY_MEP_TLV;
   7964         } else if (msg.flags & BCM_BHH_LBM_ICC_MEP_TLV) {
   7965             loopback_p->flags |= BCM_OAM_BHH_LBM_ICC_MEP_TLV;
   7966         } else if (msg.flags & BCM_BHH_LBM_ICC_MIP_TLV) {
   7967             loopback_p->flags |= BCM_OAM_BHH_LBM_ICC_MIP_TLV;
   7968         }
   7969 
   7970         if (msg.flags & BCM_BHH_LBR_ICC_MEP_TLV) {
   7971             loopback_p->flags |= BCM_OAM_BHH_LBR_ICC_MEP_TLV;
   7972         } else if (msg.flags & BCM_BHH_LBR_ICC_MIP_TLV) {
   7973             loopback_p->flags |= BCM_OAM_BHH_LBR_ICC_MIP_TLV;
   7974         }
   7975 
   7976         if (msg.flags & BCM_BHH_TX_ENABLE) {
   7977             loopback_p->flags |= BCM_OAM_LOOPBACK_TX_ENABLE;
   7978         }
   7979 
   7980         loopback_p->period                  = msg.period;
   7981         loopback_p->ttl                     = msg.ttl;
   7982         loopback_p->discovered_me.flags     = msg.discovery_flags;
   7983         loopback_p->discovered_me.name      = msg.discovery_id;
   7984         loopback_p->discovered_me.ttl       = msg.discovery_ttl;
   7985         loopback_p->rx_count                = msg.rx_count;
   7986         loopback_p->tx_count                = msg.tx_count;
   7987         loopback_p->drop_count              = msg.drop_count;
   7988         loopback_p->unexpected_response     = msg.unexpected_response;
   7989         loopback_p->out_of_sequence         = msg.out_of_sequence;
   7990         loopback_p->local_mipid_missmatch   = msg.local_mipid_missmatch;
   7991         loopback_p->remote_mipid_missmatch  = msg.remote_mipid_missmatch;
   7992         loopback_p->invalid_target_mep_tlv  = msg.invalid_target_mep_tlv;
   7993         loopback_p->invalid_mep_tlv_subtype = msg.invalid_mep_tlv_subtype;
   7994         loopback_p->invalid_tlv_offset      = msg.invalid_tlv_offset;
   7995         for (i=0; i< BCM_OAM_LM_COUNTER_MAX; i++)
   7996         {
   7997             loopback_p->lb_tx_update_lm_counter_base_id[i] =
   7998                 h_data_p->lb_tx_update_lm_counter_base_id[i]; 
   7999             loopback_p->lb_tx_update_lm_counter_offset[i] =
   8000                 h_data_p->lb_tx_update_lm_counter_offset[i]; 
   8001         }
   8002         loopback_p->lb_tx_update_lm_counter_size = h_data_p->lb_tx_counter_size;
   8003 
   8004         encap_data = msg.encap_data;
   8005         encap_data = _bcm_fp_oam_olp_l2_header_unpack(encap_data,
   8006                                                       &olp_l2_header);
   8007         encap_data = shr_olp_tx_header_unpack(encap_data,
   8008                                               &olp_oam_tx_header);
   8009 
   8010         loopback_p->int_pri = SOC_OLP_TX_PRI_GET(&olp_oam_tx_header);
   8011 
   8012         loopback_p->pkt_pri =
   8013                    bcm_fp_oam_bhh_get_oam_exp_from_encap(h_data_p,
   8014                                                          msg.encap_data,
   8015                                                          msg.encap_length);
   8016         rv = BCM_E_NONE;
   8017     }
   8018 
   8019 
   8020     _BCM_OAM_UNLOCK(oc);
   8021 
   8022     return (rv);
   8023 }
   8024 
   8025 /*
   8026  * Function:
   8027  *     bcm_fp_oam_loopback_delete
   8028  * Purpose:
   8029  *     
   8030  * Parameters:
   8031  *     unit - Device unit number
   8032  * Returns:
   8033  *     None
   8034  */
   8035 int
   8036 bcm_fp_oam_loopback_delete(int unit, bcm_oam_loopback_t *loopback_p)
   8037 {
   8038     _bcm_fp_oam_control_t *oc;
   8039     int rv = BCM_E_NONE;
   8040     shr_bhh_msg_ctrl_loopback_delete_t msg;
   8041     uint8 *buffer, *buffer_ptr;
   8042     uint16 buffer_len, reply_len;
   8043     int sess_id = 0;
   8044     _bhh_fp_oam_ep_data_t *h_data_p;
   8045 
   8046     /* Get OAM Control Structure. */
   8047     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
   8048 
   8049     _BCM_OAM_LOCK(oc);
   8050 
   8051     BCM_OAM_BHH_VALIDATE_EP(loopback_p->id);
   8052 
   8053     sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(loopback_p->id);
   8054 
   8055     /* Check endpoint status. */
   8056     rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id);
   8057     if ((BCM_E_EXISTS != rv)) {
   8058         /* Endpoint not in use. */
   8059         LOG_ERROR(BSL_LS_BCM_OAM,
   8060                   (BSL_META_U(unit,
   8061                               "OAM(unit %d) Error: Endpoint EP=%d %s.\n"),
   8062                    unit, loopback_p->id, bcm_errmsg(rv)));
   8063         _BCM_OAM_UNLOCK(oc);
   8064         return (rv);
   8065     }
   8066 
   8067     h_data_p = &oc->bhh_ep_data[sess_id];
   8068 
   8069 
   8070     msg.sess_id = h_data_p->uc_session_id;
   8071 
   8072     /* Pack control message data into DMA buffer */
   8073     buffer     = oc->bhh_dma_buffer;
   8074     buffer_ptr = shr_bhh_msg_ctrl_loopback_delete_pack(buffer, &msg);
   8075     buffer_len = buffer_ptr - buffer;
   8076 
   8077     /* Send BHH Session Update message to uC */
   8078     rv = _bcm_fp_oam_msg_send_receive(unit,
   8079             MOS_MSG_CLASS_BHH, 
   8080             MOS_MSG_SUBCLASS_BHH_LOOPBACK_DELETE,
   8081             buffer_len, 0,
   8082             MOS_MSG_SUBCLASS_BHH_LOOPBACK_DELETE_REPLY,
   8083             &reply_len);
   8084 
   8085     if(BCM_SUCCESS(rv) && (reply_len != 0))
   8086         rv =  BCM_E_INTERNAL;
   8087 
   8088 
   8089     _BCM_OAM_UNLOCK(oc);
   8090 
   8091     return (rv);
   8092 }
   8093 
   8094 /*
   8095  * Function:
   8096  *     _bcm_fp_oam_bhh_loss_add
   8097  * Purpose:
   8098  *        Loss Measurement add for BHH endpoints.
   8099  * Parameters:
   8100  *     unit - Device unit number
   8101  * Returns:
   8102  *     None
   8103  */
   8104 int
   8105 _bcm_fp_oam_bhh_loss_add(int unit, bcm_oam_loss_t *loss_p)
   8106 {
   8107     _bcm_fp_oam_control_t *oc;
   8108     _bhh_fp_oam_ep_data_t *h_data_p;
   8109     int rv = BCM_E_NONE;
   8110     uint8 *buffer, *buffer_ptr, encap_type;
   8111     uint16 buffer_len, reply_len;
   8112     uint32 flags = 0;
   8113     int sess_id = 0, i = 0;
   8114     _bhh_oam_lm_dm_info_t counter_info;
   8115     bcm_module_t         module_id;
   8116     bcm_port_t           port_id;
   8117     bcm_trunk_t          trunk_id;
   8118     int                  local_id;
   8119     
   8120     /* Get OAM Control Structure. */
   8121     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
   8122 
   8123     _BCM_OAM_LOCK(oc);
   8124 
   8125     /* Validate the index passed by user is within range */
   8126     BCM_OAM_BHH_VALIDATE_EP(loss_p->id);
   8127 
   8128     sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(loss_p->id);
   8129     h_data_p = &oc->bhh_ep_data[sess_id];
   8130 
   8131     if (!(h_data_p->in_use)) {
   8132         /* Endpoint not in use. */
   8133         LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM(unit %d) Error: "
   8134             "Endpoint EP=%d not configured.\n"), unit, loss_p->id));
   8135         _BCM_OAM_UNLOCK(oc);
   8136         return BCM_E_NOT_FOUND;
   8137     }
   8138     /*Validate LM period */
   8139     rv = _bcm_fp_oam_period_validate(loss_p->period);
   8140     if (BCM_FAILURE(rv)) {
   8141         LOG_ERROR(BSL_LS_BCM_OAM,
   8142                   (BSL_META_U(unit,
   8143                               "OAM(unit %d) Error: Invalid period : %d\n"),
   8144                    unit, loss_p->period));
   8145         _BCM_OAM_UNLOCK(oc);
   8146         return rv;
   8147     }
   8148 
   8149     h_data_p->lm_counter_size = loss_p->lm_counter_size;  
   8150     sal_memset(&counter_info, 0, sizeof(counter_info));
   8151     counter_info.counter_size = loss_p->lm_counter_size;
   8152     for (i=0; i< BCM_OAM_LM_COUNTER_MAX; i++)
   8153     {
   8154         h_data_p->lm_counter_base_id[i] = loss_p->lm_counter_base_id[i];
   8155         h_data_p->lm_counter_offset[i] = loss_p->lm_counter_offset[i];
   8156         h_data_p->lm_counter_action[i] = loss_p->lm_counter_action[i];
   8157         counter_info.counter_base_id[i] = loss_p->lm_counter_base_id[i];
   8158         counter_info.counter_offset[i] = loss_p->lm_counter_offset[i];
   8159         counter_info.counter_action[i] = loss_p->lm_counter_action[i];
   8160         counter_info.byte_count_offset[i] = 0;
   8161     }
   8162     counter_info.ts_mode = BCM_PKT_TIMESTAMP_MODE_NONE;
   8163     counter_info.oam_replacement_offset = SHR_BHH_HEADER_LENGTH;
   8164 
   8165     bhh_sdk_msg_ctrl_loss_add_t msg;
   8166 
   8167     sal_memset(&msg, 0, sizeof(msg));
   8168 
   8169     /* Check endpoint status. */
   8170     rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id);
   8171     if ((BCM_E_EXISTS != rv)) {
   8172         /* Endpoint not in use. */
   8173         LOG_ERROR(BSL_LS_BCM_OAM,
   8174                   (BSL_META_U(unit,
   8175                               "OAM(unit %d) Error: Endpoint EP=%d %s.\n"),
   8176                    unit, loss_p->id, bcm_errmsg(rv)));
   8177         _BCM_OAM_UNLOCK(oc);
   8178         return (rv);
   8179     }
   8180         
   8181 
   8182     /*
   8183      * Convert host space flags to uKernel space flags
   8184      */
   8185     if (loss_p->flags & BCM_OAM_LOSS_SINGLE_ENDED) {
   8186         flags |= BCM_BHH_LM_SINGLE_ENDED;
   8187     }
   8188 
   8189     if (loss_p->flags & BCM_OAM_LOSS_TX_ENABLE) {
   8190         flags |= BCM_BHH_LM_TX_ENABLE;
   8191     }
   8192 
   8193     if (loss_p->flags & BCM_OAM_LOSS_SLM) {
   8194         flags |= BCM_BHH_LM_SLM;
   8195     }
   8196 
   8197     sal_memset(&msg, 0, sizeof(msg));
   8198     msg.flags   = flags;
   8199     msg.sess_id = sess_id;
   8200 
   8201     /*
   8202      * Set period
   8203      */
   8204     msg.period  = loss_p->period;
   8205     msg.int_pri = loss_p->int_pri;
   8206     msg.pkt_pri = loss_p->pkt_pri;
   8207     if (h_data_p->trunk_id == BCM_TRUNK_INVALID) {
   8208         rv = _bcm_esw_gport_resolve(unit,
   8209                 h_data_p->gport, &module_id, &port_id, &trunk_id, &local_id);
   8210     } else {
   8211         rv = _bcm_esw_gport_resolve(unit,
   8212                 h_data_p->resolved_trunk_gport, &module_id, &port_id, 
   8213                 &trunk_id, &local_id);
   8214         
   8215     } 
   8216     if (BCM_FAILURE(rv)) {
   8217         LOG_ERROR(BSL_LS_BCM_OAM,
   8218                 (BSL_META_U(unit,
   8219                             "BHH(unit %d) Error: Gport resolve - %s.\n"),
   8220                  unit, bcm_errmsg(rv)));
   8221         _BCM_OAM_UNLOCK(oc);
   8222         return (rv);
   8223     }
   8224 
   8225         
   8226     /*
   8227      * Set the BHH encapsulation data
   8228      *
   8229      * The function _bcm_fp_oam_bhh_encap_create() is called first
   8230      * since this sets some fields in 'hash_data' which are
   8231      * used in the message.
   8232      */
   8233     rv = _bcm_fp_oam_bhh_encap_create(unit,
   8234             module_id,
   8235             port_id, 
   8236             h_data_p,
   8237             msg.encap_data,
   8238             &encap_type,
   8239             &msg.encap_length,
   8240             &counter_info, loss_p->int_pri, loss_p->pkt_pri,
   8241             h_data_p->egr_label_ttl);
   8242     if(BCM_FAILURE(rv))
   8243     {
   8244         LOG_ERROR(BSL_LS_BCM_OAM,
   8245                 (BSL_META_U(unit,
   8246                             "BHH(unit %d) Error: Encap create failed "
   8247                             " - %s.\n"),
   8248                  unit, bcm_errmsg(rv)));
   8249         _BCM_OAM_UNLOCK(oc);
   8250         return (rv);
   8251     }
   8252     /* Pack control message data into DMA buffer */
   8253     buffer     = oc->bhh_dma_buffer;
   8254     buffer_ptr = bhh_sdk_msg_ctrl_loss_add_pack(buffer, &msg);
   8255     buffer_len = buffer_ptr - buffer;
   8256 
   8257     /* Send BHH Session Update message to uC */
   8258     rv = _bcm_fp_oam_msg_send_receive(unit,
   8259                       MOS_MSG_CLASS_BHH, 
   8260                       MOS_MSG_SUBCLASS_BHH_LOSS_MEASUREMENT_ADD,
   8261                       buffer_len, 0,
   8262                       MOS_MSG_SUBCLASS_BHH_LOSS_MEASUREMENT_ADD_REPLY,
   8263                       &reply_len);
   8264 
   8265     loss_p->pm_id = sess_id;
   8266 
   8267     if(BCM_SUCCESS(rv) && (reply_len != 0)) 
   8268         rv =  BCM_E_INTERNAL;
   8269     
   8270 
   8271     _BCM_OAM_UNLOCK(oc);
   8272     return (rv);
   8273 }
   8274 
   8275 /*
   8276  * Function:
   8277  *     _bcm_fp_oam_bhh_loss_get
   8278  * Purpose:
   8279  *     Loss Measurement get for BHH endpoints
   8280  * Parameters:
   8281  *     unit - Device unit number
   8282  * Returns:
   8283  *     None
   8284  */
   8285 int
   8286 _bcm_fp_oam_bhh_loss_get(int unit, bcm_oam_loss_t *loss_p)
   8287 {
   8288     _bcm_fp_oam_control_t *oc;
   8289     int rv = BCM_E_NONE;
   8290     _bhh_fp_oam_ep_data_t *h_data_p;
   8291     uint8 *buffer, *buffer_ptr;
   8292     uint16 buffer_len, reply_len;
   8293     int sess_id = 0, i = 0;
   8294     bhh_sdk_msg_ctrl_loss_get_t msg;
   8295     uint8*  encap_data = NULL;
   8296     soc_olp_l2_hdr_t olp_l2_header;
   8297     soc_olp_tx_hdr_t olp_oam_tx_header;
   8298 
   8299 
   8300     /* Get OAM Control Structure. */
   8301     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
   8302 
   8303     _BCM_OAM_LOCK(oc);
   8304 
   8305     BCM_OAM_BHH_VALIDATE_EP(loss_p->id);
   8306 
   8307     sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(loss_p->id);
   8308     h_data_p = &oc->bhh_ep_data[sess_id];
   8309     if (!(h_data_p->in_use)) {
   8310         /* Endpoint not in use. */
   8311         LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM(unit %d) Error: "
   8312             "Endpoint EP=%d %s.\n"), unit, loss_p->id, bcm_errmsg(rv)));
   8313         _BCM_OAM_UNLOCK(oc);
   8314         return BCM_E_NOT_FOUND;
   8315     }
   8316 
   8317 
   8318     /* Check endpoint status. */
   8319     rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id);
   8320     if ((BCM_E_EXISTS != rv)) {
   8321         /* Endpoint not in use. */
   8322         LOG_ERROR(BSL_LS_BCM_OAM,
   8323                 (BSL_META_U(unit,
   8324                             "OAM(unit %d) Error: Endpoint EP=%d %s.\n"),
   8325                  unit, loss_p->id, bcm_errmsg(rv)));
   8326         _BCM_OAM_UNLOCK(oc);
   8327         return (rv);
   8328     }
   8329 
   8330     sal_memset(&msg, 0, sizeof(msg));
   8331     /* Send BHH Session Update message to uC */
   8332     rv = _bcm_fp_oam_msg_send_receive(unit,
   8333             MOS_MSG_CLASS_BHH, 
   8334             MOS_MSG_SUBCLASS_BHH_LOSS_MEASUREMENT_GET,
   8335             sess_id, 0,
   8336             MOS_MSG_SUBCLASS_BHH_LOSS_MEASUREMENT_GET_REPLY,
   8337             &reply_len);
   8338     if(BCM_FAILURE(rv)) {
   8339         LOG_ERROR(BSL_LS_BCM_OAM,
   8340                 (BSL_META_U(unit,
   8341                             "OAM(unit %d) Error: Endpoint EP=%d %s.\n"),
   8342                  unit, loss_p->id, bcm_errmsg(rv)));
   8343         _BCM_OAM_UNLOCK(oc);
   8344         return (rv);
   8345     }
   8346 
   8347     /* Pack control message data into DMA buffer */
   8348     buffer     = oc->bhh_dma_buffer;
   8349     buffer_ptr = bhh_sdk_msg_ctrl_loss_get_unpack(buffer, &msg);
   8350     buffer_len = buffer_ptr - buffer;
   8351 
   8352     if (reply_len != buffer_len) {
   8353         rv =  BCM_E_INTERNAL;
   8354     } else {
   8355         /*
   8356          * Convert kernel space flags to host space flags
   8357          */
   8358         if (msg.flags & BCM_BHH_LM_SINGLE_ENDED) {
   8359             loss_p->flags |= BCM_OAM_LOSS_SINGLE_ENDED;
   8360         }
   8361 
   8362         if (msg.flags & BCM_BHH_LM_TX_ENABLE) {
   8363             loss_p->flags |= BCM_OAM_LOSS_TX_ENABLE;
   8364         }
   8365 
   8366         if (msg.flags & BCM_BHH_LM_SLM) {
   8367             loss_p->flags |= BCM_OAM_LOSS_SLM;
   8368         }
   8369 
   8370         loss_p->period = msg.period;
   8371         loss_p->loss_threshold = msg.loss_threshold;             
   8372         loss_p->loss_nearend = msg.loss_nearend;               
   8373         loss_p->loss_farend = msg.loss_farend;    
   8374         loss_p->tx_nearend = msg.tx_nearend;            
   8375         loss_p->rx_nearend = msg.rx_nearend;              
   8376         loss_p->tx_farend = msg.tx_farend;               
   8377         loss_p->rx_farend = msg.rx_farend;               
   8378         loss_p->rx_oam_packets = msg.rx_oam_packets;          
   8379         loss_p->tx_oam_packets = msg.tx_oam_packets;          
   8380         loss_p->int_pri = msg.int_pri;
   8381         loss_p->pkt_pri = msg.pkt_pri;         
   8382         loss_p->pm_id = sess_id;
   8383         for (i=0; i< BCM_OAM_LM_COUNTER_MAX; i++)
   8384         {
   8385             loss_p->lm_counter_base_id[i] =
   8386                 h_data_p->lm_counter_base_id[i]; 
   8387             loss_p->lm_counter_offset[i] =
   8388                 h_data_p->lm_counter_offset[i]; 
   8389             loss_p->lm_counter_action[i] =
   8390                 h_data_p->lm_counter_action[i]; 
   8391         }
   8392         loss_p->lm_counter_size = h_data_p->lm_counter_size;
   8393         encap_data = msg.encap_data;
   8394         encap_data = _bcm_fp_oam_olp_l2_header_unpack(encap_data, 
   8395                 &olp_l2_header);
   8396         encap_data = shr_olp_tx_header_unpack(encap_data,
   8397                 &olp_oam_tx_header);
   8398          loss_p->int_pri = SOC_OLP_TX_PRI_GET(&olp_oam_tx_header);
   8399 
   8400         loss_p->pkt_pri =
   8401                  bcm_fp_oam_bhh_get_oam_exp_from_encap(h_data_p,
   8402                                                        msg.encap_data,
   8403                                                        msg.encap_length);
   8404         rv = BCM_E_NONE;
   8405     }
   8406 
   8407     _BCM_OAM_UNLOCK(oc);
   8408 
   8409     return (rv);
   8410 }
   8411 
   8412 /*
   8413  * Function:
   8414  *     _bcm_fp_oam_bhh_loss_delete
   8415  * Purpose:
   8416  *    Loss Measurement Delete for BHH endpoints
   8417  * Parameters:
   8418  *     unit - Device unit number
   8419  * Returns:
   8420  *     None
   8421  */
   8422 int
   8423 _bcm_fp_oam_bhh_loss_delete(int unit, bcm_oam_loss_t *loss_p)
   8424 {
   8425     _bcm_fp_oam_control_t *oc;
   8426     int rv = BCM_E_NONE;
   8427     _bhh_fp_oam_ep_data_t *h_data_p;
   8428     uint8 *buffer, *buffer_ptr;
   8429     uint16 buffer_len, reply_len;
   8430     int sess_id = 0;
   8431 
   8432     /* Get OAM Control Structure. */
   8433     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
   8434 
   8435     _BCM_OAM_LOCK(oc);
   8436     BCM_OAM_BHH_VALIDATE_EP(loss_p->id);
   8437 
   8438     sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(loss_p->id);
   8439     h_data_p = &oc->bhh_ep_data[sess_id];
   8440     if (!(h_data_p->in_use)) {
   8441         /* Endpoint not in use. */
   8442         LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM(unit %d) Error: "
   8443             "Endpoint EP=%d %s.\n"), unit, loss_p->id, bcm_errmsg(rv)));
   8444         _BCM_OAM_UNLOCK(oc);
   8445         return BCM_E_NOT_FOUND;
   8446     }
   8447 
   8448 
   8449     shr_bhh_msg_ctrl_loss_delete_t msg;
   8450 
   8451     /* Check endpoint status. */
   8452     rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id);
   8453     if ((BCM_E_EXISTS != rv)) {
   8454         /* Endpoint not in use. */
   8455         LOG_ERROR(BSL_LS_BCM_OAM,
   8456                 (BSL_META_U(unit,
   8457                             "OAM(unit %d) Error: Endpoint EP=%d %s.\n"),
   8458                  unit, loss_p->id, bcm_errmsg(rv)));
   8459         _BCM_OAM_UNLOCK(oc);
   8460         return (rv);
   8461     }
   8462 
   8463     h_data_p = &oc->bhh_ep_data[loss_p->id];
   8464 
   8465     msg.sess_id = sess_id;
   8466 
   8467     /* Pack control message data into DMA buffer */
   8468     buffer     = oc->bhh_dma_buffer;
   8469     buffer_ptr = shr_bhh_msg_ctrl_loss_delete_pack(buffer, &msg);
   8470     buffer_len = buffer_ptr - buffer;
   8471 
   8472     /* Send BHH Session Update message to uC */
   8473     rv = _bcm_fp_oam_msg_send_receive(unit,
   8474             MOS_MSG_CLASS_BHH, 
   8475             MOS_MSG_SUBCLASS_BHH_LOSS_MEASUREMENT_DELETE,
   8476             buffer_len, 0,
   8477             MOS_MSG_SUBCLASS_BHH_LOSS_MEASUREMENT_DELETE_REPLY,
   8478             &reply_len);
   8479 
   8480     if(BCM_SUCCESS(rv) && (reply_len != 0)) {
   8481         rv =  BCM_E_INTERNAL;
   8482     }
   8483 
   8484 
   8485     _BCM_OAM_UNLOCK(oc);
   8486 
   8487     return (rv);
   8488 }
   8489 
   8490 /*
   8491  * Function:
   8492  *     _bcm_fp_oam_bhh_delay_add
   8493  * Purpose:
   8494  *     Delay Measurement add for BHH endpoints.
   8495  * Parameters:
   8496  *     unit - Device unit number
   8497  * Returns:
   8498  *     None
   8499  */
   8500 int
   8501 _bcm_fp_oam_bhh_delay_add(int unit, bcm_oam_delay_t *delay_p)
   8502 {
   8503     _bcm_fp_oam_control_t *oc;
   8504     _bhh_fp_oam_ep_data_t *h_data_p;
   8505     int rv = BCM_E_NONE;
   8506     uint8 *buffer, *buffer_ptr, encap_type;
   8507     uint16 buffer_len, reply_len;
   8508     uint32 flags = 0;
   8509     int sess_id = 0, i = 0;
   8510     _bhh_oam_lm_dm_info_t counter_info;
   8511     bcm_module_t         module_id;
   8512     bcm_port_t           port_id;
   8513     bcm_trunk_t          trunk_id;
   8514     int                  local_id;
   8515 
   8516     /* Get OAM Control Structure. */
   8517     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
   8518 
   8519     _BCM_OAM_LOCK(oc);
   8520     BCM_OAM_BHH_VALIDATE_EP(delay_p->id);
   8521 
   8522     sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(delay_p->id);
   8523 
   8524     h_data_p = &oc->bhh_ep_data[sess_id];
   8525     if (!(h_data_p->in_use)) {
   8526         /* Endpoint not in use. */
   8527         LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM(unit %d) Error: "
   8528             "Endpoint EP=%d %s.\n"), unit, delay_p->id, bcm_errmsg(rv)));
   8529         _BCM_OAM_UNLOCK(oc);
   8530         return BCM_E_NOT_FOUND;
   8531     }
   8532     /*Validate LM period */
   8533     rv = _bcm_fp_oam_period_validate(delay_p->period);
   8534         if (BCM_FAILURE(rv)) {
   8535         LOG_ERROR(BSL_LS_BCM_OAM,
   8536                   (BSL_META_U(unit,
   8537                               "OAM(unit %d) Error: Invalid period : %d\n"),
   8538                    unit, delay_p->period));
   8539         _BCM_OAM_UNLOCK(oc);
   8540         return (rv);
   8541     }
   8542 
   8543     h_data_p->dm_tx_counter_size = delay_p->dm_tx_update_lm_counter_size;
   8544     sal_memset(&counter_info, 0, sizeof(counter_info));
   8545     counter_info.counter_size = delay_p->dm_tx_update_lm_counter_size;
   8546     for (i=0; i< BCM_OAM_LM_COUNTER_MAX; i++)
   8547     {
   8548         h_data_p->dm_tx_update_lm_counter_base_id[i] =
   8549         delay_p->dm_tx_update_lm_counter_base_id[i];
   8550         h_data_p->dm_tx_update_lm_counter_offset[i] =
   8551         delay_p->dm_tx_update_lm_counter_offset[i];
   8552         counter_info.counter_base_id[i] = 
   8553         delay_p->dm_tx_update_lm_counter_base_id[i];
   8554         counter_info.counter_offset[i] = 
   8555         delay_p->dm_tx_update_lm_counter_offset[i];
   8556         counter_info.counter_action[i] = bcmOamCounterActionIncrement;
   8557         counter_info.byte_count_offset[i] = 0;
   8558     }
   8559     counter_info.oam_replacement_offset = SHR_BHH_HEADER_LENGTH;
   8560 
   8561 
   8562     bhh_sdk_msg_ctrl_delay_add_t msg;       
   8563     sal_memset(&msg, 0, sizeof(msg));
   8564 
   8565     /* Check endpoint status. */
   8566     rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id);
   8567     if ((BCM_E_EXISTS != rv)) {
   8568         /* Endpoint not in use. */
   8569         LOG_ERROR(BSL_LS_BCM_OAM,
   8570                 (BSL_META_U(unit,
   8571                             "OAM(unit %d) Error: Endpoint EP=%d %s.\n"),
   8572                  unit, delay_p->id, bcm_errmsg(rv)));
   8573         _BCM_OAM_UNLOCK(oc);
   8574         return (rv);
   8575     }
   8576     /*
   8577      * Convert host space flags to uKernel space flags
   8578      */
   8579     if (delay_p->flags & BCM_OAM_DELAY_ONE_WAY) {
   8580         flags |= BCM_BHH_DM_ONE_WAY;
   8581     }
   8582 
   8583     if (delay_p->flags & BCM_OAM_DELAY_TX_ENABLE) {
   8584         flags |= BCM_BHH_DM_TX_ENABLE;
   8585     }
   8586 
   8587     sal_memset(&msg, 0, sizeof(msg));
   8588     msg.flags   = flags;
   8589     msg.sess_id = sess_id;
   8590 
   8591     if(delay_p->timestamp_format == bcmOAMTimestampFormatIEEE1588v1) {
   8592         msg.dm_format = BCM_BHH_DM_TYPE_PTP;
   8593         counter_info.ts_mode = BCM_PKT_TIMESTAMP_MODE_PTP;
   8594     } else {
   8595         msg.dm_format = BCM_BHH_DM_TYPE_NTP;
   8596         counter_info.ts_mode = BCM_PKT_TIMESTAMP_MODE_NTP;
   8597     }
   8598     /*
   8599      * Set period
   8600      */
   8601     msg.period  = delay_p->period;
   8602 
   8603     if (h_data_p->trunk_id == BCM_TRUNK_INVALID) {
   8604         rv = _bcm_esw_gport_resolve(unit,
   8605                 h_data_p->gport, &module_id, &port_id, &trunk_id, &local_id);
   8606     } else {
   8607         rv = _bcm_esw_gport_resolve(unit,
   8608                 h_data_p->resolved_trunk_gport, &module_id, &port_id, 
   8609                 &trunk_id, &local_id);
   8610         
   8611     }
   8612 
   8613     if (BCM_FAILURE(rv)) {
   8614         LOG_ERROR(BSL_LS_BCM_OAM,
   8615                 (BSL_META_U(unit,
   8616                             "BHH(unit %d) Error: Gport resolve - %s.\n"),
   8617                  unit, bcm_errmsg(rv)));
   8618         _BCM_OAM_UNLOCK(oc);
   8619         return (rv);
   8620     }
   8621 
   8622 
   8623     /*
   8624      * Set the BHH encapsulation data
   8625      *
   8626      * The function _bcm_fp_oam_bhh_encap_create() is called first
   8627      * since this sets some fields in 'hash_data' which are
   8628      * used in the message.
   8629      */
   8630     rv = _bcm_fp_oam_bhh_encap_create(unit,
   8631             module_id,
   8632             port_id, 
   8633             h_data_p,
   8634             msg.encap_data,
   8635             &encap_type,
   8636             &msg.encap_length,
   8637             &counter_info, delay_p->int_pri, delay_p->pkt_pri,
   8638             h_data_p->egr_label_ttl);
   8639     if(BCM_FAILURE(rv))
   8640     {
   8641         LOG_ERROR(BSL_LS_BCM_OAM,
   8642                 (BSL_META_U(unit,
   8643                             "BHH(unit %d) Error: Encap create failed "
   8644                             " - %s.\n"),
   8645                  unit, bcm_errmsg(rv)));
   8646         _BCM_OAM_UNLOCK(oc);
   8647         return (rv);
   8648     }
   8649     /* Pack control message data into DMA buffer */
   8650     buffer     = oc->bhh_dma_buffer;
   8651     buffer_ptr = bhh_sdk_msg_ctrl_delay_add_pack(buffer, &msg);
   8652     buffer_len = buffer_ptr - buffer;
   8653 
   8654     /* Send BHH Session Update message to uC */
   8655     rv = _bcm_fp_oam_msg_send_receive(unit,
   8656             MOS_MSG_CLASS_BHH, 
   8657             MOS_MSG_SUBCLASS_BHH_DELAY_MEASUREMENT_ADD,
   8658             buffer_len, 0,
   8659             MOS_MSG_SUBCLASS_BHH_DELAY_MEASUREMENT_ADD_REPLY,
   8660             &reply_len);
   8661 
   8662     delay_p->pm_id = sess_id;
   8663 
   8664     if(BCM_SUCCESS(rv) && (reply_len != 0)) { 
   8665         rv =  BCM_E_INTERNAL;
   8666     }
   8667 
   8668 
   8669     _BCM_OAM_UNLOCK(oc);
   8670     return (rv);
   8671 }
   8672 
   8673 /*
   8674  * Function:
   8675  *     _bcm_fp_oam_bhh_delay_get
   8676  * Purpose:
   8677  *     Delay Measurements get for BHH endpoints.
   8678  * Parameters:
   8679  *     unit - Device unit number
   8680  * Returns:
   8681  *     None
   8682  */
   8683 int
   8684 _bcm_fp_oam_bhh_delay_get(int unit, bcm_oam_delay_t *delay_p)
   8685 {
   8686     _bcm_fp_oam_control_t *oc;
   8687     int rv = BCM_E_NONE;
   8688     _bhh_fp_oam_ep_data_t *h_data_p;
   8689     uint8 *buffer, *buffer_ptr;
   8690     uint16 buffer_len, reply_len;
   8691     int sess_id = 0, i = 0;
   8692     bhh_sdk_msg_ctrl_delay_get_t msg;
   8693     uint8*  encap_data = NULL;
   8694     soc_olp_l2_hdr_t olp_l2_header;
   8695     soc_olp_tx_hdr_t olp_oam_tx_header;
   8696 
   8697     /* Get OAM Control Structure. */
   8698     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
   8699 
   8700     _BCM_OAM_LOCK(oc);
   8701     BCM_OAM_BHH_VALIDATE_EP(delay_p->id);
   8702 
   8703     sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(delay_p->id);
   8704 
   8705     h_data_p = &oc->bhh_ep_data[sess_id];
   8706     if (!(h_data_p->in_use)) {
   8707         /* Endpoint not in use. */
   8708         LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM(unit %d) Error: "
   8709             "Endpoint EP=%d %s.\n"), unit, delay_p->id, bcm_errmsg(rv)));
   8710         _BCM_OAM_UNLOCK(oc);
   8711         return BCM_E_NOT_FOUND;
   8712     }
   8713 
   8714     /* Check endpoint status. */
   8715     rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id);
   8716     if ((BCM_E_EXISTS != rv)) {
   8717         /* Endpoint not in use. */
   8718         LOG_ERROR(BSL_LS_BCM_OAM,
   8719                 (BSL_META_U(unit,
   8720                             "OAM(unit %d) Error: Endpoint EP=%d %s.\n"),
   8721                  unit, delay_p->id, bcm_errmsg(rv)));
   8722         _BCM_OAM_UNLOCK(oc);
   8723         return (rv);
   8724     }
   8725 
   8726     sal_memset(&msg, 0, sizeof(msg));
   8727     /* Send BHH Session Update message to uC */
   8728     rv = _bcm_fp_oam_msg_send_receive(unit,
   8729             MOS_MSG_CLASS_BHH, 
   8730             MOS_MSG_SUBCLASS_BHH_DELAY_MEASUREMENT_GET,
   8731             sess_id, 0,
   8732             MOS_MSG_SUBCLASS_BHH_DELAY_MEASUREMENT_GET_REPLY,
   8733             &reply_len);
   8734     if(BCM_FAILURE(rv)) {
   8735         LOG_ERROR(BSL_LS_BCM_OAM,
   8736                 (BSL_META_U(unit,
   8737                             "OAM(unit %d) Error: Endpoint EP=%d %s.\n"),
   8738                  unit, delay_p->id, bcm_errmsg(rv)));
   8739         _BCM_OAM_UNLOCK(oc);
   8740         return (rv);
   8741     }
   8742 
   8743     /* Pack control message data into DMA buffer */
   8744     buffer     = oc->bhh_dma_buffer;
   8745     buffer_ptr = bhh_sdk_msg_ctrl_delay_get_unpack(buffer, &msg);
   8746     buffer_len = buffer_ptr - buffer;
   8747 
   8748 
   8749     if (reply_len != buffer_len) {
   8750         rv =  BCM_E_INTERNAL;
   8751     } else {
   8752         /*
   8753          * Convert kernel space flags to host space flags
   8754          */
   8755         if (msg.flags & BCM_BHH_DM_ONE_WAY) {
   8756             delay_p->flags |= BCM_OAM_DELAY_ONE_WAY;
   8757         }
   8758 
   8759         if (msg.flags & BCM_BHH_DM_TX_ENABLE) {
   8760             delay_p->flags |= BCM_OAM_DELAY_TX_ENABLE;
   8761         }
   8762 
   8763         delay_p->period = msg.period;
   8764 
   8765         if(msg.dm_format == BCM_BHH_DM_TYPE_PTP)
   8766             delay_p->timestamp_format = bcmOAMTimestampFormatIEEE1588v1;
   8767         else
   8768             delay_p->timestamp_format = bcmOAMTimestampFormatNTP;
   8769 
   8770         rv = bcm_fp_oam_convert_ep_to_time_spec(&(delay_p->delay), 
   8771                 msg.delay_seconds, msg.delay_nanoseconds);
   8772         if(BCM_SUCCESS(rv)) {
   8773             rv = bcm_fp_oam_convert_ep_to_time_spec(&(delay_p->txf), 
   8774                     msg.txf_seconds, msg.txf_nanoseconds);
   8775         }
   8776         if(BCM_SUCCESS(rv)) {
   8777             rv = bcm_fp_oam_convert_ep_to_time_spec(&(delay_p->rxf), 
   8778                     msg.rxf_seconds, msg.rxf_nanoseconds);
   8779         }
   8780         if(BCM_SUCCESS(rv)) {
   8781             rv = bcm_fp_oam_convert_ep_to_time_spec(&(delay_p->txb), 
   8782                     msg.txb_seconds, msg.txb_nanoseconds);
   8783         }
   8784         if(BCM_SUCCESS(rv)) {
   8785             rv = bcm_fp_oam_convert_ep_to_time_spec(&(delay_p->rxb), 
   8786                     msg.rxb_seconds, msg.rxb_nanoseconds);
   8787         }
   8788         delay_p->rx_oam_packets = msg.rx_oam_packets;
   8789         delay_p->tx_oam_packets = msg.tx_oam_packets;
   8790         delay_p->int_pri = msg.int_pri;
   8791         delay_p->pkt_pri = msg.pkt_pri;
   8792         delay_p->pm_id = sess_id;
   8793         for (i=0; i< BCM_OAM_LM_COUNTER_MAX; i++)
   8794         {
   8795             delay_p->dm_tx_update_lm_counter_base_id[i] =
   8796                 h_data_p->dm_tx_update_lm_counter_base_id[i]; 
   8797             delay_p->dm_tx_update_lm_counter_offset[i] =
   8798                 h_data_p->dm_tx_update_lm_counter_offset[i]; 
   8799         }
   8800         delay_p->dm_tx_update_lm_counter_size = h_data_p->dm_tx_counter_size;
   8801         encap_data = msg.encap_data;
   8802         encap_data = _bcm_fp_oam_olp_l2_header_unpack(encap_data, 
   8803                 &olp_l2_header);
   8804         encap_data = shr_olp_tx_header_unpack(encap_data,
   8805                 &olp_oam_tx_header);
   8806         delay_p->int_pri = SOC_OLP_TX_PRI_GET (&olp_oam_tx_header);
   8807         delay_p->pkt_pri =
   8808                  bcm_fp_oam_bhh_get_oam_exp_from_encap(h_data_p,
   8809                                                        msg.encap_data,
   8810                                                        msg.encap_length);
   8811     }
   8812 
   8813 
   8814     _BCM_OAM_UNLOCK(oc);
   8815 
   8816     return (rv);
   8817 }
   8818 
   8819 /*
   8820  * Function:
   8821  *     _bcm_fp_oam_bhh_delay_delete
   8822  * Purpose:
   8823  *     Delay Measurement Delete 
   8824  * Parameters:
   8825  *     unit - Device unit number
   8826  * Returns:
   8827  *     None
   8828  */
   8829 int
   8830 _bcm_fp_oam_bhh_delay_delete(int unit, bcm_oam_delay_t *delay_p)
   8831 {
   8832     _bcm_fp_oam_control_t *oc;
   8833     int rv = BCM_E_NONE;
   8834     _bhh_fp_oam_ep_data_t *h_data_p;
   8835     uint8 *buffer, *buffer_ptr;
   8836     uint16 buffer_len, reply_len;
   8837     int sess_id = 0;
   8838 
   8839     /* Get OAM Control Structure. */
   8840     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
   8841 
   8842     _BCM_OAM_LOCK(oc);
   8843 
   8844     BCM_OAM_BHH_VALIDATE_EP(delay_p->id);
   8845 
   8846     sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(delay_p->id);
   8847     h_data_p = &oc->bhh_ep_data[sess_id];
   8848 
   8849     if (!(h_data_p->in_use)) {
   8850         /* Endpoint not in use. */
   8851         LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM(unit %d) Error: "
   8852             "Endpoint EP=%d %s.\n"), unit, delay_p->id, bcm_errmsg(rv)));
   8853         _BCM_OAM_UNLOCK(oc);
   8854         return BCM_E_NOT_FOUND;
   8855     }
   8856 
   8857 
   8858     shr_bhh_msg_ctrl_delay_delete_t msg;
   8859 
   8860     /* Check endpoint status. */
   8861     rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id);
   8862     if ((BCM_E_EXISTS != rv)) {
   8863         /* Endpoint not in use. */
   8864         LOG_ERROR(BSL_LS_BCM_OAM,
   8865                 (BSL_META_U(unit,
   8866                             "OAM(unit %d) Error: Endpoint EP=%d %s.\n"),
   8867                  unit, delay_p->id, bcm_errmsg(rv)));
   8868         _BCM_OAM_UNLOCK(oc);
   8869         return (rv);
   8870     }
   8871 
   8872     msg.sess_id = sess_id;
   8873 
   8874     /* Pack control message data into DMA buffer */
   8875     buffer     = oc->bhh_dma_buffer;
   8876     buffer_ptr = shr_bhh_msg_ctrl_delay_delete_pack(buffer, &msg);
   8877     buffer_len = buffer_ptr - buffer;
   8878 
   8879     /* Send BHH Session Update message to uC */
   8880     rv = _bcm_fp_oam_msg_send_receive(unit,
   8881             MOS_MSG_CLASS_BHH, 
   8882             MOS_MSG_SUBCLASS_BHH_DELAY_MEASUREMENT_DELETE,
   8883             buffer_len, 0,
   8884             MOS_MSG_SUBCLASS_BHH_DELAY_MEASUREMENT_DELETE_REPLY,
   8885             &reply_len);
   8886 
   8887     if(BCM_SUCCESS(rv) && (reply_len != 0)) {
   8888         rv =  BCM_E_INTERNAL;
   8889     }
   8890 
   8891 
   8892     _BCM_OAM_UNLOCK(oc);
   8893 
   8894     return (rv);
   8895 }
   8896 
   8897 /*
   8898  * Function:
   8899  *      _bcm_fp_oam_csf_add
   8900  * Purpose:
   8901  *      Start CSF PDU transmission
   8902  * Parameters:
   8903  *      unit    - (IN)    Unit number.
   8904  *      csf_ptr - (INOUT) CSF object
   8905  * Returns:
   8906  *      BCM_E_XXX
   8907  * Notes:
   8908  */
   8909 int _bcm_fp_oam_csf_add(int unit, bcm_oam_csf_t *csf_p)
   8910 {
   8911     _bcm_fp_oam_control_t      *oc;
   8912     _bhh_fp_oam_ep_data_t      *h_data_p;
   8913     bhh_sdk_msg_ctrl_csf_add_t  msg;
   8914     uint8                      *buffer, *buffer_ptr;
   8915     uint16                      buffer_len, reply_len;
   8916     _bhh_oam_lm_dm_info_t       counter_info;
   8917     bcm_module_t                module_id;
   8918     bcm_port_t                  port_id;
   8919     bcm_trunk_t                 trunk_id;
   8920     int                         local_id;
   8921     uint8                       encap_type;
   8922     int                         sess_id = 0;
   8923     int                         i;
   8924     int                         rv = BCM_E_NONE;
   8925 
   8926     /* Get OAM Control Structure. */
   8927     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
   8928     _BCM_OAM_LOCK(oc);
   8929 
   8930     if (oc->ukernel_not_ready) {
   8931         _BCM_OAM_UNLOCK(oc);
   8932         return BCM_E_INIT;
   8933     }
   8934 
   8935     BCM_OAM_BHH_VALIDATE_EP(csf_p->id);
   8936     sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(csf_p->id);
   8937 
   8938     /* Check endpoint status. */
   8939     rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id);
   8940     if ((BCM_E_EXISTS != rv)) {
   8941         /* Endpoint not in use. */
   8942         LOG_ERROR(BSL_LS_BCM_OAM,
   8943                   (BSL_META_U(unit,
   8944                               "OAM(unit %d) Error: Endpoint EP=%d %s.\n"),
   8945                    unit, csf_p->id, bcm_errmsg(rv)));
   8946         _BCM_OAM_UNLOCK(oc);
   8947         return (rv);
   8948     }
   8949 
   8950     if ((csf_p->period != BCM_OAM_ENDPOINT_CCM_PERIOD_1S) &&
   8951         (csf_p->period != BCM_OAM_ENDPOINT_CCM_PERIOD_1M)) {
   8952         /* Only 1S and 1M are supported */
   8953         _BCM_OAM_UNLOCK(oc);
   8954         return BCM_E_PARAM;
   8955     }
   8956 
   8957     h_data_p = &oc->bhh_ep_data[sess_id];
   8958     /*
   8959      * Only BHH is supported
   8960      */
   8961     if (!BHH_EP_TYPE(h_data_p)) {
   8962         _BCM_OAM_UNLOCK(oc);
   8963         return BCM_E_UNAVAIL;
   8964     }
   8965 
   8966     sal_memset(&counter_info, 0, sizeof(counter_info));
   8967     counter_info.counter_size     = csf_p->csf_tx_update_lm_counter_size;
   8968     h_data_p->csf_tx_counter_size = csf_p->csf_tx_update_lm_counter_size;
   8969     for (i = 0; i < BCM_OAM_LM_COUNTER_MAX; i++) {
   8970         h_data_p->csf_tx_update_lm_counter_base_id[i] =
   8971                                       csf_p->csf_tx_update_lm_counter_base_id[i];
   8972         h_data_p->csf_tx_update_lm_counter_offset[i] =
   8973                                       csf_p->csf_tx_update_lm_counter_offset[i];
   8974 
   8975         counter_info.counter_base_id[i] =
   8976                                       csf_p->csf_tx_update_lm_counter_base_id[i];
   8977         counter_info.counter_offset[i] =
   8978                                       csf_p->csf_tx_update_lm_counter_offset[i];
   8979         counter_info.counter_action[i] = bcmOamCounterActionIncrement;
   8980     }
   8981     counter_info.ts_mode = BCM_PKT_TIMESTAMP_MODE_NONE;
   8982 
   8983     sal_memset(&msg, 0, sizeof(msg));
   8984     msg.sess_id = sess_id;
   8985     msg.int_pri = csf_p->int_pri;
   8986     msg.pkt_pri = csf_p->pkt_pri;
   8987 
   8988     switch(csf_p->type) {
   8989         case BCM_OAM_CSF_LOS:
   8990             msg.type = SHR_CSF_TYPE_LOS;
   8991             break;
   8992 
   8993         case BCM_OAM_CSF_FDI:
   8994             msg.type = SHR_CSF_TYPE_FDI;
   8995             break;
   8996 
   8997         case BCM_OAM_CSF_RDI:
   8998             msg.type = SHR_CSF_TYPE_RDI;
   8999             break;
   9000 
   9001         case BCM_OAM_CSF_DCI:
   9002             msg.type = SHR_CSF_TYPE_DCI;
   9003             break;
   9004 
   9005         default:
   9006             _BCM_OAM_UNLOCK(oc);
   9007             return BCM_E_PARAM;
   9008     }
   9009 
   9010     /*
   9011      * Set period
   9012      */
   9013     msg.period  = csf_p->period;
   9014 
   9015     if (h_data_p->trunk_id == BCM_TRUNK_INVALID) {
   9016         rv = _bcm_esw_gport_resolve(unit, h_data_p->gport,
   9017                                     &module_id, &port_id,
   9018                                     &trunk_id, &local_id);
   9019     } else {
   9020         rv = _bcm_esw_gport_resolve(unit,
   9021                                     h_data_p->resolved_trunk_gport,
   9022                                     &module_id, &port_id,
   9023                                     &trunk_id, &local_id);
   9024     }
   9025     if (rv != BCM_E_NONE) {
   9026         _BCM_OAM_UNLOCK(oc);
   9027         return rv;
   9028     }
   9029 
   9030     /*
   9031      * Set the BHH encapsulation data
   9032  */
   9033     rv = _bcm_fp_oam_bhh_encap_create(unit, module_id, port_id, h_data_p,
   9034                                        msg.encap_data, &encap_type,
   9035                                        &msg.encap_length, &counter_info,
   9036                                        csf_p->int_pri, csf_p->pkt_pri,
   9037                                        h_data_p->egr_label_ttl);
   9038     if(BCM_FAILURE(rv)) {
   9039         LOG_ERROR(BSL_LS_BCM_OAM,
   9040                   (BSL_META_U(unit,
   9041                               "BHH(unit %d) Error: Encap create failed "
   9042                               " - %s.\n"),
   9043                    unit, bcm_errmsg(rv)));
   9044         _BCM_OAM_UNLOCK(oc);
   9045         return rv;
   9046     }
   9047 
   9048     /* Pack control message data into DMA buffer */
   9049     buffer     = oc->bhh_dma_buffer;
   9050     buffer_ptr = bhh_sdk_msg_ctrl_csf_add_pack(buffer, &msg);
   9051     buffer_len = buffer_ptr - buffer;
   9052 
   9053     /* Send BHH Session Update message to uC */
   9054     rv = _bcm_fp_oam_msg_send_receive(unit,
   9055                                       MOS_MSG_CLASS_BHH,
   9056                                       MOS_MSG_SUBCLASS_BHH_CSF_ADD,
   9057                                       buffer_len, 0,
   9058                                       MOS_MSG_SUBCLASS_BHH_CSF_ADD_REPLY,
   9059                                       &reply_len);
   9060 
   9061     if(BCM_SUCCESS(rv) && (reply_len != 0)) {
   9062         rv =  BCM_E_INTERNAL;
   9063     }
   9064 
   9065     _BCM_OAM_UNLOCK(oc);
   9066     return rv;
   9067 }
   9068 
   9069 /*
   9070  * Function:
   9071  *      _bcm_fp_oam_csf_get
   9072  * Purpose:
   9073  *      Get CSF info
   9074  * Parameters:
   9075  *      unit    - (IN)  Unit number.
   9076  *      csf_ptr - (OUT) CSF object
   9077  * Returns:
   9078  *      BCM_E_XXX
   9079  * Notes:
   9080  */
   9081 int _bcm_fp_oam_csf_get(int unit, bcm_oam_csf_t *csf_p)
   9082 {
   9083     _bcm_fp_oam_control_t       *oc;
   9084     bhh_sdk_msg_ctrl_csf_get_t   msg;
   9085     _bhh_fp_oam_ep_data_t       *h_data_p;
   9086     uint8                       *buffer, *buffer_ptr;
   9087     uint16                       buffer_len, reply_len;
   9088     uint8*                       encap_data = NULL;
   9089     soc_olp_l2_hdr_t             olp_l2_header;
   9090     soc_olp_tx_hdr_t             olp_oam_tx_header;
   9091     int                          sess_id = 0;
   9092     int                          i;
   9093     int                          rv = BCM_E_NONE;
   9094 
   9095 
   9096     /* Get OAM Control Structure. */
   9097     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
   9098     _BCM_OAM_LOCK(oc);
   9099 
   9100     if (oc->ukernel_not_ready) {
   9101         _BCM_OAM_UNLOCK(oc);
   9102         return BCM_E_INIT;
   9103     }
   9104 
   9105     BCM_OAM_BHH_VALIDATE_EP(csf_p->id);
   9106     sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(csf_p->id);
   9107 
   9108     /* Check endpoint status. */
   9109     rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id);
   9110     if ((BCM_E_EXISTS != rv)) {
   9111         /* Endpoint not in use. */
   9112         LOG_ERROR(BSL_LS_BCM_OAM,
   9113                   (BSL_META_U(unit,
   9114                               "OAM(unit %d) Error: Endpoint EP=%d %s.\n"),
   9115                    unit, csf_p->id, bcm_errmsg(rv)));
   9116         _BCM_OAM_UNLOCK(oc);
   9117         return (rv);
   9118     }
   9119 
   9120     h_data_p = &oc->bhh_ep_data[sess_id];
   9121 
   9122     if (!BHH_EP_TYPE(h_data_p)) {
   9123         _BCM_OAM_UNLOCK(oc);
   9124         return BCM_E_UNAVAIL;
   9125     }
   9126 
   9127 
   9128     sal_memset(&msg, 0, sizeof(msg));
   9129 
   9130     /* Send BHH Session Update message to uC */
   9131     rv = _bcm_fp_oam_msg_send_receive(unit,
   9132                                       MOS_MSG_CLASS_BHH,
   9133                                       MOS_MSG_SUBCLASS_BHH_CSF_GET,
   9134                                       sess_id, 0,
   9135                                       MOS_MSG_SUBCLASS_BHH_CSF_GET_REPLY,
   9136                                       &reply_len);
   9137     if(BCM_FAILURE(rv)) {
   9138         LOG_ERROR(BSL_LS_BCM_OAM,
   9139                   (BSL_META_U(unit,
   9140                               "OAM(unit %d) Error: Endpoint EP=%d %s.\n"),
   9141                    unit, csf_p->id, bcm_errmsg(rv)));
   9142         _BCM_OAM_UNLOCK(oc);
   9143         return (rv);
   9144     }
   9145 
   9146     /* Pack control message data into DMA buffer */
   9147     buffer     = oc->bhh_dma_buffer;
   9148     buffer_ptr = bhh_sdk_msg_ctrl_csf_get_unpack(buffer, &msg);
   9149     buffer_len = buffer_ptr - buffer;
   9150 
   9151 
   9152     if (reply_len != buffer_len) {
   9153         _BCM_OAM_UNLOCK(oc);
   9154         return BCM_E_INTERNAL;
   9155     }
   9156 
   9157     switch(msg.type) {
   9158         case SHR_CSF_TYPE_LOS:
   9159             csf_p->type = BCM_OAM_CSF_LOS;
   9160             break;
   9161 
   9162         case SHR_CSF_TYPE_FDI:
   9163             csf_p->type = BCM_OAM_CSF_FDI;
   9164             break;
   9165 
   9166         case SHR_CSF_TYPE_RDI:
   9167             csf_p->type = BCM_OAM_CSF_RDI;
   9168             break;
   9169 
   9170         case SHR_CSF_TYPE_DCI:
   9171             csf_p->type = BCM_OAM_CSF_DCI;
   9172             break;
   9173 
   9174         default:
   9175             _BCM_OAM_UNLOCK(oc);
   9176             return BCM_E_INTERNAL;
   9177     }
   9178 
   9179     csf_p->period = msg.period;
   9180     csf_p->flags  = msg.flags;
   9181 
   9182     for (i = 0; i< BCM_OAM_LM_COUNTER_MAX; i++) {
   9183         csf_p->csf_tx_update_lm_counter_base_id[i] =
   9184                                   h_data_p->csf_tx_update_lm_counter_base_id[i];
   9185         csf_p->csf_tx_update_lm_counter_offset[i] =
   9186                                   h_data_p->csf_tx_update_lm_counter_offset[i];
   9187     }
   9188     csf_p->csf_tx_update_lm_counter_size = h_data_p->csf_tx_counter_size;
   9189 
   9190     encap_data = msg.encap_data;
   9191     encap_data = _bcm_fp_oam_olp_l2_header_unpack(encap_data,
   9192                                                   &olp_l2_header);
   9193     encap_data = shr_olp_tx_header_unpack(encap_data,
   9194                                           &olp_oam_tx_header);
   9195     csf_p->int_pri = SOC_OLP_TX_PRI_GET (&olp_oam_tx_header);
   9196     csf_p->pkt_pri = bcm_fp_oam_bhh_get_oam_exp_from_encap(h_data_p,
   9197                                                            msg.encap_data,
   9198                                                            msg.encap_length);
   9199     _BCM_OAM_UNLOCK(oc);
   9200     return BCM_E_NONE;
   9201 
   9202 }
   9203 
   9204 /*
   9205  * Function:
   9206  *      _bcm_fp_oam_csf_delete
   9207  * Purpose:
   9208  *      Stop CSF PDU transmission
   9209  * Parameters:
   9210  *      unit    - (IN  Unit number.
   9211  *      csf_ptr - (IN) CSF object
   9212  * Returns:
   9213  *      BCM_E_XXX
   9214  * Notes:
   9215  */
   9216 int _bcm_fp_oam_csf_delete(int unit, bcm_oam_csf_t *csf_p)
   9217 {
   9218     _bcm_fp_oam_control_t   *oc;
   9219     _bhh_fp_oam_ep_data_t   *h_data_p;
   9220     uint16                   reply_len;
   9221     int                      sess_id;
   9222     int                      rv = BCM_E_NONE;
   9223 
   9224     /* Get OAM Control Structure. */
   9225     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
   9226     _BCM_OAM_LOCK(oc);
   9227 
   9228     if (oc->ukernel_not_ready) {
   9229         _BCM_OAM_UNLOCK(oc);
   9230         return BCM_E_INIT;
   9231     }
   9232 
   9233     BCM_OAM_BHH_VALIDATE_EP(csf_p->id);
   9234     sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(csf_p->id);
   9235 
   9236     /* Check endpoint status. */
   9237     rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id);
   9238     if ((BCM_E_EXISTS != rv)) {
   9239         /* Endpoint not in use. */
   9240         LOG_ERROR(BSL_LS_BCM_OAM,
   9241                   (BSL_META_U(unit,
   9242                               "OAM(unit %d) Error: Endpoint EP=%d %s.\n"),
   9243                    unit, csf_p->id, bcm_errmsg(rv)));
   9244         _BCM_OAM_UNLOCK(oc);
   9245         return (rv);
   9246     }
   9247 
   9248     h_data_p = &oc->bhh_ep_data[sess_id];
   9249 
   9250     if (!BHH_EP_TYPE(h_data_p)) {
   9251         _BCM_OAM_UNLOCK(oc);
   9252         return BCM_E_UNAVAIL;
   9253     }
   9254 
   9255     /* Send BHH Session Update message to uC */
   9256     rv = _bcm_fp_oam_msg_send_receive(unit,
   9257                                       MOS_MSG_CLASS_BHH,
   9258                                       MOS_MSG_SUBCLASS_BHH_CSF_DELETE,
   9259                                       sess_id, 0,
   9260                                       MOS_MSG_SUBCLASS_BHH_CSF_DELETE_REPLY,
   9261                                       &reply_len);
   9262 
   9263     _BCM_OAM_UNLOCK(oc);
   9264     return (rv);
   9265 }
   9266 
   9267 /*
   9268  * Function:
   9269  *     _bcm_fp_oam_bhh_group_traverse
   9270  * Purpose:
   9271  *     Traverse the entire set of BHH groups, calling a specified
   9272  *     callback for each one
   9273  * Parameters:
   9274  *     unit  - (IN) BCM device number
   9275  *     cb        - (IN) Pointer to call back function.
   9276  *     user_data - (IN) Pointer to user supplied data.
   9277  * Returns:
   9278  *     BCM_E_XXX
   9279  */
   9280 int
   9281 _bcm_fp_oam_bhh_group_traverse(int unit, bcm_oam_group_traverse_cb cb,
   9282                            void *user_data)
   9283 {
   9284     _bcm_fp_oam_control_t    *oc;        /* OAM control structure pointer. */
   9285     bcm_oam_group_info_t  group_info; /* Group information to be set.   */
   9286     bcm_oam_group_t       grp_idx;    /* MA Group index.                */
   9287     int                   rv;         /* Operation return status.       */
   9288 
   9289     if (NULL == cb) {
   9290         return (BCM_E_PARAM);
   9291     }
   9292 
   9293     /* Get device OAM control structure handle. */
   9294     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
   9295 
   9296     if (soc_feature(unit, soc_feature_bhh)) { 
   9297         for (grp_idx = 0; grp_idx < oc->bhh_endpoint_count; grp_idx++) {
   9298 
   9299             /* Check if the group is in use. */
   9300             if (BCM_E_EXISTS
   9301                    == shr_idxres_list_elem_state(oc->bhh_group_pool, grp_idx)) {
   9302 
   9303                 /* Initialize the group information structure. */
   9304                 bcm_oam_group_info_t_init(&group_info);
   9305 
   9306                 group_info.id = BCM_OAM_BHH_GET_SDK_GROUP(grp_idx);
   9307                 /* Retrieve group information and set in group_info structure.*/
   9308                 rv = _bcm_fp_oam_bhh_group_get(unit, &group_info);
   9309                 if (BCM_FAILURE(rv)) {
   9310                     LOG_ERROR(BSL_LS_BCM_OAM,
   9311                             (BSL_META_U(unit,
   9312                                         "OAM(unit %d) Error: "
   9313                                         "_bcm_fp_oam_bhh_group_get "
   9314                                         "(GID=%d) - %s.\n"), unit, grp_idx, 
   9315                                         bcm_errmsg(rv)));
   9316                     return (rv);
   9317                 }
   9318                 /* Call the user call back routine with group information. */
   9319                 rv = cb(unit, &group_info, user_data);
   9320                 if (BCM_FAILURE(rv)) {
   9321                     LOG_ERROR(BSL_LS_BCM_OAM,
   9322                             (BSL_META_U(unit,
   9323                                         "OAM(unit %d) Error: User call back " 
   9324                                         "routine (GID=%d) - %s.\n"), unit, 
   9325                                         grp_idx, bcm_errmsg(rv)));
   9326                     return (rv);
   9327                 }
   9328             }
   9329         }
   9330     }
   9331 
   9332     return BCM_E_NONE;
   9333 }
   9334 
   9335 /*
   9336  * Function:
   9337  *     _bcm_fp_oam_bhh_group_destroy_all
   9338  * Purpose:
   9339  *     Traverse the entire set of BHH groups and deletes all of them
   9340  * Parameters:
   9341  *     unit  - (IN) BCM device number
   9342  * Returns:
   9343  *     BCM_E_XXX
   9344  */
   9345 int
   9346 _bcm_fp_oam_bhh_group_destroy_all(int unit)
   9347 {
   9348     _bcm_fp_oam_control_t    *oc;        /* OAM control structure pointer. */
   9349     bcm_oam_group_t       grp_idx, group = 0;/* MA Group index.            */
   9350     int                   rv;         /* Operation return status.       */
   9351 
   9352     /* Get device OAM control structure handle. */
   9353     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
   9354 
   9355     for (grp_idx = 0; grp_idx < oc->bhh_endpoint_count; grp_idx++) {
   9356 
   9357         /* Check if the group is in use. */
   9358         if (BCM_E_EXISTS
   9359                 == shr_idxres_list_elem_state(oc->bhh_group_pool, grp_idx)) {
   9360 
   9361             group = BCM_OAM_BHH_GET_SDK_GROUP(grp_idx);
   9362 
   9363             rv = _bcm_fp_oam_bhh_group_destroy(unit, group);
   9364             if (BCM_FAILURE(rv)) {
   9365                 LOG_ERROR(BSL_LS_BCM_OAM,
   9366                         (BSL_META_U(unit,
   9367                                     "OAM(unit %d) Error: "
   9368                                     "_bcm_fp_oam_bhh_group_destroy "
   9369                                     "(GID=%d) - %s.\n"), unit, group, 
   9370                          bcm_errmsg(rv)));
   9371                 return (rv);
   9372             }
   9373         }
   9374     }
   9375 
   9376     return BCM_E_NONE;
   9377 }
   9378 #endif /*(INCLUDE_BHH) */
   9379 
   9380 /*******************************************************************************/
   9381 /* CCM Embedded App supporting functions Start */
   9382 /*******************************************************************************/
   9383 #if defined (INCLUDE_CCM)
   9384 
   9385 #define _BCM_OAM_GLP_MODULE_ID_GET(_glp_) (0xFF & ((_glp_) >> 7))
   9386 #define _BCM_OAM_GLP_PORT_GET(_glp_)      (0x7F & (_glp_))
   9387 
   9388 /*
   9389  * Macro:
   9390  *     _BCM_OAM_EP_INDEX_VALIDATE
   9391  * Purpose:
   9392  *     Validate OAM Endpoint ID value.
   9393  * Parameters:
   9394  *     _ep_ - Endpoint ID value.
   9395  */
   9396 #define _BCM_OAM_EP_INDEX_VALIDATE(_ep_)                       \
   9397     do {                                                       \
   9398         if ((_ep_) < 0 || (_ep_) >= oc->mep_count) {            \
   9399             LOG_ERROR(BSL_LS_BCM_OAM,                          \
   9400                       (BSL_META("OAM(unit %d) Error: Invalid Endpoint ID" \
   9401                        " = %d.\n"), unit, _ep_));              \
   9402             return (BCM_E_PARAM);                              \
   9403         }                                                      \
   9404     } while (0);
   9405 
   9406 /*
   9407  * Macro:
   9408  *     _BCM_FP_OAM_GROUP_INDEX_VALIDATE
   9409  * Purpose:
   9410  *     Validate OAM Group ID value.
   9411  * Parameters:
   9412  *     _group_ - Group ID value.
   9413  */
   9414 #define _BCM_FP_OAM_GROUP_INDEX_VALIDATE(_group_)                   \
   9415     do {                                                            \
   9416         if ((_group_) < 0 || (_group_) >= oc->group_count) {        \
   9417             LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META("OAM Error: "       \
   9418               "Invalid Group ID = %d.\n"), _group_));               \
   9419             return (BCM_E_PARAM);                                   \
   9420         }                                                           \
   9421     } while (0);
   9422 
   9423 
   9424 /*
   9425  * Function:
   9426  *     _bcm_fp_oam_group_set_msg_send
   9427  * Purpose:
   9428  *     Send Group Create/Update Message to UKERNEL
   9429  * Parameters:
   9430  *     unit          - (IN) BCM device number
   9431  *     ep_data       - (IN) Pointer to endpoint information.
   9432  *     msg_flags     - (IN) Msg control flags
   9433  * Returns:
   9434  *      BCM_E_XXX
   9435  */
   9436 static int
   9437 _bcm_fp_oam_group_set_msg_send(int unit, _bcm_fp_oam_group_data_t *grp_p,
   9438                               uint32 msg_flags, uint16 *r_msg_len)
   9439 {
   9440     shr_ccm_msg_ctrl_group_data_t group_msg;
   9441     _bcm_fp_oam_control_t *oc = NULL;
   9442     uint8 *dma_buffer1 = NULL;  /* DMA buffer */
   9443     uint8 *dma_buffer2 = NULL;  /* DMA buffer ptr after pack */
   9444     uint16 s_msg_len = 0;       /* Send Message length */
   9445     int rv = 0;
   9446 
   9447     /* Get OAM Control Structure. */
   9448     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
   9449 
   9450     dma_buffer1 = oc->dma_buffer;
   9451 
   9452     /* Validate input parameter. */
   9453     if (NULL == grp_p) {
   9454         return (BCM_E_INTERNAL);
   9455     }
   9456 
   9457     /* Clear meo_msg structure */
   9458     sal_memset(&group_msg, 0, sizeof(group_msg));
   9459     group_msg.flags = msg_flags;
   9460 
   9461     /* Fill Mep data and Send MEP Create message to UKENREL */
   9462     sal_memcpy(&(group_msg.group_data), &(grp_p->group_data),
   9463                sizeof(ccm_group_data_t));
   9464 
   9465     /* Pack Mep data to buffer */
   9466     dma_buffer1 = oc->dma_buffer;
   9467     dma_buffer2 = shr_ccm_msg_ctrl_group_set_pack(dma_buffer1, &group_msg);
   9468     s_msg_len = dma_buffer2 - dma_buffer1;
   9469     rv = _bcm_fp_oam_msg_send_receive(unit, MOS_MSG_CLASS_CCM,
   9470             MOS_MSG_SUBCLASS_CCM_GROUP_SET, s_msg_len, 0,
   9471             MOS_MSG_SUBCLASS_CCM_GROUP_SET_REPLY, r_msg_len);
   9472     if (BCM_FAILURE(rv)) {
   9473         LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: "
   9474                   "Group Set Msg returned error %s.\n"), bcm_errmsg(rv)));
   9475     }
   9476     return rv;
   9477 }
   9478 
   9479 
   9480 /*
   9481  * Function:
   9482  *     bcm_fp_oam_ccm_group_create
   9483  * Purpose:
   9484  *     Create or replace an OAM group object
   9485  * Parameters:
   9486  *     unit       - (IN) BCM device number
   9487  *     group_info - (IN/OUT) Pointer to an OAM group information.
   9488  * Returns:
   9489  *     BCM_E_XXX
   9490  */
   9491 int
   9492 bcm_fp_oam_ccm_group_create(int unit, bcm_oam_group_info_t *group_info)
   9493 {
   9494     _bcm_fp_oam_control_t *oc = NULL;           /* OAM control structure */
   9495     _bcm_fp_oam_group_data_t *oam_group = NULL; /* OAM Group being created */
   9496     uint32 msg_flags = 0;                       /* Group Msg flags */
   9497     uint16 r_len = 0;                           /* Received Msg length */
   9498     int rv = 0;                                 /* return value */
   9499 
   9500     /* Validate input parameter. */
   9501     if (NULL == group_info) {
   9502         return (BCM_E_PARAM);
   9503     }
   9504 
   9505     /* Get OAM control structure handle. */
   9506     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
   9507 
   9508     /* Validate group id. */
   9509     if (group_info->flags & BCM_OAM_GROUP_WITH_ID) {
   9510         _BCM_FP_OAM_GROUP_INDEX_VALIDATE(group_info->id);
   9511     }
   9512 
   9513     /*
   9514      * If MA group create is called with replace flag bit set.
   9515      *  - Check and return error if a group does not exist with the ID.
   9516      */
   9517     if (group_info->flags & BCM_OAM_GROUP_REPLACE) {
   9518         if (group_info->flags & BCM_OAM_GROUP_WITH_ID) {
   9519 
   9520             /* Search the list with the MA Group ID value. */
   9521             rv = shr_idxres_list_elem_state(oc->group_pool, group_info->id);
   9522             if (BCM_E_EXISTS != rv) {
   9523                 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit,
   9524                           "OAM Error: Group does not exist.\n")));
   9525                 return (BCM_E_PARAM);
   9526             }
   9527         } else {
   9528             LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit,
   9529                       "OAM Error: Replace command needs a valid Group ID.\n")));
   9530             return (BCM_E_PARAM);
   9531         }
   9532     } else if (group_info->flags & BCM_OAM_GROUP_WITH_ID) {
   9533         /*
   9534          * If MA group create is called with ID flag bit set.
   9535          *  - Check and return error if the ID is already in use.
   9536          */
   9537         rv = shr_idxres_list_reserve(oc->group_pool, group_info->id,
   9538                                      group_info->id);
   9539         if (BCM_FAILURE(rv)) {
   9540             return ((rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv);
   9541         }
   9542     } else {
   9543         /* Reserve the next available group index. */
   9544          rv = shr_idxres_list_alloc(oc->group_pool,
   9545                                     (shr_idxres_element_t *) &group_info->id);
   9546         if (BCM_FAILURE(rv)) {
   9547             LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit,
   9548                       "OAM Error: Group allocation (GID=%d) %s\n"),
   9549                       group_info->id, bcm_errmsg(rv)));
   9550             return (rv);
   9551         }
   9552     }
   9553 
   9554     /* Get this group memory to store group information. */
   9555     oam_group = &(oc->group_data[group_info->id]);
   9556 
   9557     if (!(group_info->flags & BCM_OAM_GROUP_REPLACE)) {
   9558 
   9559         /* Store the group name. */
   9560         sal_memcpy(oam_group->group_data.name, group_info->name,
   9561                    BCM_OAM_GROUP_NAME_LENGTH);
   9562 
   9563         /* Store Lowest Alarm Priority */
   9564         oam_group->group_data.lowest_alarm_priority = group_info->lowest_alarm_priority;
   9565 
   9566         /* Initialize RMEP head to NULL.*/
   9567         sal_memset(oam_group->group_data.rmep_bitmap, 0,
   9568                                     sizeof(oam_group->group_data.rmep_bitmap));
   9569 
   9570         /* Check if software RDI flag bit needs to be set in hardware. */
   9571         oam_group->group_data.flags |=
   9572             ((group_info->flags & BCM_OAM_GROUP_REMOTE_DEFECT_TX) ?
   9573               _FP_OAM_GROUP_SW_RDI_FLAG : 0);
   9574 
   9575         /* Set LMEP as not configured */
   9576         oam_group->group_data.lmep_id = _FP_OAM_INVALID_LMEP_ID;
   9577 
   9578         oam_group->group_data.group_id = group_info->id;
   9579 
   9580         /* Send Group Create message to uKernel */
   9581         rv = _bcm_fp_oam_group_set_msg_send(unit, oam_group, msg_flags, &r_len);
   9582          if (BCM_FAILURE(rv)) {
   9583             LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: "
   9584                 "Group create Msg failed, id:%d - %s"), group_info->id,
   9585                 bcm_errmsg(rv)));
   9586         } else {
   9587             oam_group->in_use = 1;
   9588         }
   9589 
   9590     } else {
   9591         /* Only lowest alarm prio and S/w RDI bit can be replaced */
   9592         if ((oam_group->group_data.flags & _FP_OAM_GROUP_SW_RDI_FLAG) !=
   9593             (group_info->flags & BCM_OAM_GROUP_REMOTE_DEFECT_TX)) {
   9594 
   9595             if (group_info->flags & BCM_OAM_GROUP_REMOTE_DEFECT_TX) {
   9596                 oam_group->group_data.flags |= _FP_OAM_GROUP_SW_RDI_FLAG;
   9597             } else {
   9598                 oam_group->group_data.flags &= ~(_FP_OAM_GROUP_SW_RDI_FLAG);
   9599             }
   9600             msg_flags |= _GRP_REPLACE;
   9601             msg_flags |= _GRP_REPLACE_SW_RDI;
   9602         }
   9603 
   9604         if (oam_group->group_data.lowest_alarm_priority !=
   9605             group_info->lowest_alarm_priority) {
   9606 
   9607             oam_group->group_data.lowest_alarm_priority =
   9608                 group_info->lowest_alarm_priority;
   9609             msg_flags |= _GRP_REPLACE;
   9610             msg_flags |= _GRP_REPLACE_LOWEST_ALARM_PRIO;
   9611         }
   9612 
   9613         /* Send Group Create message to uKernel */
   9614         rv = _bcm_fp_oam_group_set_msg_send(unit, oam_group, msg_flags, &r_len);
   9615          if (BCM_FAILURE(rv)) {
   9616             LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: "
   9617                 "Group create Msg failed, id:%d - %s"), group_info->id,
   9618                 bcm_errmsg(rv)));
   9619         }
   9620     }
   9621 
   9622     return rv;
   9623 }
   9624 
   9625 /*
   9626  * Function:
   9627  *     bcm_fp_oam_ccm_group_get
   9628  * Purpose:
   9629  *     Delete an OAM group object. All OAM endpoints associated with the
   9630  *     group will also be destroyed.
   9631  * Parameters:
   9632  *     unit       - (IN) BCM device number
   9633  *     group_info - (IN/OUT) Pointer to an OAM group Id.
   9634  * Returns:
   9635  *     BCM_E_XXX
   9636  */
   9637 int
   9638 bcm_fp_oam_ccm_group_get(int unit, bcm_oam_group_info_t *group_info) {
   9639 
   9640     _bcm_fp_oam_control_t *oc = NULL;           /* OAM control structure */
   9641     _bcm_fp_oam_group_data_t *group_p;          /* Handle to S/w Group Data */
   9642     int rv = 0;                                 /* Return Value */
   9643     uint16 reply_len;
   9644     uint8 *dma_buffer1 = NULL;
   9645     uint8 *dma_buffer2 = NULL;
   9646     shr_ccm_msg_ctrl_group_data_t group_msg;
   9647 
   9648     /* Get OAM control structure handle. */
   9649     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
   9650 
   9651     /* Validate Group Index */
   9652     _BCM_FP_OAM_GROUP_INDEX_VALIDATE(group_info->id);
   9653 
   9654     /* Get Handle to Local DB */
   9655     group_p = &(oc->group_data[group_info->id]);
   9656     if (!(group_p->in_use)) {
   9657         return BCM_E_NOT_FOUND;
   9658     }
   9659 
   9660     rv = _bcm_fp_oam_msg_send_receive(unit, MOS_MSG_CLASS_CCM,
   9661             MOS_MSG_SUBCLASS_CCM_GROUP_GET_FAULTS_ONLY, group_info->id, 0,
   9662             MOS_MSG_SUBCLASS_CCM_GROUP_GET_REPLY, &reply_len);
   9663 
   9664     /* UnPack control message data into DMA buffer */
   9665     dma_buffer1 = oc->dma_buffer;
   9666     dma_buffer2 = shr_ccm_msg_ctrl_group_get_unpack(dma_buffer1, &group_msg);
   9667 
   9668     if (reply_len != dma_buffer2 - dma_buffer1) {
   9669         rv = BCM_E_INTERNAL;
   9670         LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: "
   9671             "Group get Msg lenght check failed, id:%d.\n"), group_info->id));
   9672         return (rv);
   9673     }
   9674     group_info->faults = group_msg.group_data.faults;
   9675     group_info->persistent_faults = group_msg.group_data.persistent_faults;
   9676 
   9677     sal_memcpy(group_info->name, group_p->group_data.name, _FP_OAM_MAID_LEN);
   9678     group_info->lowest_alarm_priority =
   9679         group_p->group_data.lowest_alarm_priority;
   9680 
   9681     if (group_p->group_data.flags & _FP_OAM_GROUP_SW_RDI_FLAG) {
   9682         group_info->flags |= BCM_OAM_GROUP_REMOTE_DEFECT_TX;
   9683     }
   9684 
   9685     return rv;
   9686 }
   9687 
   9688 int
   9689 _bcm_fp_oam_ccm_group_traverse(int unit, bcm_oam_group_traverse_cb cb,
   9690                            void *user_data)
   9691 {
   9692     _bcm_fp_oam_control_t    *oc = NULL;        /* OAM control structure pointer. */
   9693     bcm_oam_group_info_t     group_info;
   9694     bcm_oam_group_t          grp_idx;    /* MA Group index.                */
   9695     int                      rv;         /* Operation return status.       */
   9696     _bcm_fp_oam_group_data_t *group_p;
   9697 
   9698     if (NULL == cb) {
   9699         return (BCM_E_PARAM);
   9700     }
   9701 
   9702     /* Get device OAM control structure handle. */
   9703     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
   9704 
   9705         for (grp_idx = 0; grp_idx < oc->group_count; grp_idx++) {
   9706             group_p = &(oc->group_data[grp_idx]);
   9707             if (group_p->in_use) {
   9708                 group_info.id = grp_idx;
   9709                 rv = bcm_fp_oam_ccm_group_get(unit, &group_info);
   9710                 if (BCM_FAILURE(rv)) {
   9711                     LOG_ERROR(BSL_LS_BCM_OAM,
   9712                              (BSL_META_U(unit,
   9713                                          "OAM(unit %d) Error: "
   9714                                          "_bcm_fp_oam_ccm_group_get "
   9715                                          "(GID=%d) - %s.\n"), unit, grp_idx,
   9716                                          bcm_errmsg(rv)));
   9717                     return (rv);
   9718                 }
   9719                 /* Call the user call back routine with group information. */
   9720                 rv = cb(unit, &group_info, user_data);
   9721                 if (BCM_FAILURE(rv)) {
   9722                     LOG_ERROR(BSL_LS_BCM_OAM,
   9723                              (BSL_META_U(unit,
   9724                                         "OAM(unit %d) Error: User call back "
   9725                                         "routine (GID=%d) - %s.\n"), unit,
   9726                                         grp_idx, bcm_errmsg(rv)));
   9727                     return (rv);
   9728                 }
   9729             }
   9730         }
   9731     return BCM_E_NONE;
   9732 }
   9733 
   9734 /*
   9735  * Function:
   9736  *     bcm_fp_oam_ccm_group_destroy
   9737  * Purpose:
   9738  *     Delete an OAM group object. All OAM endpoints associated with the
   9739  *     group will also be destroyed.
   9740  * Parameters:
   9741  *     unit       - (IN) BCM device number
   9742  *     group_info - (IN/OUT) Pointer to an OAM group Id.
   9743  * Returns:
   9744  *     BCM_E_XXX
   9745  */
   9746 int
   9747 bcm_fp_oam_ccm_group_destroy(int unit, bcm_oam_group_t group_id)
   9748 {
   9749     _bcm_fp_oam_control_t *oc = NULL;           /* OAM control structure */
   9750     _bcm_fp_oam_group_data_t *group_p;          /* Handle to S/w Group Data */
   9751     int rv = 0;                                 /* Return Value */
   9752     uint16 r_len;                               /* Msg reply lenght */
   9753     int i = 0;
   9754 
   9755     /* Get OAM control structure handle. */
   9756     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
   9757 
   9758     /* Validate Group Index */
   9759     _BCM_FP_OAM_GROUP_INDEX_VALIDATE(group_id);
   9760 
   9761     /* Get Handle to Local DB */
   9762     group_p = &(oc->group_data[group_id]);
   9763     if (!(group_p->in_use)) {
   9764         return BCM_E_NOT_FOUND;
   9765     }
   9766 
   9767     rv = _bcm_fp_oam_msg_send_receive(unit, MOS_MSG_CLASS_CCM,
   9768             MOS_MSG_SUBCLASS_CCM_GROUP_DELETE, group_id, 0,
   9769             MOS_MSG_SUBCLASS_CCM_GROUP_DELETE_REPLY, &r_len);
   9770 
   9771     if (BCM_FAILURE(rv)) {
   9772         LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: "
   9773             "Group Del Msg returned error %s.\n"), bcm_errmsg(rv)));
   9774         rv = BCM_E_INTERNAL;
   9775         return rv;
   9776     }
   9777 
   9778     /* Clean up Local db, including LMEPs and RMEPs */
   9779     if (group_p->group_data.lmep_id != _FP_OAM_INVALID_LMEP_ID) {
   9780         sal_memset(&(oc->mep_data[group_p->group_data.lmep_id]), 0,
   9781                    sizeof(_bcm_fp_oam_mep_data_t));
   9782 
   9783         /* Free the LMEP index */
   9784         rv = shr_idxres_list_free(oc->mep_pool, group_p->group_data.lmep_id);
   9785         if (BCM_FAILURE(rv)) {
   9786             LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: "
   9787                       "LMEP index Free failed EP:%d %s.\n"),
   9788                       group_p->group_data.lmep_id, bcm_errmsg(rv)));
   9789             return (rv);
   9790         }
   9791     }
   9792 
   9793     for (i=0; i<_CCM_MEP_COUNT; i++) {
   9794         if (_GET_BIT_FLD(group_p->group_data.rmep_bitmap, i) ) {
   9795             sal_memset(&(oc->mep_data[i]), 0, sizeof(_bcm_fp_oam_mep_data_t));
   9796 
   9797             /* Free the RMEP index */
   9798             rv = shr_idxres_list_free(oc->mep_pool, i);
   9799             if (BCM_FAILURE(rv)) {
   9800                 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: "
   9801                           "RMEP index Free failed EP:%d %s.\n"), i,
   9802                           bcm_errmsg(rv)));
   9803                 return (rv);
   9804             }
   9805         }
   9806     }
   9807 
   9808     /* Free the Group index */
   9809     rv = shr_idxres_list_free(oc->group_pool, group_id);
   9810 
   9811     if (BCM_FAILURE(rv)) {
   9812         LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: "
   9813                   "Group index Free failed EP:%d %s.\n"), group_id,
   9814                   bcm_errmsg(rv)));
   9815         return (rv);
   9816     }
   9817 
   9818     sal_memset(group_p, 0, sizeof(_bcm_fp_oam_group_data_t));
   9819     group_p->group_data.lmep_id = _FP_OAM_INVALID_LMEP_ID;
   9820 
   9821     return rv;
   9822 }
   9823 
   9824 
   9825 /*
   9826  * Function:
   9827  *     _bcm_fp_oam_ep_hash_key_construct
   9828  * Purpose:
   9829  *     Construct hash table key for a given endpoint information.
   9830  * Parameters:
   9831  *     unit    - (IN) BCM device number
   9832  *     oc      - (IN) Pointer to OAM control structure.
   9833  *     ep_info - (IN) Pointer to endpoint information structure.
   9834  *     key     - (IN/OUT) Pointer to hash key buffer.
   9835  * Retruns:
   9836  *     None
   9837  */
   9838 STATIC void
   9839 _bcm_fp_oam_ep_hash_key_construct(int unit, _bcm_fp_oam_control_t *oc,
   9840         bcm_oam_endpoint_info_t *ep_info, _bcm_fp_oam_hash_key_t *key)
   9841 {
   9842     uint8   *loc = *key;
   9843     uint8   direction = 0;
   9844     uint8   isLocal = 1;
   9845 
   9846     sal_memset(key, 0, sizeof(_bcm_fp_oam_hash_key_t));
   9847 
   9848     if (NULL != ep_info) {
   9849 
   9850         if (ep_info->flags & BCM_OAM_ENDPOINT_UP_FACING) {
   9851             direction = 1;
   9852         }
   9853         if (ep_info->flags & BCM_OAM_ENDPOINT_REMOTE) {
   9854             isLocal = 0;
   9855         }
   9856         _BCM_OAM_KEY_PACK(loc, &direction, sizeof(direction));
   9857         _BCM_OAM_KEY_PACK(loc, &isLocal, sizeof(isLocal));
   9858         _BCM_OAM_KEY_PACK(loc, &ep_info->group, sizeof(ep_info->group));
   9859         _BCM_OAM_KEY_PACK(loc, &ep_info->name, sizeof(ep_info->name));
   9860         _BCM_OAM_KEY_PACK(loc, &ep_info->gport, sizeof(ep_info->gport));
   9861         _BCM_OAM_KEY_PACK(loc, &ep_info->level, sizeof(ep_info->level));
   9862         _BCM_OAM_KEY_PACK(loc, &ep_info->vlan, sizeof(ep_info->vlan));
   9863         _BCM_OAM_KEY_PACK(loc, &ep_info->inner_vlan,
   9864                           sizeof(ep_info->inner_vlan));
   9865     }
   9866 
   9867     /* End address should not exceed size of _bcm_oam_hash_key_t. */
   9868     assert ((int) (loc - *key) <= sizeof(_bcm_oam_hash_key_t));
   9869 }
   9870 
   9871 
   9872 /*
   9873  * Function:
   9874  *     _bcm_fp_oam_endpoint_params_validate
   9875  * Purpose:
   9876  *     Validate an endpoint parameters.
   9877  * Parameters:
   9878  *     unit      - (IN) BCM device number
   9879  *     oc        - (IN) Pointer to OAM control structure.
   9880  *     hash_key  - (IN) Pointer to endpoint hash key value.
   9881  *     ep_info_p - (IN) Pointer to endpoint information.
   9882  * Retruns:
   9883  *     BCM_E_XXX
   9884  */
   9885 STATIC int
   9886 _bcm_fp_oam_endpoint_params_validate(int unit, _bcm_fp_oam_control_t *oc,
   9887         _bcm_fp_oam_hash_key_t *hash_key,  bcm_oam_endpoint_info_t *ep_info_p)
   9888 {
   9889     int rv = 0;
   9890     _bcm_fp_oam_group_data_t *group_p = NULL;
   9891 
   9892     LOG_DEBUG(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Info: "
   9893               "_bcm_fp_oam_endpoint_params_validate.\n")));
   9894 
   9895     /* Endpoint must be 802.1ag/Ethernet OAM type. */
   9896     if ((bcmOAMEndpointTypeEthernet != ep_info_p->type))
   9897     {
   9898         /* Other OAM types are not supported, return error. */
   9899         return BCM_E_UNAVAIL;
   9900     }
   9901 
   9902     /* Supported MDL level is 0 - 7. */
   9903     if ((ep_info_p->level < 0) || (ep_info_p->level > _FP_OAM_MAX_MDL)) {
   9904         LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: "
   9905           "EP Level should be in the range(0-%d).\n"), _FP_OAM_MAX_MDL ));
   9906         return (BCM_E_PARAM);
   9907      }
   9908 
   9909     /* Supported MEPID Name range is 1 - 8191, Skipping range check for MIP and MPLS LM/DM */
   9910     if (((ep_info_p->name < _FP_OAM_EP_NAME_MIN)
   9911         || (ep_info_p->name > _FP_OAM_EP_NAME_MAX)) &&
   9912         !(ep_info_p->flags & BCM_OAM_ENDPOINT_INTERMEDIATE)
   9913 #if defined(INCLUDE_MPLS_LM_DM)
   9914         && (!_MPLS_LM_DM_ENDPOINT_TYPE(ep_info_p->type))) {
   9915 #else
   9916        ) {
   9917 #endif
   9918        LOG_ERROR(BSL_LS_BCM_OAM,
   9919                  (BSL_META_U(unit,
   9920                              "OAM Error: MEP Name should be in the range(%d-%d).\n"),
   9921                   _FP_OAM_EP_NAME_MIN, _FP_OAM_EP_NAME_MAX));
   9922        return (BCM_E_PARAM);
   9923     }
   9924 
   9925     /* For replace operation, endpoint ID is required. */
   9926     if ((ep_info_p->flags & BCM_OAM_ENDPOINT_REPLACE)
   9927         && !(ep_info_p->flags & BCM_OAM_ENDPOINT_WITH_ID)) {
   9928 
   9929         return (BCM_E_PARAM);
   9930     }
   9931 
   9932     /* If it is a Port + CVlan based MEP or Section Port + CVlan
   9933      * based MEP and the CVlan (inner_vlan) is 0, return E_PARAM
   9934      */
   9935     if ((0 == ep_info_p->inner_vlan) &&
   9936         (ep_info_p->flags & BCM_OAM_ENDPOINT_MATCH_INNER_VLAN)) {
   9937         return (BCM_E_PARAM);
   9938     }
   9939 
   9940     /* If it is a Port + S + CVlan based MEP or Section Port + S + CVlan
   9941      * based MEP and one of SVlan(vlan) or CVlan (inner_vlan) is 0,
   9942      * return E_PARAM
   9943      */
   9944     if (((0 == ep_info_p->inner_vlan) || (0 == ep_info_p->vlan)) &&
   9945         ((ep_info_p->flags & BCM_OAM_ENDPOINT_MATCH_OUTER_AND_INNER_VLAN))) {
   9946         return (BCM_E_PARAM);
   9947     }
   9948 
   9949     /* Validate endpoint index value. */
   9950     if (ep_info_p->flags & BCM_OAM_ENDPOINT_WITH_ID) {
   9951         _BCM_OAM_EP_INDEX_VALIDATE(ep_info_p->id);
   9952     }
   9953 
   9954     /* MIP's are not created with non-zero ccm period */
   9955     if ((ep_info_p->flags & BCM_OAM_ENDPOINT_INTERMEDIATE) &&
   9956         (ep_info_p->ccm_period != BCM_OAM_ENDPOINT_CCM_PERIOD_DISABLED)) {
   9957          return (BCM_E_PARAM);
   9958     }
   9959 
   9960     /* Validate endpoint group id. */
   9961     _BCM_FP_OAM_GROUP_INDEX_VALIDATE(ep_info_p->group);
   9962 
   9963     rv = shr_idxres_list_elem_state(oc->group_pool, ep_info_p->group);
   9964     if (BCM_E_EXISTS != rv) {
   9965         LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: "
   9966                   "Group (GID:%d) does not exist.\n"), ep_info_p->group));
   9967         return (BCM_E_PARAM);
   9968     }
   9969 
   9970     /* Only One LMEP should be configured per group */
   9971     group_p = &(oc->group_data[ep_info_p->group]);
   9972     if (!(ep_info_p->flags & BCM_OAM_ENDPOINT_REMOTE)) {
   9973 
   9974         if ((group_p->group_data.lmep_id != _FP_OAM_INVALID_LMEP_ID) &&
   9975              !(ep_info_p->flags & BCM_OAM_ENDPOINT_REPLACE)) {
   9976             LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: "
   9977               "LMEP already existst for the group\n")));
   9978             return (rv);
   9979         }
   9980     }
   9981 
   9982 #if 0
   9983     
   9984     rv = shr_htb_find(oc->ma_mep_htbl, *hash_key,
   9985                       (shr_htb_data_t *)&h_stored_data, 0);
   9986 
   9987     if (BCM_SUCCESS(rv) && !(ep_info_p->flags & BCM_OAM_ENDPOINT_REPLACE)) {
   9988         LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: %s\n"),
   9989                   bcm_errmsg(BCM_E_EXISTS)));
   9990 
   9991         /* Endpoint must not be in use except for Replace operation. */
   9992         return (BCM_E_EXISTS);
   9993     } else {
   9994         /* Cannot replace any Key params for an endpoint */
   9995         if ((ep_info_p->flags & BCM_OAM_ENDPOINT_REPLACE) && !(BCM_SUCCESS(rv))) {
   9996             LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: Endpoint "
   9997                 "ID=%d, invalid params for replace operation or Endpoint "
   9998                 "doesn't exists\n"), ep_info_p->id));
   9999         }
  10000     }
  10001 #endif
  10002     return (BCM_E_NONE);
  10003 }
  10004 
  10005 
  10006 /*
  10007  * Function:
  10008  *     _bcm_fp_oam_get_ctr_info_from_stat_id
  10009  * Purpose:
  10010  *     Get OLP Formatted Counter Id from Stat Id
  10011  * Parameters:
  10012  *     unit          - (IN) BCM device number
  10013  *     stat_id       - (IN) Stat group Id.
  10014  *     offset        - (IN) Offset from Base
  10015  *     counter_id    - (OUT) OLP Formatted counter value
  10016  * Returns:
  10017  *      void
  10018  */
  10019 STATIC void
  10020 _bcm_fp_oam_get_ctr_info_from_stat_id(int unit, uint32 stat_id, uint8 offset,
  10021                                                            uint32 *counter_id)
  10022 {
  10023     bcm_stat_group_mode_t stat_group;
  10024     bcm_stat_object_t stat_object;
  10025     uint32 stat_mode;
  10026     uint32 stat_pool_number;
  10027     uint32 stat_base_idx;
  10028 
  10029     _bcm_esw_stat_get_counter_id_info(unit, stat_id,
  10030       &stat_group, &stat_object, &stat_mode, &stat_pool_number, &stat_base_idx);
  10031 
  10032     *counter_id = ( ((stat_base_idx & _FP_OAM_OLP_CTR_WIDTH) + offset) |
  10033                     ((stat_pool_number & _FP_OAM_OLP_CTR_POOL_WIDTH) <<
  10034                      _FP_OAM_OLP_CTR_WIDTH) );
  10035 
  10036 }
  10037 
  10038 
  10039 /*
  10040  * Function:
  10041  *     _bcm_fp_oam_olp_header_pack
  10042  * Purpose:
  10043  *     Pack OLP Header into buffer.
  10044  * Parameters:
  10045  *     buffer     - (IN/OUT) Buffer to Pack OLP Header
  10046  *     mep_data   - (IN)     Pointer to MEP data.
  10047  * Retruns:
  10048  *     BCM_E_XX
  10049  */
  10050 STATIC int
  10051 _bcm_fp_oam_olp_header_pack(int unit, uint8 *buffer, ccm_mep_data_t *mep_data)
  10052 {
  10053 
  10054     soc_olp_l2_hdr_t olp_l2_hdr;
  10055     soc_olp_tx_hdr_t olp_oam_header;
  10056     int rv = BCM_E_NONE;
  10057     uint32 counter_id;
  10058     bcm_module_t my_modid = 0;
  10059     bcm_gport_t  cpu_dglp;
  10060 
  10061     BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_modid));
  10062     BCM_IF_ERROR_RETURN(_bcm_esw_glp_construct(unit, BCM_TRUNK_INVALID, my_modid,
  10063                                                CMIC_PORT(unit), &cpu_dglp));
  10064     /* Get OLP L2 Header for CPU port */
  10065     sal_memset(&olp_l2_hdr, 0, sizeof(olp_l2_hdr));
  10066     rv = _bcm_olp_l2_hdr_get(unit, cpu_dglp, 0, &olp_l2_hdr);
  10067     if (BCM_FAILURE(rv)) {
  10068         LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: "
  10069                   "OLP Header get failed.\n")));
  10070         return (rv);
  10071     }
  10072 
  10073     /* OLP OAM Header */
  10074     sal_memset(&olp_oam_header, 0, sizeof(olp_oam_header));
  10075     /* Set Port number */
  10076     SOC_OLP_TX_PORT(&olp_oam_header) =
  10077         _BCM_OAM_GLP_PORT_GET(mep_data->dglp);
  10078     SOC_OLP_TX_MODID(&olp_oam_header) =
  10079         _BCM_OAM_GLP_MODULE_ID_GET(mep_data->dglp);
  10080 
  10081     if (mep_data->flags & _FP_OAM_DIRECTION_UP) {
  10082         SOC_OLP_TX_HDR_STYPE_GET(&olp_oam_header) = 1;
  10083     }
  10084 
  10085     if (0 < mep_data->num_ctrs) {
  10086         _bcm_fp_oam_get_ctr_info_from_stat_id(unit, mep_data->flex_stat_id[0],
  10087             mep_data->counter_offset[0], &counter_id);
  10088         SOC_OLP_TX_CTR1_ID(&olp_oam_header) = counter_id;
  10089         SOC_OLP_TX_CTR1_LOCATION(&olp_oam_header) = _FP_OAM_OLP_CTR_LOC_EP;
  10090         SOC_OLP_TX_CTR1_ACTION(&olp_oam_header) = _FP_OAM_OLP_CTR_ACTN_INC;
  10091     }
  10092     if (1 < mep_data->num_ctrs) {
  10093         _bcm_fp_oam_get_ctr_info_from_stat_id(unit, mep_data->flex_stat_id[1],
  10094             mep_data->counter_offset[1], &counter_id);
  10095         SOC_OLP_TX_CTR2_ID_SET(&olp_oam_header, counter_id);
  10096         SOC_OLP_TX_CTR2_LOCATION(&olp_oam_header) = _FP_OAM_OLP_CTR_LOC_EP;
  10097         SOC_OLP_TX_CTR2_ACTION(&olp_oam_header) = _FP_OAM_OLP_CTR_ACTN_INC;
  10098     }
  10099 
  10100     /* Now that we have both L2 and OAM OLP Headers, pack them */
  10101     buffer = _bcm_fp_oam_olp_l2_header_pack(buffer, &olp_l2_hdr);
  10102     buffer = shr_olp_tx_header_pack(buffer, &olp_oam_header);
  10103 
  10104     return (rv);
  10105 }
  10106 
  10107 
  10108 /*
  10109  * Function:
  10110  *     _bcm_fp_oam_l2_encap_pack
  10111  * Purpose:
  10112  *     Pack OLP Header into buffer.
  10113  * Parameters:
  10114  *     buffer     - (IN/OUT) Buffer to Pack L2 Encap
  10115  *     mep_data   - (IN)     Pointer to MEP data.
  10116  * Retruns:
  10117  *     BCM_E_XX
  10118  */
  10119 STATIC uint8*
  10120 _bcm_fp_oam_l2_encap_pack(int unit, uint8 *buffer, ccm_mep_data_t *mep_data)
  10121 {
  10122     uint32 vlan_tag = 0;
  10123     uint16 cfm_ether_type = _CCM_ETHER_TYPE;
  10124     int i;
  10125     /* Pack DA */
  10126     for (i=0; i<6; i++) {
  10127         _SHR_PACK_U8(buffer, mep_data->da[i]);
  10128     }
  10129     /* Pack SA */
  10130     for (i=0; i<6; i++) {
  10131         _SHR_PACK_U8(buffer, mep_data->sa[i]);
  10132     }
  10133     /* Pack Outer vlan */
  10134     if (mep_data->vlan) {
  10135         vlan_tag = 0;
  10136         vlan_tag = (mep_data->tpid << 16) |
  10137                    ((mep_data->pkt_pri & 0x7) << 13) |
  10138                    (mep_data->vlan & 0x0FFF);
  10139         _SHR_PACK_U32(buffer, vlan_tag);
  10140     }
  10141     /* Pack Inner vlan */
  10142     if (mep_data->inner_vlan) {
  10143         vlan_tag = 0;
  10144         vlan_tag = (mep_data->inner_tpid << 16) |
  10145                    ((mep_data->inner_vlan_pri & 0x7) << 13) |
  10146                    (mep_data->inner_vlan & 0x0FFF);
  10147         _SHR_PACK_U32(buffer, vlan_tag);
  10148     }
  10149     /* Pack EtherType */
  10150     _SHR_PACK_U16(buffer, cfm_ether_type);
  10151     return buffer;
  10152 }
  10153 
  10154 
  10155 /*
  10156  * Function:
  10157  *     _bcm_fp_oam_mep_set_msg_send
  10158  * Purpose:
  10159  *     Send Mep Create/Update Message to UKERNEL
  10160  * Parameters:
  10161  *     unit          - (IN) BCM device number
  10162  *     ep_data       - (IN) Pointer to endpoint information.
  10163  *     uint32        - (IN) Msg Control flags
  10164  * Returns:
  10165  *      BCM_E_XXX
  10166  */
  10167 static int
  10168 _bcm_fp_oam_mep_set_msg_send(int unit, _bcm_fp_oam_mep_data_t *ep_data,
  10169                             uint32 msg_flags, uint16 *r_msg_len)
  10170 {
  10171     shr_ccm_msg_ctrl_mep_data_t mep_msg;
  10172     _bcm_fp_oam_control_t *oc = NULL;
  10173     uint8 *dma_buffer1 = NULL;  /* DMA buffer */
  10174     uint8 *dma_buffer2 = NULL;  /* DMA buffer ptr after pack */
  10175     uint16 s_msg_len = 0;       /* Send Message length */
  10176     int rv = 0;
  10177 
  10178     /* Get OAM Control Structure. */
  10179     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
  10180 
  10181     dma_buffer1 = oc->dma_buffer;
  10182 
  10183     /* Validate input parameter. */
  10184     if (NULL == ep_data) {
  10185         return (BCM_E_INTERNAL);
  10186     }
  10187 
  10188     /* Clear mep_msg structure */
  10189     sal_memset(&mep_msg, 0, sizeof(mep_msg));
  10190     mep_msg.flags = msg_flags;
  10191 
  10192     if (msg_flags & _MEP_L2_ENCAP_RECREATE) {
  10193         dma_buffer1 = _bcm_fp_oam_l2_encap_pack(unit, mep_msg.L2_encap,
  10194                                                 &(ep_data->mep_data));
  10195         mep_msg.l2_encap_len = dma_buffer1 - mep_msg.L2_encap;
  10196     }
  10197 
  10198     if (msg_flags & _MEP_OLP_RECREATE) {
  10199         rv = _bcm_fp_oam_olp_header_pack(unit, mep_msg.OLP_Tx_Hdr, 
  10200                                          &(ep_data->mep_data));
  10201         if (BCM_FAILURE(rv)) {
  10202             LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: "
  10203                       "OLP Header Pack failed.\n")));
  10204             return (rv);
  10205         }
  10206     }
  10207 
  10208     /* Fill Mep data and Send MEP Create message to UKENREL */
  10209     sal_memcpy(&(mep_msg.mep_data), &(ep_data->mep_data),
  10210                sizeof(ccm_mep_data_t));
  10211 
  10212     /* Pack Mep data to buffer */
  10213     dma_buffer1 = oc->dma_buffer;
  10214     dma_buffer2 = shr_ccm_msg_ctrl_mep_set_pack(dma_buffer1, &mep_msg);
  10215     s_msg_len = dma_buffer2 - dma_buffer1;
  10216     rv = _bcm_fp_oam_msg_send_receive(unit, MOS_MSG_CLASS_CCM,
  10217             MOS_MSG_SUBCLASS_CCM_MEP_SET, s_msg_len, 0,
  10218             MOS_MSG_SUBCLASS_CCM_MEP_SET_REPLY, r_msg_len);
  10219 
  10220     if (BCM_FAILURE(rv)) {
  10221         LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: "
  10222             "MEP Create Msg returned error %s.\n"), bcm_errmsg(rv)));
  10223         rv = BCM_E_INTERNAL;
  10224     }
  10225     return (rv);
  10226 }
  10227 
  10228 
  10229 /*
  10230  * Function:
  10231  *     bcm_fp_oam_ccm_endpoint_create
  10232  * Purpose:
  10233  *     Create or replace a CCM OAM endpoint object
  10234  * Parameters:
  10235  *     unit          - (IN) BCM device number
  10236  *     endpoint_info - (IN/OUT) Pointer to endpoint information buffer.
  10237  * Returns:
  10238  *      BCM_E_XXX
  10239  */
  10240 int
  10241 bcm_fp_oam_ccm_endpoint_create(int unit, bcm_oam_endpoint_info_t *endpoint_info)
  10242 {
  10243     _bcm_fp_oam_control_t *oc = NULL;
  10244     _bcm_fp_oam_hash_key_t hash_key;
  10245     _bcm_fp_oam_mep_data_t *ep_data;
  10246     uint32 mep_index;
  10247     int src_glp;
  10248     int dst_glp;
  10249     bcm_gport_t dgpp;
  10250     bcm_trunk_t trunk_id = BCM_TRUNK_INVALID;
  10251     ccm_group_data_t *grp_data_ptr = NULL;
  10252     uint32  msg_flags = 0;
  10253     uint16  r_len = 0; /* Msg response lenght */
  10254     int rv = 0;
  10255     bcm_trunk_member_t   trunk_member;
  10256     int i;
  10257 
  10258     /* Validate input parameter. */
  10259     if (NULL == endpoint_info) {
  10260         return (BCM_E_PARAM);
  10261     }
  10262     /* Get OAM Control Structure. */
  10263     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
  10264 
  10265     /* Calculate the hash key for given enpoint input parameters. */
  10266     _bcm_fp_oam_ep_hash_key_construct(unit, oc, endpoint_info, &hash_key);
  10267 
  10268     /* Validate endpoint input parameters. */
  10269     rv = _bcm_fp_oam_endpoint_params_validate(unit, oc, &hash_key,
  10270                                               endpoint_info);
  10271     if (BCM_FAILURE(rv)) {
  10272         LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: Parameter "
  10273             "Validation failed %s.\n"), bcm_errmsg(rv)));
  10274         return (rv);
  10275     }
  10276 
  10277     rv = _bcm_fp_oam_endpoint_gport_resolve(unit, endpoint_info,
  10278                                             &src_glp, &dst_glp, &dgpp,
  10279                                             &trunk_id, &trunk_member);
  10280     if (BCM_FAILURE(rv)) {
  10281         LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: Gport Resolve "
  10282             "Failed %s.\n"), bcm_errmsg(rv)));
  10283         return (rv);
  10284     }
  10285 
  10286     /* Now that EP passed all the validation checks, create the endpoint */
  10287     if (!(endpoint_info->flags & BCM_OAM_ENDPOINT_REPLACE)) {
  10288 
  10289         if (trunk_id != BCM_TRUNK_INVALID) {
  10290             rv = _bcm_fp_oam_trunk_ports_update_trunk_id(unit, trunk_id);
  10291             if (BCM_FAILURE(rv)) {
  10292                 /* Dont return just for this error */
  10293                 LOG_WARN(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: "
  10294                                 "Trunk map update failed EP:%d %s.\n"), endpoint_info->id,
  10295                             bcm_errmsg(rv)));
  10296             }       
  10297         } 
  10298 
  10299         if (endpoint_info->flags & BCM_OAM_ENDPOINT_WITH_ID) {
  10300             /* Reserve the Id passed by the user */
  10301             mep_index = endpoint_info->id;
  10302             rv = shr_idxres_list_reserve(oc->mep_pool, mep_index, mep_index);
  10303 
  10304         } else {
  10305             /* Allocate the next Id from the pool */
  10306             rv = shr_idxres_list_alloc(oc->mep_pool,
  10307                     (shr_idxres_element_t *)&mep_index);
  10308             endpoint_info->id = mep_index;
  10309         }
  10310 
  10311         if (BCM_FAILURE(rv)) {
  10312             LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: "
  10313                       "MEP index alloc failed EP:%d %s.\n"), endpoint_info->id,
  10314                       bcm_errmsg(rv)));
  10315             return (rv);
  10316         }       
  10317 
  10318         /* Shift to specific data element in the array */
  10319         ep_data = &(oc->mep_data[mep_index]);
  10320 
  10321         /* If it is a Port + S + CVlan based MEP */
  10322         if (endpoint_info->flags & BCM_OAM_ENDPOINT_MATCH_OUTER_AND_INNER_VLAN) {
  10323             ep_data->mep_data.type = _FP_OAM_MEP_TYPE_S_C_VLAN;
  10324 
  10325         } else {
  10326 
  10327             /* If it is a Port + CVlan based MEP */
  10328             if (endpoint_info->flags & BCM_OAM_ENDPOINT_MATCH_INNER_VLAN) {
  10329                 ep_data->mep_data.type = _FP_OAM_MEP_TYPE_CVLAN;
  10330 
  10331             } else {
  10332 
  10333                 /* If it is a Port + SVlan based MEP */
  10334                 if (endpoint_info->vlan) {
  10335                     ep_data->mep_data.type = _FP_OAM_MEP_TYPE_SVLAN;
  10336 
  10337                 } else {
  10338                     /* If it is a Port based MEP */
  10339                     ep_data->mep_data.type = _FP_OAM_MEP_TYPE_PORT;
  10340                 }
  10341             }
  10342         }
  10343 
  10344         ep_data->mep_data.ep_id = mep_index;
  10345         ep_data->mep_data.level = endpoint_info->level;
  10346         ep_data->mep_data.period = endpoint_info->ccm_period;
  10347         ep_data->mep_data.name = endpoint_info->name;
  10348 
  10349         ep_data->mep_data.gport = endpoint_info->gport;
  10350         ep_data->mep_data.dglp = dst_glp;
  10351         ep_data->mep_data.sglp = src_glp;
  10352         ep_data->mep_data.trunk_index = endpoint_info->trunk_index;
  10353 
  10354         ep_data->mep_data.group_id = endpoint_info->group;
  10355 
  10356         ep_data->mep_data.vlan = endpoint_info->vlan;
  10357         ep_data->mep_data.pkt_pri = endpoint_info->pkt_pri;
  10358         ep_data->mep_data.tpid = endpoint_info->outer_tpid;
  10359 
  10360         ep_data->mep_data.inner_vlan = endpoint_info->inner_vlan;
  10361         ep_data->mep_data.inner_vlan_pri = endpoint_info->inner_pkt_pri;
  10362         ep_data->mep_data.inner_tpid = endpoint_info->inner_tpid;
  10363 
  10364         sal_memcpy(ep_data->mep_data.da,  endpoint_info->dst_mac_address,
  10365                    sizeof(bcm_mac_t));
  10366         sal_memcpy(ep_data->mep_data.sa,  endpoint_info->src_mac_address,
  10367                    sizeof(bcm_mac_t));
  10368 
  10369         grp_data_ptr = &(oc->group_data[endpoint_info->group].group_data);
  10370         if (!(endpoint_info->flags & BCM_OAM_ENDPOINT_REMOTE)) {
  10371             if (endpoint_info->flags & BCM_OAM_ENDPOINT_INTERFACE_STATE_TX) {
  10372                 ep_data->mep_data.flags |= _FP_OAM_INTERFACE_STATUS_TX;
  10373                 ep_data->mep_data.intf_state = endpoint_info->interface_state;
  10374             }
  10375 
  10376             if (endpoint_info->flags & BCM_OAM_ENDPOINT_PORT_STATE_TX) {
  10377                 ep_data->mep_data.flags |= _FP_OAM_PORT_STATUS_TX;
  10378                 ep_data->mep_data.port_state = endpoint_info->port_state;
  10379             }
  10380 
  10381             
  10382 
  10383             if (endpoint_info->ccm_tx_update_lm_counter_size != 0) {
  10384                 ep_data->mep_data.num_ctrs =
  10385                     endpoint_info->ccm_tx_update_lm_counter_size;
  10386                 for (i=0; i<ep_data->mep_data.num_ctrs; i++) {
  10387                     ep_data->mep_data.flex_stat_id[i] =
  10388                             endpoint_info->ccm_tx_update_lm_counter_base_id[i];
  10389                     ep_data->mep_data.counter_offset[i] =
  10390                             endpoint_info->ccm_tx_update_lm_counter_offset[i];
  10391                 }
  10392             }
  10393 
  10394             /* Set LMEP ID in group */
  10395             grp_data_ptr->lmep_id = mep_index;
  10396             msg_flags |= _MEP_OLP_RECREATE;
  10397             msg_flags |= (_MEP_L2_ENCAP_RECREATE);
  10398         } else {
  10399             ep_data->mep_data.flags |= _FP_OAM_REMOTE_MEP;
  10400             /* RMEP ID in the group */
  10401             _SET_BIT_FLD(grp_data_ptr->rmep_bitmap, mep_index);
  10402         }
  10403 
  10404         if (endpoint_info->flags & BCM_OAM_ENDPOINT_UP_FACING) {
  10405             ep_data->mep_data.flags |= _FP_OAM_DIRECTION_UP;
  10406         }
  10407 
  10408 
  10409         /* Send MEP Create Message to UKERNEL */
  10410         rv = _bcm_fp_oam_mep_set_msg_send(unit, ep_data, msg_flags, &r_len);
  10411 
  10412         if (BCM_FAILURE(rv)) {
  10413 
  10414             /* Free the allocated MEP index */
  10415             shr_idxres_list_free(oc->mep_pool, mep_index);
  10416 
  10417             /* Clear LMEP ID in Group */
  10418             if (!(endpoint_info->flags & BCM_OAM_ENDPOINT_REMOTE)) {
  10419                 grp_data_ptr->lmep_id = _FP_OAM_INVALID_LMEP_ID;
  10420             }
  10421             LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: "
  10422                   "MEP Creation failed EP:%d %s.\n"), endpoint_info->id,
  10423                   bcm_errmsg(rv)));
  10424             return (rv);
  10425 
  10426         } else {
  10427             ep_data->in_use = 1;
  10428         }
  10429 
  10430     } else {
  10431         /* Update case */
  10432         ep_data = &(oc->mep_data[endpoint_info->id]);
  10433 
  10434         /* For Remote MEP, can't replace anything */
  10435         if (endpoint_info->flags & BCM_OAM_ENDPOINT_REMOTE) {
  10436             LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: "
  10437                       "Cannot replace any parameter in RMEP.\n")));
  10438             return BCM_E_PARAM;
  10439         }
  10440 
  10441         /* For local MEP, can replace only Intf status, Port status, trunk index
  10442            counter indices */
  10443         if (((ep_data->mep_data.flags & _FP_OAM_INTERFACE_STATUS_TX) !=
  10444             (endpoint_info->flags & BCM_OAM_ENDPOINT_INTERFACE_STATE_TX)) ||
  10445             (ep_data->mep_data.intf_state != endpoint_info->interface_state)) {
  10446 
  10447             if (endpoint_info->flags & BCM_OAM_ENDPOINT_INTERFACE_STATE_TX) {
  10448 
  10449                 ep_data->mep_data.flags |= _FP_OAM_INTERFACE_STATUS_TX;
  10450                 ep_data->mep_data.intf_state = endpoint_info->interface_state;
  10451             } else {
  10452                 ep_data->mep_data.flags &= ~(_FP_OAM_INTERFACE_STATUS_TX);
  10453                 ep_data->mep_data.intf_state = 0;
  10454             }
  10455             /* Something valid was found to be replaced */
  10456             msg_flags |= _MEP_REPLACE;
  10457             msg_flags |= _REPLACE_INTF_STATUS;
  10458 
  10459         }
  10460 
  10461         if (((ep_data->mep_data.flags & _FP_OAM_PORT_STATUS_TX) !=
  10462             (endpoint_info->flags & BCM_OAM_ENDPOINT_PORT_STATE_TX)) ||
  10463             (ep_data->mep_data.port_state != endpoint_info->port_state)) {
  10464 
  10465             if (endpoint_info->flags & BCM_OAM_ENDPOINT_PORT_STATE_TX) {
  10466                 ep_data->mep_data.flags |= _FP_OAM_PORT_STATUS_TX;
  10467                 ep_data->mep_data.port_state = endpoint_info->port_state;
  10468             } else {
  10469                 ep_data->mep_data.flags &= ~(_FP_OAM_PORT_STATUS_TX);
  10470                 ep_data->mep_data.port_state = 0;
  10471             }
  10472             /* Something valid was found to be replaced */
  10473             msg_flags |= _MEP_REPLACE;
  10474             msg_flags |= _REPLACE_PORT_STATUS;
  10475         }
  10476 
  10477         if (ep_data->mep_data.trunk_index != endpoint_info->trunk_index) {
  10478             ep_data->mep_data.trunk_index = endpoint_info->trunk_index;
  10479             ep_data->mep_data.dglp = dst_glp;
  10480 
  10481             msg_flags |= (_MEP_REPLACE | _MEP_OLP_RECREATE);
  10482             msg_flags |= _REPLACE_TRUNK_INDEX;
  10483         }
  10484 
  10485         if (endpoint_info->flags2 & BCM_OAM_ENDPOINT_FLAGS2_UPDATE_COUNTER_ACTION) {
  10486             if (endpoint_info->ccm_tx_update_lm_counter_size != 0) {
  10487                 ep_data->mep_data.num_ctrs =
  10488                     endpoint_info->ccm_tx_update_lm_counter_size;
  10489                 for (i=0; i<ep_data->mep_data.num_ctrs; i++) {
  10490                     ep_data->mep_data.flex_stat_id[i] =
  10491                             endpoint_info->ccm_tx_update_lm_counter_base_id[i];
  10492                     ep_data->mep_data.counter_offset[i] =
  10493                             endpoint_info->ccm_tx_update_lm_counter_offset[i];
  10494                 }
  10495             }
  10496             msg_flags |= (_MEP_REPLACE | _MEP_OLP_RECREATE);
  10497             msg_flags |= _REPLACE_CTRS;
  10498         }
  10499 
  10500         if (!(msg_flags & _MEP_REPLACE)) {
  10501             /* Nothing valid was found to be updated */
  10502             rv = BCM_E_PARAM;
  10503             LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: "
  10504                 "Nothing valid to update:%d %s.\n"), endpoint_info->id,
  10505                 bcm_errmsg(rv)));
  10506             return (rv);
  10507         }
  10508 
  10509         /* Send MEP Update message to UKERNEL */
  10510         rv = _bcm_fp_oam_mep_set_msg_send(unit, ep_data, msg_flags, &r_len);
  10511 
  10512         if (BCM_FAILURE(rv)) {
  10513             LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: "
  10514                   "MEP Update failed EP:%d %s.\n"), endpoint_info->id,
  10515                   bcm_errmsg(rv)));
  10516             return (rv);
  10517         }
  10518     }
  10519 
  10520     return rv;
  10521 
  10522 }
  10523 
  10524 
  10525 /*,
  10526  * Function:
  10527  *     bcm_fp_oam_ccm_endpoint_get
  10528  * Purpose:
  10529  *     Create or replace an OAM endpoint object
  10530  * Parameters:
  10531  *     unit          - (IN) BCM device number
  10532  *     endpoint_info - (IN/OUT) Pointer to endpoint information buffer.
  10533  * Returns:
  10534  *      BCM_E_XXX
  10535  */
  10536 int
  10537 bcm_fp_oam_ccm_endpoint_get(int unit, bcm_oam_endpoint_info_t *ep_info_p) {
  10538 
  10539     _bcm_fp_oam_control_t *oc = NULL;
  10540     _bcm_fp_oam_mep_data_t *ep_data;
  10541     uint16  r_len = 0; /* Msg response lenght */
  10542     uint8 *dma_buffer1 = NULL;
  10543     uint8 *dma_buffer2 = NULL;
  10544     shr_ccm_msg_ctrl_mep_data_t mep_msg;
  10545     int rv = 0;
  10546 
  10547     /* Validate input parameter. */
  10548     if (NULL == ep_info_p) {
  10549         return (BCM_E_PARAM);
  10550     }
  10551     /* Get OAM Control Structure. */
  10552     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
  10553 
  10554     /* Validate EP Index */
  10555     _BCM_OAM_EP_INDEX_VALIDATE(ep_info_p->id);
  10556 
  10557     /* Get pointer to S/w MEP data */
  10558     ep_data = &(oc->mep_data[ep_info_p->id]);
  10559 
  10560     if (!(ep_data->in_use)) {
  10561         return BCM_E_NOT_FOUND;
  10562     }
  10563 
  10564     rv = _bcm_fp_oam_msg_send_receive(unit, MOS_MSG_CLASS_CCM,
  10565             MOS_MSG_SUBCLASS_CCM_MEP_GET_FAULTS_ONLY, ep_info_p->id, 0,
  10566             MOS_MSG_SUBCLASS_CCM_MEP_GET_REPLY, &r_len);
  10567 
  10568     if (BCM_FAILURE(rv)) {
  10569         LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: "
  10570               "MEP Update failed EP:%d %s.\n"), ep_info_p->id,
  10571               bcm_errmsg(rv)));
  10572         return (rv);
  10573     }
  10574     sal_memset(&mep_msg, 0, sizeof(shr_ccm_msg_ctrl_mep_data_t));
  10575     dma_buffer1 = oc->dma_buffer;
  10576     dma_buffer2 = shr_ccm_msg_ctrl_mep_get_unpack(dma_buffer1, &mep_msg);
  10577 
  10578     if (r_len != dma_buffer2 - dma_buffer1) {
  10579         rv = BCM_E_INTERNAL;
  10580         LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: "
  10581             "Mep get Msg lenght check failed, id:%d.\n"), ep_info_p->id));
  10582         return (rv);
  10583     }
  10584     ep_info_p->faults = mep_msg.mep_data.faults;
  10585     ep_info_p->persistent_faults = mep_msg.mep_data.persistent_faults;
  10586 
  10587     /* Fill rest of data from local db */
  10588     ep_info_p->type = bcmOAMEndpointTypeEthernet;
  10589     ep_info_p->group = ep_data->mep_data.group_id;
  10590     ep_info_p->ccm_period = ep_data->mep_data.period;
  10591     ep_info_p->gport = ep_data->mep_data.gport;
  10592     ep_info_p->trunk_index = ep_data->mep_data.trunk_index;
  10593     ep_info_p->name = ep_data->mep_data.name;
  10594     ep_info_p->level = ep_data->mep_data.level;
  10595 
  10596     ep_info_p->vlan = ep_data->mep_data.vlan;
  10597     ep_info_p->pkt_pri = ep_data->mep_data.pkt_pri;
  10598     ep_info_p->outer_tpid = ep_data->mep_data.tpid;
  10599 
  10600     ep_info_p->inner_vlan = ep_data->mep_data.inner_vlan;
  10601     ep_info_p->inner_pkt_pri = ep_data->mep_data.inner_vlan_pri;
  10602     ep_info_p->inner_tpid = ep_data->mep_data.inner_tpid;
  10603 
  10604     if (!(ep_data->mep_data.flags & _FP_OAM_REMOTE_MEP)) {
  10605 
  10606         if (ep_data->mep_data.flags & _FP_OAM_INTERFACE_STATUS_TX) {
  10607             ep_info_p->flags |= BCM_OAM_ENDPOINT_INTERFACE_STATE_TX;
  10608             ep_info_p->interface_state = ep_data->mep_data.intf_state;
  10609         }
  10610 
  10611         if (ep_data->mep_data.flags & _FP_OAM_PORT_STATUS_TX) {
  10612             ep_info_p->flags |= BCM_OAM_ENDPOINT_PORT_STATE_TX;
  10613             ep_info_p->port_state = ep_data->mep_data.port_state;
  10614         }
  10615 
  10616         ep_info_p->lm_counter_base_id = ep_data->mep_data.flex_stat_id[0];
  10617         sal_memcpy(ep_info_p->src_mac_address, ep_data->mep_data.sa,
  10618                    sizeof(bcm_mac_t));
  10619         sal_memcpy(ep_info_p->dst_mac_address, ep_data->mep_data.da,
  10620                    sizeof(bcm_mac_t));
  10621     } else {
  10622         /* Set remote flag */
  10623         ep_info_p->flags |= BCM_OAM_ENDPOINT_REMOTE;
  10624         ep_info_p->interface_state = mep_msg.mep_data.intf_state;
  10625         ep_info_p->port_state = mep_msg.mep_data.port_state;
  10626         sal_memcpy(ep_info_p->src_mac_address, mep_msg.mep_data.sa, 
  10627                    sizeof(bcm_mac_t));
  10628         sal_memcpy(ep_info_p->dst_mac_address, mep_msg.mep_data.da, 
  10629                    sizeof(bcm_mac_t));
  10630     }
  10631 
  10632     return (rv);
  10633 }
  10634 
  10635 
  10636 int
  10637 _bcm_fp_oam_ccm_endpoint_traverse(int unit, bcm_oam_group_t group,
  10638                                   bcm_oam_endpoint_traverse_cb cb, void *user_data)
  10639 {
  10640     _bcm_fp_oam_control_t    *oc;        /* OAM control structure pointer. */
  10641     _bcm_fp_oam_group_data_t *group_p;
  10642     int rv = 0;                                 /* Return Value */
  10643     ccm_group_data_t *grp_data_ptr = NULL;
  10644     bcm_oam_endpoint_info_t endpoint_info = {0};
  10645     bcm_oam_endpoint_t epid;
  10646 
  10647     if (NULL == cb) {
  10648         return (BCM_E_PARAM);
  10649     }
  10650 
  10651     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
  10652 
  10653     group_p = &(oc->group_data[group]);
  10654     if (group_p->in_use) {
  10655         grp_data_ptr = &(oc->group_data[group].group_data);
  10656         epid = grp_data_ptr->lmep_id;
  10657         if(epid >=0 && epid <oc->mep_count) {
  10658             endpoint_info.id = epid;
  10659             rv = bcm_fp_oam_ccm_endpoint_get(unit, &endpoint_info);
  10660 
  10661             rv = cb(unit, &endpoint_info, user_data);
  10662             if (BCM_FAILURE(rv)) {
  10663                 LOG_ERROR(BSL_LS_BCM_OAM,
  10664                           (BSL_META_U(unit,
  10665                                       "OAM(unit %d) Error: User call back "
  10666                                       "routine (EP=%d) - %s.\n"), unit,
  10667                                       epid, bcm_errmsg(rv)));
  10668                 return (rv);
  10669             }
  10670 
  10671         }
  10672     }
  10673     return BCM_E_NONE;
  10674 }
  10675 
  10676 /*
  10677  * Function:
  10678  *     bcm_fp_oam_ccm_group_destroy
  10679  * Purpose:
  10680  *     Delete an OAM group object. All OAM endpoints associated with the
  10681  *     group will also be destroyed.
  10682  * Parameters:
  10683  *     unit       - (IN) BCM device number
  10684  *     group_info - (IN/OUT) Pointer to an OAM group Id.
  10685  * Returns:
  10686  *     BCM_E_XXX
  10687  */
  10688 int
  10689 bcm_fp_oam_ccm_endpoint_destroy(int unit, bcm_oam_endpoint_t endpoint)
  10690 {
  10691     _bcm_fp_oam_control_t *oc = NULL;      /* OAM control structure */
  10692     _bcm_fp_oam_mep_data_t *ep_p;          /* Handle to S/w Group Data */
  10693     int rv = 0;                            /* Return Value */
  10694     uint16 r_len;                          /* Msg reply lenght */
  10695     _bcm_fp_oam_group_data_t *grp_p;       /* Handle to S/w Group Data */
  10696 
  10697     /* Get OAM control structure handle. */
  10698     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
  10699 
  10700     /* Validate EP Index */
  10701     _BCM_OAM_EP_INDEX_VALIDATE(endpoint);
  10702 
  10703     /* Get Handle to Local DB */
  10704     ep_p = &(oc->mep_data[endpoint]);
  10705     if (!(ep_p->in_use)) {
  10706         return BCM_E_NOT_FOUND;
  10707     }
  10708 
  10709     rv = _bcm_fp_oam_msg_send_receive(unit, MOS_MSG_CLASS_CCM,
  10710             MOS_MSG_SUBCLASS_CCM_MEP_DELETE, endpoint, 0,
  10711             MOS_MSG_SUBCLASS_CCM_MEP_DELETE_REPLY, &r_len);
  10712 
  10713     if (BCM_FAILURE(rv)) {
  10714         LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: "
  10715             "Mep Del Msg returned error %s.\n"), bcm_errmsg(rv)));
  10716         rv = BCM_E_INTERNAL;
  10717         return rv;
  10718     }
  10719 
  10720     /* Clean up Group's LMEP/RMEP reference */
  10721     grp_p = &(oc->group_data[ep_p->mep_data.group_id]);
  10722     if (ep_p->mep_data.flags &  _FP_OAM_REMOTE_MEP) {
  10723         _CLR_BIT_FLD(grp_p->group_data.rmep_bitmap, endpoint);
  10724     } else {
  10725         grp_p->group_data.lmep_id = _FP_OAM_INVALID_LMEP_ID;
  10726     }
  10727 
  10728     /* Free the EP index */
  10729     rv = shr_idxres_list_free(oc->mep_pool, endpoint);
  10730     if (BCM_FAILURE(rv)) {
  10731         LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: "
  10732                   "MEP index Free failed EP:%d %s.\n"), endpoint,
  10733                   bcm_errmsg(rv)));
  10734         return (rv);
  10735     }
  10736 
  10737     sal_memset(ep_p, 0, sizeof(_bcm_fp_oam_mep_data_t));
  10738 
  10739     return rv;
  10740 }
  10741 
  10742 
  10743 /*
  10744  * Function:
  10745  *      _bcm_fp_oam_ccm_event_mask_set
  10746  * Purpose:
  10747  *      Set the CCM Events mask.
  10748  * Parameters:
  10749  *      unit        - (IN) Unit number.
  10750  * Returns:
  10751  *      BCM_E_NONE Operation completed successfully
  10752  *      BCM_E_XXX  Operation failed
  10753  * Notes:
  10754  */
  10755 STATIC int
  10756 _bcm_fp_oam_ccm_event_mask_set(int unit)
  10757 {
  10758     _bcm_fp_oam_control_t *oc;
  10759     _bcm_oam_event_handler_t *event_handler_p;
  10760     uint32 event_mask = 0;
  10761     uint16 reply_len;
  10762     int rv = BCM_E_NONE;
  10763 
  10764     /* Lock already taken by the calling routine. */
  10765     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
  10766 
  10767     /* Get event mask from all callbacks */
  10768     for (event_handler_p = oc->event_handler_list_p;
  10769          event_handler_p != NULL;
  10770          event_handler_p = event_handler_p->next_p) {
  10771 
  10772         if (SHR_BITGET(event_handler_p->event_types.w,
  10773                        bcmOAMEventGroupCCMxcon)) {
  10774             event_mask |= G_XCON;
  10775         }
  10776         if (SHR_BITGET(event_handler_p->event_types.w,
  10777                        bcmOAMEventGroupCCMError)) {
  10778             event_mask |= G_CCM_ERROR;
  10779         }
  10780         if (SHR_BITGET(event_handler_p->event_types.w,
  10781                        bcmOAMEventGroupRemote)) {
  10782             event_mask |= G_RDI;
  10783         }
  10784         if (SHR_BITGET(event_handler_p->event_types.w,
  10785                        bcmOAMEventGroupCCMTimeout)) {
  10786             event_mask |= G_CCM_TIMEOUT;
  10787         }
  10788         if (SHR_BITGET(event_handler_p->event_types.w,
  10789                        bcmOAMEventGroupMACStatus)) {
  10790             event_mask |= G_CCM_MAC;
  10791         }
  10792         if (SHR_BITGET(event_handler_p->event_types.w,
  10793                        bcmOAMEventGroupCCMxconClear)) {
  10794             event_mask |= G_XCON_CLR;
  10795         }
  10796         if (SHR_BITGET(event_handler_p->event_types.w,
  10797                        bcmOAMEventGroupCCMErrorClear)) {
  10798             event_mask |= G_CCM_ERROR_CLR;
  10799         }
  10800         if (SHR_BITGET(event_handler_p->event_types.w,
  10801                        bcmOAMEventGroupRemoteClear)) {
  10802             event_mask |= G_RDI_CLR;
  10803         }
  10804         if (SHR_BITGET(event_handler_p->event_types.w,
  10805                        bcmOAMEventGroupCCMTimeoutClear)) {
  10806             event_mask |= G_CCM_TIME_IN;
  10807         }
  10808         if (SHR_BITGET(event_handler_p->event_types.w,
  10809                        bcmOAMEventGroupMACStatusClear)) {
  10810             event_mask |= G_CCM_MAC_CLR;
  10811         }
  10812 
  10813         if (SHR_BITGET(event_handler_p->event_types.w,
  10814                        bcmOAMEventEndpointPortDown)) {
  10815             event_mask |= E_PORT_DOWN;
  10816         }
  10817         if (SHR_BITGET(event_handler_p->event_types.w,
  10818                        bcmOAMEventEndpointPortUp)) {
  10819             event_mask |= E_PORT_UP;
  10820         }
  10821         if (SHR_BITGET(event_handler_p->event_types.w,
  10822                        bcmOAMEventEndpointInterfaceDown)) {
  10823             event_mask |= E_INTF_DOWN;
  10824         }
  10825         if (SHR_BITGET(event_handler_p->event_types.w,
  10826                        bcmOAMEventEndpointInterfaceUp)) {
  10827             event_mask |= E_INTF_UP;
  10828         }
  10829         if (SHR_BITGET(event_handler_p->event_types.w,
  10830                        bcmOAMEventEndpointInterfaceTesting)) {
  10831             event_mask |= E_INTF_TEST;
  10832         }
  10833         if (SHR_BITGET(event_handler_p->event_types.w,
  10834                        bcmOAMEventEndpointInterfaceUnkonwn)) {
  10835             event_mask |= E_INTF_UK;
  10836         }
  10837         if (SHR_BITGET(event_handler_p->event_types.w,
  10838                        bcmOAMEventEndpointInterfaceDormant)) {
  10839             event_mask |= E_INTF_DOR;
  10840         }
  10841         if (SHR_BITGET(event_handler_p->event_types.w,
  10842                        bcmOAMEventEndpointInterfaceDormantToUp)) {
  10843             event_mask |= E_INTF_DOR;
  10844         }
  10845         if (SHR_BITGET(event_handler_p->event_types.w,
  10846                        bcmOAMEventEndpointInterfaceNotPresent)) {
  10847             event_mask |= E_INTF_NP;
  10848         }
  10849         if (SHR_BITGET(event_handler_p->event_types.w,
  10850                        bcmOAMEventEndpointInterfaceLLDown)) {
  10851             event_mask |= E_INTF_LL;
  10852         }
  10853         if (SHR_BITGET(event_handler_p->event_types.w,
  10854                        bcmOAMEventEndpointCCMTimeout)) {
  10855             event_mask |= E_CCM_TIMEOUT;
  10856         }
  10857         if (SHR_BITGET(event_handler_p->event_types.w,
  10858                        bcmOAMEventEndpointCCMTimein)) {
  10859             event_mask |= E_CCM_TIME_IN;
  10860         }
  10861         if (SHR_BITGET(event_handler_p->event_types.w,
  10862                        bcmOAMEventEndpointRemote)) {
  10863             event_mask |= E_CCM_RDI;
  10864         }
  10865         if (SHR_BITGET(event_handler_p->event_types.w,
  10866                        bcmOAMEventEndpointRemoteUp)) {
  10867             event_mask |= E_CCM_RDI_CLR;
  10868         }
  10869     }
  10870 
  10871     /* Update CCM event mask in uKernel */
  10872     if (event_mask != oc->event_mask) {
  10873         /* Send CCM Event Mask message to uC */
  10874         rv = _bcm_fp_oam_msg_send_receive(unit, MOS_MSG_CLASS_CCM,
  10875                  MOS_MSG_SUBCLASS_CCM_EVENT_MASK_SET, 0, event_mask,
  10876                  MOS_MSG_SUBCLASS_CCM_EVENT_MASK_SET_REPLY,
  10877                  &reply_len);
  10878 
  10879         if (BCM_FAILURE(rv)) {
  10880             LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: "
  10881                 "Event Mask set Msg returned error %s.\n"), bcm_errmsg(rv)));
  10882             rv = BCM_E_INTERNAL;
  10883         }
  10884     }
  10885 
  10886     oc->event_mask = event_mask;
  10887 
  10888     return (rv);
  10889 }
  10890 
  10891 
  10892 /*
  10893  * Function:
  10894  *      _bcm_fp_oam_ccm_callback_thread
  10895  * Purpose:
  10896  *      Thread to listen for event messages from uController.
  10897  * Parameters:
  10898  *      param - Pointer to CCM info structure.
  10899  * Returns:
  10900  *      None
  10901  */
  10902 STATIC void
  10903 _bcm_fp_oam_ccm_callback_thread(void *param)
  10904 {
  10905     int rv;
  10906     _bcm_fp_oam_control_t *oc = (_bcm_fp_oam_control_t *)param;
  10907     bcm_oam_event_types_t events;
  10908     bcm_oam_event_type_t event_type;
  10909     mos_msg_data_t event_msg;
  10910     int data_index = 0;
  10911     uint32 event_mask;
  10912     _bcm_oam_event_handler_t *event_handler_p;
  10913     int ep_id = BCM_OAM_ENDPOINT_INVALID;
  10914     int group_id = BCM_OAM_GROUP_INVALID;
  10915     char thread_name[SAL_THREAD_NAME_MAX_LEN];
  10916 
  10917     thread_name[0] = 0;
  10918     sal_thread_name(oc->event_thread_id, thread_name, sizeof (thread_name));
  10919 
  10920     while (1) {
  10921         /* Wait on notifications from uController */
  10922         rv = soc_cmic_uc_msg_receive(oc->unit, oc->ccm_uc_num,
  10923                                      MOS_MSG_CLASS_CCM_EVENT, &event_msg,
  10924                                      sal_sem_FOREVER);
  10925         if (BCM_FAILURE(rv)) {
  10926             break;  /*  Thread exit */
  10927         }
  10928 
  10929         /* Get data from event message */
  10930         data_index = (int)bcm_ntohs(event_msg.s.len);
  10931         event_mask = bcm_ntohl(event_msg.s.data);
  10932 
  10933         /* One event Msg can either carry one or more Events related
  10934            Group or Endpoint, Check whether Group event or EP event */
  10935 
  10936          /* Validate EP Index */
  10937          if ( (data_index < 0) || (data_index >= oc->mep_count) ||
  10938              !(oc->mep_data[data_index].in_use) ) {
  10939             LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META("OAM Error: "
  10940                 "CCM Event with Invalid EP ID = %d.\n"), data_index));
  10941             continue;
  10942          }
  10943          ep_id = data_index;
  10944          group_id = oc->mep_data[data_index].mep_data.group_id;
  10945 
  10946         /* Set events */
  10947         sal_memset(&events, 0, sizeof(events));
  10948         if (event_mask & G_EVENT_MASK) {
  10949 
  10950             /* Group Events */
  10951             if (event_mask & G_XCON) {
  10952                 LOG_DEBUG(BSL_LS_BCM_OAM, (BSL_META_U(oc->unit,
  10953                     "bcmOAMEventGroupCCMxcon - %d\n"), data_index));
  10954 
  10955                 if (oc->event_handler_cnt[bcmOAMEventGroupCCMxcon] > 0) {
  10956                     SHR_BITSET(events.w, bcmOAMEventGroupCCMxcon);
  10957                 }
  10958             }
  10959             if (event_mask & G_CCM_ERROR) {
  10960                 LOG_DEBUG(BSL_LS_BCM_OAM, (BSL_META_U(oc->unit,
  10961                     "bcmOAMEventGroupCCMError - %d\n"), data_index));
  10962 
  10963                 if (oc->event_handler_cnt[bcmOAMEventGroupCCMError] > 0) {
  10964                     SHR_BITSET(events.w, bcmOAMEventGroupCCMError);
  10965                 }
  10966             }
  10967 
  10968             if (event_mask & G_RDI) {
  10969                 LOG_DEBUG(BSL_LS_BCM_OAM, (BSL_META_U(oc->unit,
  10970                     "bcmOAMEventGroupRemote - %d\n"), data_index));
  10971 
  10972                 if (oc->event_handler_cnt[bcmOAMEventGroupRemote] > 0) {
  10973                     SHR_BITSET(events.w, bcmOAMEventGroupRemote);
  10974                 }
  10975             }
  10976 
  10977             if (event_mask & G_CCM_TIMEOUT) {
  10978                 LOG_DEBUG(BSL_LS_BCM_OAM, (BSL_META_U(oc->unit,
  10979                     "bcmOAMEventGroupCCMTimeout - %d\n"), data_index));
  10980 
  10981                 if (oc->event_handler_cnt[bcmOAMEventGroupCCMTimeout] > 0) {
  10982                     SHR_BITSET(events.w, bcmOAMEventGroupCCMTimeout);
  10983                 }
  10984             }
  10985 
  10986             if (event_mask & G_CCM_MAC) {
  10987                 LOG_DEBUG(BSL_LS_BCM_OAM, (BSL_META_U(oc->unit,
  10988                     "bcmOAMEventGroupMACStatus - %d\n"), data_index));
  10989 
  10990                 if (oc->event_handler_cnt[bcmOAMEventGroupMACStatus] > 0) {
  10991                     SHR_BITSET(events.w, bcmOAMEventGroupMACStatus);
  10992                 }
  10993             }
  10994 
  10995             /* Group Clear Events */
  10996             if (event_mask & G_XCON_CLR) {
  10997                 LOG_DEBUG(BSL_LS_BCM_OAM, (BSL_META_U(oc->unit,
  10998                     "bcmOAMEventGroupRemote - %d\n"), data_index));
  10999 
  11000                 if (oc->event_handler_cnt[bcmOAMEventGroupCCMxconClear] > 0) {
  11001                     SHR_BITSET(events.w, bcmOAMEventGroupCCMxconClear);
  11002                 }
  11003             }
  11004 
  11005             if (event_mask & G_CCM_ERROR_CLR) {
  11006                 LOG_DEBUG(BSL_LS_BCM_OAM, (BSL_META_U(oc->unit,
  11007                     "bcmOAMEventGroupCCMTimeout - %d\n"), data_index));
  11008 
  11009                 if (oc->event_handler_cnt[bcmOAMEventGroupCCMErrorClear] > 0) {
  11010                     SHR_BITSET(events.w, bcmOAMEventGroupCCMErrorClear);
  11011                 }
  11012             }
  11013 
  11014             if (event_mask & G_RDI_CLR) {
  11015                 LOG_DEBUG(BSL_LS_BCM_OAM, (BSL_META_U(oc->unit,
  11016                     "bcmOAMEventGroupRemote - %d\n"), data_index));
  11017 
  11018                 if (oc->event_handler_cnt[bcmOAMEventGroupRemoteClear] > 0) {
  11019                     SHR_BITSET(events.w, bcmOAMEventGroupRemoteClear);
  11020                 }
  11021             }
  11022 
  11023             if (event_mask & G_CCM_TIME_IN) {
  11024                 LOG_DEBUG(BSL_LS_BCM_OAM, (BSL_META_U(oc->unit,
  11025                     "bcmOAMEventGroupCCMTimeoutClear - %d\n"), data_index));
  11026 
  11027                 if (oc->event_handler_cnt[bcmOAMEventGroupCCMTimeoutClear] > 0) {
  11028                     SHR_BITSET(events.w, bcmOAMEventGroupCCMTimeoutClear);
  11029                 }
  11030             }
  11031 
  11032             if (event_mask & G_CCM_MAC_CLR) {
  11033                 LOG_DEBUG(BSL_LS_BCM_OAM, (BSL_META_U(oc->unit,
  11034                     "bcmOAMEventGroupMACStatusClear - %d\n"), data_index));
  11035 
  11036                 if (oc->event_handler_cnt[bcmOAMEventGroupMACStatusClear] > 0) {
  11037                     SHR_BITSET(events.w, bcmOAMEventGroupMACStatusClear);
  11038                 }
  11039             }
  11040         }
  11041         if ( event_mask & E_EVENT_MASK) {
  11042 
  11043             /* Endpoint Events */
  11044             if (event_mask & E_PORT_DOWN) {
  11045                 LOG_DEBUG(BSL_LS_BCM_OAM, (BSL_META_U(oc->unit,
  11046                     "bcmOAMEventEndpointPortDown - %d\n"), data_index));
  11047 
  11048                 if (oc->event_handler_cnt[bcmOAMEventEndpointPortDown] > 0) {
  11049                     SHR_BITSET(events.w, bcmOAMEventEndpointPortDown);
  11050                 }
  11051             }
  11052 
  11053             if (event_mask & E_PORT_UP) {
  11054                 LOG_DEBUG(BSL_LS_BCM_OAM, (BSL_META_U(oc->unit,
  11055                     "bcmOAMEventEndpointPortUp - %d\n"), data_index));
  11056 
  11057                 if (oc->event_handler_cnt[bcmOAMEventEndpointPortUp] > 0) {
  11058                     SHR_BITSET(events.w, bcmOAMEventEndpointPortUp);
  11059                 }
  11060             }
  11061 
  11062             if (event_mask & E_INTF_DOWN) {
  11063                 LOG_DEBUG(BSL_LS_BCM_OAM, (BSL_META_U(oc->unit,
  11064                     "bcmOAMEventEndpointInterfaceDown - %d\n"), data_index));
  11065 
  11066                 if (oc->event_handler_cnt[bcmOAMEventEndpointInterfaceDown] > 0) {
  11067                     SHR_BITSET(events.w, bcmOAMEventEndpointInterfaceDown);
  11068                 }
  11069             }
  11070 
  11071             if (event_mask & E_INTF_UP) {
  11072                 LOG_DEBUG(BSL_LS_BCM_OAM, (BSL_META_U(oc->unit,
  11073                     "bcmOAMEventEndpointInterfaceUp - %d\n"), data_index));
  11074 
  11075                 if (oc->event_handler_cnt[bcmOAMEventEndpointInterfaceUp] > 0) {
  11076                     SHR_BITSET(events.w, bcmOAMEventEndpointInterfaceUp);
  11077                 }
  11078             }
  11079 
  11080             if (event_mask & E_INTF_TEST) {
  11081                 LOG_DEBUG(BSL_LS_BCM_OAM, (BSL_META_U(oc->unit,
  11082                     "bcmOAMEventEndpointInterfaceTesting - %d\n"), data_index));
  11083 
  11084                 if (oc->event_handler_cnt[bcmOAMEventEndpointInterfaceTesting] > 0) {
  11085                     SHR_BITSET(events.w, bcmOAMEventEndpointInterfaceTesting);
  11086                 }
  11087             }
  11088 
  11089             if (event_mask & E_INTF_UK) {
  11090                 LOG_DEBUG(BSL_LS_BCM_OAM, (BSL_META_U(oc->unit,
  11091                     "bcmOAMEventEndpointInterfaceUnkonwn - %d\n"), data_index));
  11092 
  11093                 if (oc->event_handler_cnt[bcmOAMEventEndpointInterfaceUnkonwn] > 0) {
  11094                     SHR_BITSET(events.w, bcmOAMEventEndpointInterfaceUnkonwn);
  11095                 }
  11096             }
  11097 
  11098             if (event_mask & E_INTF_DOR) {
  11099                 LOG_DEBUG(BSL_LS_BCM_OAM, (BSL_META_U(oc->unit,
  11100                     "bcmOAMEventEndpointInterfaceDormant - %d\n"), data_index));
  11101 
  11102                 if (oc->event_handler_cnt[bcmOAMEventEndpointInterfaceDormant] > 0) {
  11103                     SHR_BITSET(events.w, bcmOAMEventEndpointInterfaceDormant);
  11104                 }
  11105             }
  11106 
  11107             if (event_mask & E_INTF_NP) {
  11108                 LOG_DEBUG(BSL_LS_BCM_OAM, (BSL_META_U(oc->unit,
  11109                     "bcmOAMEventEndpointInterfaceNotPresent - %d\n"), data_index));
  11110 
  11111                 if (oc->event_handler_cnt[bcmOAMEventEndpointInterfaceNotPresent] > 0) {
  11112                     SHR_BITSET(events.w, bcmOAMEventEndpointInterfaceNotPresent);
  11113                 }
  11114             }
  11115 
  11116             if (event_mask & E_INTF_LL) {
  11117                 LOG_DEBUG(BSL_LS_BCM_OAM, (BSL_META_U(oc->unit,
  11118                     "bcmOAMEventEndpointInterfaceLLDown - %d\n"), data_index));
  11119 
  11120                 if (oc->event_handler_cnt[bcmOAMEventEndpointInterfaceLLDown] > 0) {
  11121                     SHR_BITSET(events.w, bcmOAMEventEndpointInterfaceLLDown);
  11122                 }
  11123             }
  11124 
  11125             if (event_mask & E_CCM_TIMEOUT) {
  11126                 LOG_DEBUG(BSL_LS_BCM_OAM, (BSL_META_U(oc->unit,
  11127                     "bcmOAMEventEndpointCCMTimeout - %d\n"), data_index));
  11128 
  11129                 if (oc->event_handler_cnt[bcmOAMEventEndpointCCMTimeout] > 0) {
  11130                     SHR_BITSET(events.w, bcmOAMEventEndpointCCMTimeout);
  11131                 }
  11132             }
  11133 
  11134             if (event_mask & E_CCM_TIME_IN) {
  11135                 LOG_DEBUG(BSL_LS_BCM_OAM, (BSL_META_U(oc->unit,
  11136                     "bcmOAMEventEndpointCCMTimein - %d\n"), data_index));
  11137 
  11138                 if (oc->event_handler_cnt[bcmOAMEventEndpointCCMTimein] > 0) {
  11139                     SHR_BITSET(events.w, bcmOAMEventEndpointCCMTimein);
  11140                 }
  11141             }
  11142 
  11143             if (event_mask & E_CCM_RDI) {
  11144                 LOG_DEBUG(BSL_LS_BCM_OAM, (BSL_META_U(oc->unit,
  11145                     "bcmOAMEventEndpointRemote - %d\n"), data_index));
  11146 
  11147                 if (oc->event_handler_cnt[bcmOAMEventEndpointRemote] > 0) {
  11148                     SHR_BITSET(events.w, bcmOAMEventEndpointRemote);
  11149                 }
  11150             }
  11151 
  11152             if (event_mask & E_CCM_RDI_CLR) {
  11153                 LOG_DEBUG(BSL_LS_BCM_OAM, (BSL_META_U(oc->unit,
  11154                     "bcmOAMEventEndpointRemoteUp - %d\n"), data_index));
  11155 
  11156                 if (oc->event_handler_cnt[bcmOAMEventEndpointRemoteUp] > 0) {
  11157                     SHR_BITSET(events.w, bcmOAMEventEndpointRemoteUp);
  11158                 }
  11159             }
  11160         }
  11161 
  11162         /* Loop over registered callbacks,
  11163          * If any match the events field, then invoke
  11164          */
  11165         for (event_handler_p = oc->event_handler_list_p; event_handler_p != NULL;
  11166              event_handler_p = event_handler_p->next_p) {
  11167 
  11168             for (event_type = bcmOAMEventEndpointPortDown;
  11169                  event_type < bcmOAMEventCount; ++event_type) {
  11170 
  11171                 if (SHR_BITGET(events.w, event_type)) {
  11172                     if (SHR_BITGET(event_handler_p->event_types.w, event_type)) {
  11173                         event_handler_p->cb(oc->unit,
  11174                         0,
  11175                         event_type,
  11176                         group_id, /* Group index */
  11177                         ep_id, /* Endpoint index */
  11178                         event_handler_p->user_data);
  11179                     }
  11180                 }
  11181             }
  11182         }
  11183     }
  11184 
  11185     oc->event_thread_id = NULL;
  11186     LOG_DEBUG(BSL_LS_BCM_OAM, (BSL_META_U(oc->unit, "Thread Exit:%s\n"),
  11187                thread_name));
  11188     sal_thread_exit(0);
  11189 }
  11190 
  11191 
  11192 /*
  11193  * Function:
  11194  *      _bcm_fp_oam_cmm_group_regen
  11195  * Purpose:
  11196  *      Reconstruct CCM Group S/w State from UKENREL on WB
  11197  *      Assumes Lock
  11198  * Parameters:
  11199  *      unit - (IN) BCM device number
  11200  * Retruns:
  11201  *     BCM_E_XXX
  11202  */
  11203 STATIC int
  11204 _bcm_fp_oam_cmm_group_regen(int unit, int grp_id) {
  11205 
  11206     int rv;
  11207     _bcm_fp_oam_control_t *oc;  /* Pointer to OAM control structure */
  11208     uint16 r_len;
  11209     shr_ccm_msg_ctrl_group_data_t grp_msg;
  11210     uint8 *dma_buffer1 = NULL;
  11211     uint8 *dma_buffer2 = NULL;
  11212 
  11213     /* Get OAM control structure. */
  11214     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
  11215 
  11216     rv = _bcm_fp_oam_msg_send_receive(unit, MOS_MSG_CLASS_CCM,
  11217             MOS_MSG_SUBCLASS_CCM_GROUP_GET, grp_id, 0,
  11218             MOS_MSG_SUBCLASS_CCM_GROUP_GET_REPLY, &r_len);
  11219 
  11220     if (BCM_FAILURE(rv)) {
  11221         LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: "
  11222               "Group Get failed Id:%d %s.\n"), grp_id, bcm_errmsg(rv)));
  11223         return (rv);
  11224     }
  11225 
  11226     sal_memset(&grp_msg, 0, sizeof(shr_ccm_msg_ctrl_group_data_t));
  11227     dma_buffer1 = oc->dma_buffer;
  11228     dma_buffer2 = shr_ccm_msg_ctrl_group_get_unpack(dma_buffer1, &grp_msg);
  11229 
  11230     if (r_len != dma_buffer2 - dma_buffer1) {
  11231         rv = BCM_E_INTERNAL;
  11232         LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: "
  11233             "Group get Msg lenght check failed, Id:%d.\n"), grp_id));
  11234         return (rv);
  11235     }
  11236 
  11237     sal_memcpy(&(oc->group_data[grp_id].group_data) , &(grp_msg.group_data), 
  11238                sizeof(ccm_group_data_t));
  11239 
  11240     rv = shr_idxres_list_reserve(oc->group_pool, grp_id, grp_id);
  11241     if (BCM_FAILURE(rv)) {
  11242         LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: "
  11243                   "Group index reservation failed, id:%d.\n"), grp_id));
  11244         return ((rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv);
  11245     }
  11246     oc->group_data[grp_id].in_use = 1;
  11247 
  11248     return BCM_E_NONE;
  11249 }
  11250 
  11251 
  11252 /*
  11253  * Function:
  11254  *      _bcm_fp_oam_cmm_mep_regen
  11255  * Purpose:
  11256  *      Reconstruct CCM MEP S/w State from UKENREL on WB
  11257  *      Assumes Lock
  11258  * Parameters:
  11259  *      unit - (IN) BCM device number
  11260  * Retruns:
  11261  *     BCM_E_XXX
  11262  */
  11263 STATIC int
  11264 _bcm_fp_oam_cmm_mep_regen(int unit, int mep_id) {
  11265 
  11266     int rv;
  11267     _bcm_fp_oam_control_t *oc;  /* Pointer to OAM control structure */
  11268     uint16 r_len;
  11269     shr_ccm_msg_ctrl_mep_data_t mep_msg;
  11270     uint8 *dma_buffer1 = NULL;
  11271     uint8 *dma_buffer2 = NULL;
  11272 
  11273     /* Get OAM control structure. */
  11274     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
  11275 
  11276     rv = _bcm_fp_oam_msg_send_receive(unit, MOS_MSG_CLASS_CCM,
  11277             MOS_MSG_SUBCLASS_CCM_MEP_GET, mep_id, 0,
  11278             MOS_MSG_SUBCLASS_CCM_MEP_GET_REPLY, &r_len);
  11279 
  11280     if (BCM_FAILURE(rv)) {
  11281         LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: "
  11282               "MEP Get failed EP:%d %s.\n"), mep_id, bcm_errmsg(rv)));
  11283         return (rv);
  11284     }
  11285 
  11286     sal_memset(&mep_msg, 0, sizeof(shr_ccm_msg_ctrl_mep_data_t));
  11287     dma_buffer1 = oc->dma_buffer;
  11288     dma_buffer2 = shr_ccm_msg_ctrl_mep_get_unpack(dma_buffer1, &mep_msg);
  11289 
  11290     if (r_len != dma_buffer2 - dma_buffer1) {
  11291         rv = BCM_E_INTERNAL;
  11292         LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: "
  11293             "Mep get Msg lenght check failed, id:%d.\n"), mep_id));
  11294         return (rv);
  11295     }
  11296 
  11297     sal_memcpy(&(oc->mep_data[mep_id].mep_data) , &(mep_msg.mep_data), 
  11298                sizeof(ccm_mep_data_t));
  11299 
  11300     rv = shr_idxres_list_reserve(oc->mep_pool, mep_id, mep_id);
  11301     if (BCM_FAILURE(rv)) {
  11302         LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: "
  11303                   "Mep index reservation failed, id:%d.\n"), mep_id));
  11304         return ((rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv);
  11305     }
  11306     oc->mep_data[mep_id].in_use = 1;
  11307 
  11308     return BCM_E_NONE;
  11309 }
  11310 
  11311 
  11312 /*
  11313  * Function:
  11314  *      _bcm_fp_oam_ccm_reinit
  11315  * Purpose:
  11316  *      Reconstruct CCM S/w State from UKENREL on WB
  11317  * Parameters:
  11318  *      unit - (IN) BCM device number
  11319  * Retruns:
  11320  *     BCM_E_XXX
  11321  */
  11322 STATIC int
  11323 _bcm_fp_oam_ccm_reinit(int unit) {
  11324     _bcm_fp_oam_control_t *oc;  /* Pointer to OAM control structure */
  11325     int rv = BCM_E_NONE;        /* Operation return status */
  11326     uint16 r_len = 0;
  11327     shr_ccm_msg_ctrl_app_data_t app_data_msg;
  11328     uint8 *dma_buffer1 = NULL;
  11329     uint8 *dma_buffer2 = NULL;
  11330     int i, j;
  11331     ccm_group_data_t *group_ptr = NULL;
  11332 
  11333     /* Get OAM control structure. */
  11334     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
  11335     _BCM_OAM_LOCK(oc);
  11336 
  11337     /* Recover group Bitmap from UKENREL */
  11338     rv = _bcm_fp_oam_msg_send_receive(unit, MOS_MSG_CLASS_CCM,
  11339         MOS_MSG_SUBCLASS_CCM_GET_APP_DATA, 0, 0,
  11340         MOS_MSG_SUBCLASS_CCM_GET_APP_DATA_REPLY, &r_len);
  11341     if (BCM_FAILURE(rv)) {
  11342         LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: "
  11343               "App data get failed %s\n"), bcm_errmsg(rv)));
  11344         _BCM_OAM_UNLOCK(oc);
  11345         return (rv);
  11346     }
  11347 
  11348     sal_memset(&app_data_msg, 0, sizeof(shr_ccm_msg_ctrl_app_data_t));
  11349     dma_buffer1 = oc->dma_buffer;
  11350     dma_buffer2 = shr_ccm_msg_ctrl_app_data_unpack(dma_buffer1, &app_data_msg);
  11351     if (r_len != dma_buffer2 - dma_buffer1) {
  11352         rv = BCM_E_INTERNAL;
  11353         LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: "
  11354             "App Data get Length mismatch\n")));
  11355         _BCM_OAM_UNLOCK(oc);
  11356         return (rv);
  11357     }
  11358 
  11359     /* Recover Group Data from UKENREL */
  11360     for (i=0; i<oc->group_count; i++) {
  11361         if (_GET_BIT_FLD(app_data_msg.group_bitmap, i)) {
  11362             rv = _bcm_fp_oam_cmm_group_regen(unit, i);
  11363             if (BCM_FAILURE(rv)) {
  11364                 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: "
  11365                       "Group Regen failed, Id:%d, %s\n"), i, bcm_errmsg(rv)));
  11366                 _BCM_OAM_UNLOCK(oc);
  11367                 return (rv);
  11368             }
  11369 
  11370             /* Now that we have reconstrcuted the group, Reconstrcut its 
  11371                LMEP & RMEPs */
  11372             group_ptr = &(oc->group_data[i].group_data);
  11373             if (group_ptr->lmep_id != _FP_OAM_INVALID_LMEP_ID) {
  11374 
  11375                 /* Get LMEP */
  11376                 rv = _bcm_fp_oam_cmm_mep_regen(unit, group_ptr->lmep_id);
  11377                 if (BCM_FAILURE(rv)) {
  11378                     LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: "
  11379                           "LMEP Regen failed, Id:%d, %s\n"), group_ptr->lmep_id,
  11380                           bcm_errmsg(rv)));
  11381                     _BCM_OAM_UNLOCK(oc);
  11382                     return (rv);
  11383                 }
  11384 
  11385                 /* Get RMEPs */
  11386                 for (j=0; j<oc->mep_count; j++) {
  11387                     if (_GET_BIT_FLD(group_ptr->rmep_bitmap, j)) {
  11388                         rv = _bcm_fp_oam_cmm_mep_regen(unit, j);
  11389                         if (BCM_FAILURE(rv)) {
  11390                             LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, 
  11391                                 "OAM Error: RMEP Regen failed Id:%d %s\n"), j,
  11392                                 bcm_errmsg(rv)));
  11393                             _BCM_OAM_UNLOCK(oc);
  11394                             return (rv);
  11395                         }
  11396                     }
  11397                 }
  11398             }
  11399         }
  11400     }
  11401 
  11402     _BCM_OAM_UNLOCK(oc);
  11403     return BCM_E_NONE;
  11404 }
  11405 
  11406 #endif /* INCLUDE_CCM */
  11407 /*******************************************************************************/
  11408 /* CCM Embedded App supporting functions End */
  11409 /*******************************************************************************/
  11410 
  11411 /*******************************************************************************/
  11412 /* MPLS LM/DM App specific routines start                                      */
  11413 /*******************************************************************************/
  11414 #if defined(INCLUDE_MPLS_LM_DM)
  11415 #if defined(BCM_WARM_BOOT_SUPPORT)
  11416 /*
  11417  * Function:
  11418  *     _bcm_fp_oam_mpls_lm_dm_scache_v0sync
  11419  * Purpose:
  11420  *     Sync MPLS LM/DM scache v0
  11421  * Parameters:
  11422  *     unit   - (IN) Device unit number
  11423  *     scache - (IN) Pointer to current scache location
  11424  * Returns:
  11425  *     BCM_E_XXX
  11426  */
  11427 STATIC int
  11428 _bcm_fp_oam_mpls_lm_dm_scache_v0_sync(int unit, uint8 *scache)
  11429 {
  11430     int                                            i;
  11431     uint16                                         idx;
  11432     _bcm_fp_oam_control_t                         *oc;
  11433     _bcm_fp_oam_mpls_lm_dm_ep_data_t              *ep;
  11434     _bcm_fp_oam_pm_profile_control_t              *pmc = NULL;
  11435     _bcm_fp_oam_mpls_lm_dm_scache_v0_global_data_t gdata;
  11436    _bcm_fp_oam_mpls_lm_dm_scache_v0_ep_data_t      ep_sync;
  11437 
  11438     /* Get handle to control structure. */
  11439     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
  11440 
  11441 
  11442     /* Sync global data to scache */
  11443     gdata.uc_num           = oc->mpls_lm_dm_uc_num;
  11444     gdata.ukernel_ready    = oc->mpls_lm_dm_ukernel_ready;
  11445     gdata.rx_channel       = oc->mpls_lm_dm_rx_channel;
  11446     gdata.max_ep_count     = oc->mpls_lm_dm_max_ep_count;
  11447     gdata.base_endpoint_id = oc->mpls_lm_dm_base_endpoint_id;
  11448 
  11449     sal_memcpy(scache, &gdata, sizeof(gdata));
  11450     scache += sizeof(gdata);
  11451 
  11452     /* Sync EP data to scache */
  11453     _MPLS_LM_DM_EP_ITER(ep, idx) {
  11454         ep_sync.in_use       = ep->in_use;
  11455         ep_sync.flags        = ep->flags;
  11456         ep_sync.type         = ep->type;
  11457         ep_sync.vccv_type    = ep->vccv_type;
  11458         ep_sync.gport        = ep->gport;
  11459         ep_sync.trunk_index  = ep->trunk_index;
  11460         ep_sync.outer_vlan   = ep->outer_vlan;
  11461         ep_sync.outer_tpid   = ep->outer_tpid;
  11462         ep_sync.outer_pri    = ep->outer_pri;
  11463         ep_sync.inner_vlan   = ep->inner_vlan;
  11464         ep_sync.inner_tpid   = ep->inner_tpid;
  11465         ep_sync.inner_pri    = ep->inner_pri;
  11466         ep_sync.egress_label = ep->egress_label;
  11467         ep_sync.intf_id      = ep->intf_id;
  11468         ep_sync.vpn          = ep->vpn;
  11469         ep_sync.lm_exp       = ep->lm_exp;
  11470         ep_sync.lm_int_pri   = ep->lm_int_pri;
  11471         ep_sync.dm_exp       = ep->dm_exp;
  11472         ep_sync.dm_int_pri   = ep->dm_int_pri;
  11473 
  11474         sal_memcpy(&(ep_sync.dst_mac), &(ep->dst_mac), sizeof(bcm_mac_t));
  11475         sal_memcpy(&(ep_sync.src_mac), &(ep->src_mac), sizeof(bcm_mac_t));
  11476 
  11477         for (i = 0; i < BCM_OAM_LM_COUNTER_MAX; i++) {
  11478             ep_sync.lm_ctr_base_id[i] = ep->lm_ctr_base_id[i];
  11479             ep_sync.lm_ctr_offset[i]  = ep->lm_ctr_offset[i];
  11480             ep_sync.lm_ctr_action[i]  = ep->lm_ctr_action[i];
  11481 
  11482             ep_sync.dm_ctr_base_id[i] = ep->dm_ctr_base_id[i];
  11483             ep_sync.dm_ctr_offset[i]  = ep->dm_ctr_offset[i];
  11484         }
  11485         ep_sync.lm_ctr_size         = ep->lm_ctr_size;
  11486         ep_sync.dm_ctr_size         = ep->dm_ctr_size;
  11487         ep_sync.session_id          = ep->session_id;
  11488         ep_sync.session_num_entries = ep->session_num_entries;
  11489         ep_sync.pm_profile          = ep->pm_profile;
  11490 
  11491         sal_memcpy(scache, &ep_sync, sizeof(ep_sync));
  11492         scache += sizeof(ep_sync);
  11493     }
  11494 
  11495     /* Store pm profile */
  11496     if (_BCM_FP_OAM_PM_MPLS_LM_DM_DATA_COLLECTION_MODE_IS_PROCESSED(oc)) {
  11497 
  11498         pmc = pm_profile_control[unit];
  11499         if (!pmc) {
  11500             return BCM_E_NOT_FOUND;
  11501         }
  11502 
  11503         for(i = 0; i < _BCM_OAM_MAX_PM_PROFILES; i++) {
  11504             sal_memcpy(scache, &(pmc->profile_info[i]),
  11505                        sizeof(_bcm_fp_oam_pm_profile_int_info_t));
  11506 
  11507             scache += sizeof(_bcm_fp_oam_pm_profile_int_info_t);
  11508         }
  11509     } else {
  11510         scache += _BCM_FP_OAM_PM_PROFILE_SCACHE_SIZE;
  11511     }
  11512     return BCM_E_NONE;
  11513 }
  11514 
  11515 /*
  11516  * Function:
  11517  *     _bcm_fp_oam_mpls_lm_dm_scache_v0_recover
  11518  * Purpose:
  11519  *     Recover MPLS LM/DM software state from scache v0
  11520  * Parameters:
  11521  *     unit   - (IN) Device unit number
  11522  *     scache - (IN) Pointer to current scache location
  11523  * Returns:
  11524  *     BCM_E_XXX
  11525  */
  11526 STATIC int
  11527 _bcm_fp_oam_mpls_lm_dm_scache_v0_recover(int unit, uint8 *scache)
  11528 {
  11529     int                                            i;
  11530     int                                            idx;
  11531     _bcm_fp_oam_control_t                         *oc;
  11532     _bcm_fp_oam_mpls_lm_dm_ep_data_t              *ep;
  11533     _bcm_fp_oam_mpls_lm_dm_scache_v0_ep_data_t     ep_scache;
  11534     _bcm_fp_oam_pm_profile_control_t              *pmc = NULL;
  11535     bcm_oam_endpoint_info_t                        ep_info;
  11536     int                                            sglp, dglp;
  11537     bcm_trunk_t                                    trunk_id = BCM_TRUNK_INVALID;
  11538     bcm_trunk_member_t                             trunk_member;
  11539     bcm_stat_object_t                              object;
  11540     uint32                                         pool;
  11541     uint32                                         offset_mode;
  11542     uint32                                         base_index;
  11543     bcm_stat_group_mode_t                          group_mode;
  11544 
  11545 
  11546 
  11547     /* Get handle to control structure. */
  11548     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
  11549 
  11550     /* Step over the global data, as these are either hardcoded or recovered
  11551      * from other sources for now (BTE, config file)
  11552      */
  11553     scache += sizeof(_bcm_fp_oam_mpls_lm_dm_scache_v0_global_data_t);
  11554 
  11555     /* Recover EP data from scache */
  11556     _MPLS_LM_DM_EP_ITER(ep, idx) {
  11557         sal_memcpy(&ep_scache, scache, sizeof(ep_scache));
  11558         scache += sizeof(ep_scache);
  11559 
  11560         ep->in_use       = ep_scache.in_use;
  11561         if (!ep->in_use) {
  11562             continue;
  11563         }
  11564 
  11565         ep->flags        = ep_scache.flags;
  11566         ep->type         = ep_scache.type;
  11567         ep->vccv_type    = ep_scache.vccv_type;
  11568         ep->gport        = ep_scache.gport;
  11569         ep->trunk_index  = ep_scache.trunk_index;
  11570         ep->outer_vlan   = ep_scache.outer_vlan;
  11571         ep->outer_tpid   = ep_scache.outer_tpid;
  11572         ep->outer_pri    = ep_scache.outer_pri;
  11573         ep->inner_vlan   = ep_scache.inner_vlan;
  11574         ep->inner_tpid   = ep_scache.inner_tpid;
  11575         ep->inner_pri    = ep_scache.inner_pri;
  11576         ep->egress_label = ep_scache.egress_label;
  11577         ep->intf_id      = ep_scache.intf_id;
  11578         ep->vpn          = ep_scache.vpn;
  11579         ep->lm_exp       = ep_scache.lm_exp;
  11580         ep->lm_int_pri   = ep_scache.lm_int_pri;
  11581         ep->dm_exp       = ep_scache.dm_exp;
  11582         ep->dm_int_pri   = ep_scache.dm_int_pri;
  11583 
  11584         sal_memcpy(&(ep->dst_mac), &(ep_scache.dst_mac), sizeof(bcm_mac_t));
  11585         sal_memcpy(&(ep->src_mac), &(ep_scache.src_mac), sizeof(bcm_mac_t));
  11586 
  11587         for (i = 0; i < BCM_OAM_LM_COUNTER_MAX; i++) {
  11588             ep->lm_ctr_base_id[i] = ep_scache.lm_ctr_base_id[i];
  11589             ep->lm_ctr_offset[i]  = ep_scache.lm_ctr_offset[i];
  11590             ep->lm_ctr_action[i]  = ep_scache.lm_ctr_action[i];
  11591 
  11592             ep->dm_ctr_base_id[i] = ep_scache.dm_ctr_base_id[i];
  11593             ep->dm_ctr_offset[i]  = ep_scache.dm_ctr_offset[i];
  11594         }
  11595         ep->lm_ctr_size         = ep_scache.lm_ctr_size;
  11596         ep->dm_ctr_size         = ep_scache.dm_ctr_size;
  11597         ep->session_id          = ep_scache.session_id;
  11598         ep->session_num_entries = ep_scache.session_num_entries;
  11599 
  11600         /* Reconstruct rest of the EP data using the recovered values */
  11601         ep->id = _MPLS_LM_DM_SESS_ID_TO_EP_ID(idx);
  11602 
  11603         _bcm_esw_stat_get_counter_id_info(unit, ep->session_id,
  11604                                           &group_mode, &object, &offset_mode,
  11605                                           &pool, &base_index);
  11606         ep->hw_base_session_id = _MPLS_LM_DM_HW_SESS_ID_GET(pool, base_index);
  11607 
  11608         bcm_oam_endpoint_info_t_init(&ep_info);
  11609         ep_info.type = ep->type;
  11610         ep_info.gport = ep->gport;
  11611         ep_info.trunk_index = ep->trunk_index;
  11612         BCM_IF_ERROR_RETURN(
  11613                _bcm_fp_oam_endpoint_gport_resolve(unit, &ep_info,
  11614                                                   &sglp, &dglp, &(ep->tx_gport),
  11615                                                   &trunk_id, &trunk_member));
  11616 
  11617         BCM_IF_ERROR_RETURN(shr_idxres_list_reserve(oc->mpls_lm_dm_pool,
  11618                                                     ep->id, ep->id));
  11619     }
  11620 
  11621 
  11622     if (_BCM_FP_OAM_PM_MPLS_LM_DM_DATA_COLLECTION_MODE_IS_PROCESSED(oc)) {
  11623 
  11624         pmc = pm_profile_control[unit];
  11625         if (!pmc) {
  11626             return BCM_E_INIT;
  11627         }
  11628 
  11629         for(i = 0; i < _BCM_OAM_MAX_PM_PROFILES; i++) {
  11630             sal_memcpy(&(pmc->profile_info[i]), scache,
  11631                        sizeof(_bcm_fp_oam_pm_profile_int_info_t));
  11632 
  11633             scache += sizeof(_bcm_fp_oam_pm_profile_int_info_t);
  11634         }
  11635     } else {
  11636         scache += _BCM_FP_OAM_PM_PROFILE_SCACHE_SIZE;
  11637     }
  11638 
  11639     return BCM_E_NONE;
  11640 }
  11641 
  11642 /*
  11643  * Function:
  11644  *       _bcm_fp_oam_mpls_lm_dm_scache_alloc
  11645  * Purpose:
  11646  *     Allocate scache memory for MPLS LM/DM module
  11647  * Parameters:
  11648  *     unit - (IN) BCM device number
  11649  * Returns:
  11650  *     BCM_E_XXX
  11651  */
  11652 STATIC int
  11653 _bcm_fp_oam_mpls_lm_dm_scache_alloc(int unit)
  11654 {
  11655     _bcm_fp_oam_control_t *oc;
  11656     soc_scache_handle_t    scache_handle;
  11657     uint8                 *scache;
  11658     int                    alloc_size = 0;
  11659     int                    rv = BCM_E_NONE;
  11660 
  11661     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
  11662     _BCM_OAM_LOCK(oc);
  11663 
  11664     /* MPLS LM/DM Scache V0 size */
  11665     alloc_size += _MPLS_LM_DM_SCACHE_V0_SIZE;
  11666 
  11667     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_OAM,
  11668                           bcmFpOamWbSequenceMplsLmDm);
  11669 
  11670     rv = _bcm_esw_scache_ptr_get(unit, scache_handle, 1, alloc_size,
  11671                                  &scache,
  11672                                  BCM_WB_MPLS_LM_DM_DEFAULT_VERSION, NULL);
  11673 
  11674     _BCM_OAM_UNLOCK(oc);
  11675     return rv;
  11676 }
  11677 
  11678 /*
  11679  * Function:
  11680  *     _bcm_fp_oam_mpls_lm_dm_sync
  11681  * Purpose:
  11682  *     Store MPLS LM/DM configuration to level two storage cache memory.
  11683  * Parameters:
  11684  *     unit - (IN) Device unit number
  11685  * Returns:
  11686  *     BCM_E_XXX
  11687  */
  11688 STATIC int
  11689 _bcm_fp_oam_mpls_lm_dm_sync(int unit)
  11690 {
  11691     int                     rv = BCM_E_NONE;
  11692     _bcm_fp_oam_control_t  *oc;
  11693     int                     stable_size;
  11694     soc_scache_handle_t     scache_handle;
  11695     uint8                  *scache = NULL;
  11696 
  11697     /* Get OAM module storage size. */
  11698     SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size));
  11699 
  11700     /* If level 2 store is not configured return from here. */
  11701     if (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit) || (stable_size == 0)) {
  11702         return BCM_E_NONE;
  11703     }
  11704 
  11705     /* Get handle to control structure. */
  11706     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
  11707     _BCM_OAM_LOCK(oc);
  11708 
  11709     if (!(oc->mpls_lm_dm_ukernel_ready)) {
  11710         goto cleanup;
  11711     }
  11712 
  11713     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_OAM,
  11714                           bcmFpOamWbSequenceMplsLmDm);
  11715 
  11716     rv = _bcm_esw_scache_ptr_get(unit, scache_handle, 0, 0, &scache,
  11717                                  BCM_WB_MPLS_LM_DM_DEFAULT_VERSION, NULL);
  11718 
  11719     if (BCM_FAILURE(rv)) {
  11720         goto cleanup;
  11721     }
  11722     if (NULL == scache) {
  11723         rv = BCM_E_INTERNAL;
  11724         goto cleanup;
  11725     }
  11726 
  11727     /* Sync MPLS LM/DM scache v0 */
  11728     rv = _bcm_fp_oam_mpls_lm_dm_scache_v0_sync(unit, scache);
  11729     if (BCM_FAILURE(rv)) {
  11730         goto cleanup;
  11731     }
  11732 
  11733  cleanup:
  11734     _BCM_OAM_UNLOCK(oc);
  11735     return rv;
  11736 }
  11737 
  11738 /*
  11739  * Function:
  11740  *     _bcm_fp_oam_mpls_lm_dm_wb_recover
  11741  * Purpose:
  11742  *     Recover MPLS LM/DM information from scache
  11743  * Parameters:
  11744  *     unit - (IN) Device unit number
  11745  * Returns:
  11746  *     BCM_E_XXX
  11747  */
  11748 STATIC int
  11749 _bcm_fp_oam_mpls_lm_dm_wb_recover(int unit)
  11750 {
  11751     int                 stable_size;       /* Secondary storage size.   */
  11752     uint8               *scache = NULL;
  11753     soc_scache_handle_t scache_handle;
  11754     _bcm_fp_oam_control_t  *oc;
  11755     int                 rv = BCM_E_NONE;
  11756     uint16              recovered_ver = 0;
  11757 
  11758     SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size));
  11759 
  11760     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
  11761     _BCM_OAM_LOCK(oc);
  11762 
  11763     if (!oc->mpls_lm_dm_ukernel_ready) {
  11764         goto cleanup;
  11765     }
  11766 
  11767     if (!SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit) && (stable_size > 0)) {
  11768 
  11769         SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_OAM,
  11770                               bcmFpOamWbSequenceMplsLmDm);
  11771 
  11772         rv = _bcm_esw_scache_ptr_get(unit, scache_handle, 0, 0,
  11773                                      &scache, BCM_WB_MPLS_LM_DM_DEFAULT_VERSION,
  11774                                      &recovered_ver);
  11775         if (BCM_E_NOT_FOUND == rv) {
  11776             /* Upgrading from SDK release that does not have warmboot state */
  11777             _bcm_fp_oam_mpls_lm_dm_scache_alloc(unit);
  11778             rv = BCM_E_NONE;
  11779             goto cleanup;
  11780         } else if (BCM_FAILURE(rv)) {
  11781             goto cleanup;
  11782         }
  11783 
  11784         if (NULL == scache) {
  11785             rv =  BCM_E_NOT_FOUND;
  11786             goto cleanup;
  11787         }
  11788     } else {
  11789         rv = BCM_E_NONE;
  11790         goto cleanup;
  11791     }
  11792 
  11793     rv = _bcm_fp_oam_mpls_lm_dm_scache_v0_recover(unit, scache);
  11794     if (BCM_FAILURE(rv)) {
  11795         goto cleanup;
  11796     }
  11797 
  11798  cleanup:
  11799     _BCM_OAM_UNLOCK(oc);
  11800     return rv;
  11801 }
  11802 #endif /* BCM_WARM_BOOT_SUPPORT */
  11803 
  11804 /*
  11805  * Function:
  11806  *     _bcm_fp_oam_mpls_lm_dm_init
  11807  * Purpose:
  11808  *     Initialize MPLS LM/DM app
  11809  * Parameters:
  11810  *     unit        - (IN) BCM device number
  11811  *     oc          - (IN) OAM control block
  11812  * Returns:
  11813  *      BCM_E_XXX
  11814  */
  11815 STATIC int
  11816 _bcm_fp_oam_mpls_lm_dm_init(uint8 unit, _bcm_fp_oam_control_t *oc)
  11817 {
  11818     int                            rv = BCM_E_NONE;
  11819     int                            uc = 0;
  11820     uint8                         *buffer, *buffer_ptr;
  11821     uint16                         buffer_len, reply_len;
  11822     uint16                         size;
  11823     mpls_lm_dm_sdk_msg_ctrl_init_t mpls_lm_dm_msg_init;
  11824     int                            uc_status;
  11825 
  11826     /*
  11827      * Start MPLS LM/DM application in BTE (Broadcom Task Engine) uController,
  11828      * Determine which uController is running MPLS LM/DM by choosing the first
  11829      * uC that returns successfully.
  11830      */
  11831     oc->mpls_lm_dm_ukernel_ready = 0;
  11832     for (uc = 0; uc < SOC_INFO(unit).num_ucs; uc++) {
  11833         rv = soc_uc_status(unit, uc, &uc_status);
  11834         if ((rv == SOC_E_NONE) && (uc_status != 0)) {
  11835             rv = soc_cmic_uc_appl_init(unit, uc, MOS_MSG_CLASS_MPLS_LM_DM,
  11836                                        _MPLS_LM_DM_UC_MSG_TIMEOUT_USECS,
  11837                                        MPLS_LM_DM_SDK_VERSION,
  11838                                        MPLS_LM_DM_UC_MIN_VERSION,
  11839                                        _bcm_oam_mpls_lm_dm_appl_callback, NULL);
  11840             if (SOC_E_NONE == rv) {
  11841                 /* MPLS_LM_DM started successfully */
  11842                 oc->mpls_lm_dm_uc_num = uc;
  11843                 break;
  11844             }
  11845         }
  11846     }
  11847 
  11848     if (uc >= SOC_INFO(unit).num_ucs) {
  11849         /* App not loaded return OK and skip rest of initialization */
  11850         return BCM_E_NONE;
  11851     }
  11852 
  11853     /*
  11854      * Assign RX DMA channel to CPU COS Queue
  11855      * (This is the RX channel to listen on for MPLS LM/DM packets).
  11856      *
  11857      * DMA channels (12) are assigned 4 per processor:
  11858      * (see /src/bcm/common/rx.c)
  11859      *   channels 0..3  --> PCI host
  11860      *   channels 4..7  --> uController 0
  11861      *   chnanels 8..11 --> uController 1
  11862      *
  11863      * The uControllers designate the 4 local DMA channels as follows:
  11864      *   local channel  0     --> TX
  11865      *   local channel  1..3  --> RX
  11866      *
  11867      * Each uController application needs to use a different
  11868      * RX DMA channel to listen on.
  11869      */
  11870     oc->mpls_lm_dm_rx_channel = (BCM_RX_CHANNELS *
  11871                                  (SOC_ARM_CMC(unit, oc->mpls_lm_dm_uc_num))) +
  11872                                  MPLS_LM_DM_RX_CHANNEL_UC_VIEW;
  11873 
  11874     if (soc_feature(unit, soc_feature_oam_pm)) {
  11875         oc->pm_mpls_lm_dm_data_collection_mode =
  11876                              soc_property_get(unit,
  11877                                               spn_MPLS_LMDM_DATA_COLLECTION_MODE,
  11878                                               _BCM_OAM_PM_COLLECTION_MODE_NONE);
  11879     }
  11880 
  11881     /*
  11882      * Allocate DMA buffers
  11883      * DMA buffer will be used to send and receive 'long' messages
  11884      * between SDK Host and uController (BTE).
  11885      */
  11886     oc->mpls_lm_dm_dma_buffer_len = sizeof(mpls_lm_dm_sdk_msg_ctrl_t);
  11887     if (_BCM_FP_OAM_PM_MPLS_LM_DM_DATA_COLLECTION_MODE_ENABLED(oc)) {
  11888         /* If PM is enabled, increase the size of the buffer if required */
  11889         if (sizeof(shr_oam_pm_msg_ctrl_t) > oc->mpls_lm_dm_dma_buffer_len) {
  11890             oc->mpls_lm_dm_dma_buffer_len = sizeof(shr_oam_pm_msg_ctrl_t);
  11891         }
  11892     }
  11893     oc->mpls_lm_dm_dma_buffer = soc_cm_salloc(unit,
  11894                                               oc->mpls_lm_dm_dma_buffer_len,
  11895                                               "MPLS_LM_DM DMA buffer");
  11896     if (!oc->mpls_lm_dm_dma_buffer) {
  11897         return (BCM_E_MEMORY);
  11898     }
  11899     sal_memset(oc->mpls_lm_dm_dma_buffer, 0, oc->mpls_lm_dm_dma_buffer_len);
  11900 
  11901     if (_BCM_FP_OAM_PM_MPLS_LM_DM_DATA_COLLECTION_MODE_IS_RAW_DATA(oc)) {
  11902         oc->mpls_lm_dm_max_ep_count = MPLS_LM_DM_MAX_RAW_DATA_SESSIONS;
  11903     } else {
  11904         oc->mpls_lm_dm_max_ep_count = MPLS_LM_DM_MAX_SESSIONS;
  11905     }
  11906 
  11907 #if defined(BCM_WARM_BOOT_SUPPORT)
  11908     if (!SOC_WARM_BOOT(unit)) {
  11909 #endif /* BCM_WARM_BOOT_SUPPORT */
  11910 
  11911         /* Send Initialize MPLS LM/DM App on UKERNEL */
  11912         /* Set control message data */
  11913         sal_memset(&mpls_lm_dm_msg_init, 0, sizeof(mpls_lm_dm_msg_init));
  11914         mpls_lm_dm_msg_init.num_sessions = oc->mpls_lm_dm_max_ep_count;
  11915         mpls_lm_dm_msg_init.rx_channel   = MPLS_LM_DM_RX_CHANNEL_UC_VIEW;
  11916 
  11917         if (_BCM_FP_OAM_PM_MPLS_LM_DM_DATA_COLLECTION_MODE_ENABLED(oc)) {
  11918             if (_BCM_FP_OAM_PM_MPLS_LM_DM_DATA_COLLECTION_MODE_IS_RAW_DATA(oc)) {
  11919                 mpls_lm_dm_msg_init.flags |= SHR_MPLS_LM_DM_PM_MODE_RAW;
  11920             } else {
  11921                 mpls_lm_dm_msg_init.flags |= SHR_MPLS_LM_DM_PM_MODE_STATS;
  11922             }
  11923         }
  11924 
  11925 
  11926         /* Pack control message data into DMA buffer */
  11927         buffer = oc->mpls_lm_dm_dma_buffer;
  11928         buffer_ptr = mpls_lm_dm_sdk_msg_ctrl_init_pack(buffer,
  11929                                                        &mpls_lm_dm_msg_init);
  11930         buffer_len = buffer_ptr - buffer;
  11931 
  11932         /* Send MPLS_LM_DM Init message to uC */
  11933         rv = _bcm_fp_oam_msg_send_receive(unit,
  11934                                           MOS_MSG_CLASS_MPLS_LM_DM,
  11935                                           MOS_MSG_SUBCLASS_MPLS_LM_DM_INIT,
  11936                                           buffer_len, 0,
  11937                                           MOS_MSG_SUBCLASS_MPLS_LM_DM_INIT_REPLY,
  11938                                           &reply_len);
  11939 
  11940         if (BCM_FAILURE(rv) || (reply_len != 0)) {
  11941             /* Could not start MPLS_LM_DM appl */
  11942             LOG_ERROR(BSL_LS_BCM_OAM,
  11943                       (BSL_META_U(unit,
  11944                                   "OAM(unit %d) Error: "
  11945                                   "MPLS LM DM Session alloc msg failed\n"), unit));
  11946             return rv;
  11947         }
  11948 #if defined(BCM_WARM_BOOT_SUPPORT)
  11949     }
  11950 #endif /* BCM_WARM_BOOT_SUPPORT */
  11951 
  11952     oc->mpls_lm_dm_ukernel_ready = 1;
  11953 
  11954     oc->mpls_lm_dm_base_endpoint_id  =
  11955                                 soc_property_get(unit,
  11956                                                  spn_MPLS_LM_DM_BASE_ENDPOINT_ID,
  11957                                                  768);
  11958 
  11959     /* Check if the endpoint id space tramples over other apps */
  11960 #if defined(INCLUDE_CCM)
  11961     if (soc_feature(unit, soc_feature_uc_ccm)) {
  11962         if (oc->ccm_ukernel_ready) {
  11963             /* Base endpoint Id for CCM is 0 */
  11964             if (oc->mep_count >= oc->mpls_lm_dm_base_endpoint_id) {
  11965                 return BCM_E_CONFIG;
  11966             }
  11967         }
  11968     }
  11969 #endif /* INCLUDE_CCM */
  11970 
  11971 #if defined(INCLUDE_BHH)
  11972     if (soc_feature(unit, soc_feature_bhh)) {
  11973         if (!oc->ukernel_not_ready) {
  11974             if (oc->mpls_lm_dm_base_endpoint_id <= oc->bhh_base_endpoint_id) {
  11975                 if ((oc->mpls_lm_dm_base_endpoint_id +
  11976                      oc->mpls_lm_dm_max_ep_count)
  11977                                              >= oc->bhh_base_endpoint_id) {
  11978                     return BCM_E_CONFIG;
  11979                 }
  11980             } else {
  11981                 if (oc->mpls_lm_dm_base_endpoint_id <=
  11982                            (oc->bhh_base_endpoint_id + oc->bhh_endpoint_count)) {
  11983                     return BCM_E_CONFIG;
  11984                 }
  11985             }
  11986         }
  11987     }
  11988 #endif /* INCLUDE_BHH */
  11989 
  11990     /* Create Session Pool */
  11991     rv = shr_idxres_list_create(&oc->mpls_lm_dm_pool,
  11992                                 oc->mpls_lm_dm_base_endpoint_id,
  11993                                 oc->mpls_lm_dm_base_endpoint_id +
  11994                                                        oc->mpls_lm_dm_max_ep_count,
  11995                                 oc->mpls_lm_dm_base_endpoint_id,
  11996                                 oc->mpls_lm_dm_base_endpoint_id +
  11997                                                        oc->mpls_lm_dm_max_ep_count,
  11998                                 "MPLS LM/DM pool");
  11999     if (BCM_FAILURE(rv)) {
  12000         return (rv);
  12001     }
  12002 
  12003     /* Allocate MPLS LM/DM EP data memory */
  12004     size = sizeof(_bcm_fp_oam_mpls_lm_dm_ep_data_t) * oc->mpls_lm_dm_max_ep_count;
  12005     _BCM_OAM_ALLOC(oc->mpls_lm_dm_ep_data,
  12006                    _bcm_fp_oam_mpls_lm_dm_ep_data_t,
  12007                    size, "MPLS LM/DM EP data");
  12008 
  12009     if (soc_feature(unit, soc_feature_oam_pm)) {
  12010         rv = _bcm_fp_oam_mpls_lm_dm_pm_init(unit);
  12011         if (BCM_FAILURE(rv)) {
  12012             return rv;
  12013         }
  12014     }
  12015 
  12016 
  12017 #if defined(BCM_WARM_BOOT_SUPPORT)
  12018     if (SOC_WARM_BOOT(unit)) {
  12019         rv = _bcm_fp_oam_mpls_lm_dm_wb_recover(unit);
  12020     } else {
  12021         rv = _bcm_fp_oam_mpls_lm_dm_scache_alloc(unit);
  12022     }
  12023 
  12024     if (rv == BCM_E_NOT_FOUND) {
  12025         /* Continue with initialization if scache not found */
  12026         rv = BCM_E_NONE;
  12027     }
  12028     if (BCM_FAILURE(rv)) {
  12029         return (rv);
  12030     }
  12031 #endif /* BCM_WARM_BOOT_SUPPORT */
  12032 
  12033     /*
  12034      * Start event message callback thread
  12035      */
  12036     if (_BCM_FP_OAM_PM_MPLS_LM_DM_DATA_COLLECTION_MODE_IS_RAW_DATA(oc)) {
  12037         if (oc->mpls_lm_dm_pm_event_thread_id == NULL) {
  12038             if ((oc->mpls_lm_dm_pm_event_thread_id =
  12039                  sal_thread_create("bcmMPLSLMDM", SAL_THREAD_STKSZ,
  12040                                    MPLS_LMDM_EVENT_THREAD_PRIORITY,
  12041                                    _bcm_fp_oam_mpls_lm_dm_pm_thread,
  12042                                    (void *)oc)) == SAL_THREAD_ERROR) {
  12043                 oc->mpls_lm_dm_pm_event_thread_id = NULL;
  12044                 return (BCM_E_MEMORY);
  12045             }
  12046         }
  12047     }
  12048 
  12049     return rv;
  12050 }
  12051 
  12052 /*
  12053  * Function:
  12054  *     _bcm_fp_oam_mpls_lm_dm_detach
  12055  * Purpose:
  12056  *     Uninitialize MPLS LM/DM app
  12057  * Parameters:
  12058  *     unit        - (IN) BCM device number
  12059  * Returns:
  12060  *      BCM_E_XXX
  12061  */
  12062 STATIC int
  12063 _bcm_fp_oam_mpls_lm_dm_detach(uint8 unit)
  12064 {
  12065     int                    rv = BCM_E_NONE;
  12066     _bcm_fp_oam_control_t *oc = NULL;
  12067     sal_usecs_t            timeout = sal_time_usecs() + 5000000;
  12068     uint16                 reply_len;
  12069     int                    uc_status;
  12070 
  12071     /* Get OAM Control Structure. */
  12072     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
  12073     _BCM_OAM_LOCK(oc);
  12074 
  12075     if (!oc->mpls_lm_dm_ukernel_ready) {
  12076         _BCM_OAM_UNLOCK(oc);
  12077         return BCM_E_NONE;
  12078     }
  12079 
  12080 
  12081     while (NULL !=  oc->mpls_lm_dm_pm_event_thread_id) {
  12082         soc_cmic_uc_msg_receive_cancel(unit, oc->mpls_lm_dm_uc_num,
  12083                                        MOS_MSG_CLASS_MPLS_LM_DM_EVENT);
  12084 
  12085         if (sal_time_usecs() < timeout) {
  12086             /*give some time to already running mpls_lm_dm callback thread
  12087              * to schedule and exit */
  12088             sal_usleep(10000);
  12089         } else {
  12090             /*timeout*/
  12091             LOG_ERROR(BSL_LS_BCM_OAM,
  12092                       (BSL_META_U(unit,
  12093                                   "MPLS_LM_DM event thread did not exit.\n")));
  12094             _BCM_OAM_UNLOCK(oc);
  12095             return BCM_E_INTERNAL;
  12096         }
  12097     }
  12098 
  12099     if (!SOC_WARM_BOOT(unit)) {
  12100         /* Send MPLS_LM_DM Uninit message to uC. Ignore error as uC could have
  12101          * died earlier.
  12102          */
  12103         SOC_IF_ERROR_RETURN(soc_uc_status(unit, oc->mpls_lm_dm_uc_num, &uc_status));
  12104         if (uc_status) {
  12105             rv = _bcm_fp_oam_msg_send_receive(unit,
  12106                                               MOS_MSG_CLASS_MPLS_LM_DM,
  12107                                               MOS_MSG_SUBCLASS_MPLS_LM_DM_UNINIT,
  12108                                               0, 0,
  12109                                               MOS_MSG_SUBCLASS_MPLS_LM_DM_UNINIT_REPLY,
  12110                                               &reply_len);
  12111             if (BCM_SUCCESS(rv) && (reply_len != 0)) {
  12112                 LOG_ERROR(BSL_LS_BCM_OAM,
  12113                          (BSL_META_U(unit,
  12114                                      "MPLS LM/DM UNINIT failed - reply_len %u\n"),
  12115                           reply_len));
  12116                 _BCM_OAM_UNLOCK(oc);
  12117                 return BCM_E_INTERNAL;
  12118             }
  12119             /* Ignore timeout/init error since that may indicate
  12120              * uKernel was reloaded/msging is not up.*/
  12121             if ((rv == BCM_E_TIMEOUT) || (rv == BCM_E_INIT)) {
  12122                  LOG_DEBUG(BSL_LS_BCM_OAM,
  12123                           (BSL_META_U(unit,
  12124                                       "MPLS LM/DM UNINIT failed - %s\n"),
  12125                            bcm_errmsg(rv)));
  12126                  rv = BCM_E_NONE;
  12127             }
  12128         }
  12129     }
  12130 
  12131     _BCM_OAM_UNLOCK(oc);
  12132     return rv;
  12133 }
  12134 
  12135 /*
  12136  * Function:
  12137  *     _bcm_fp_oam_mpls_lm_dm_endpoint_params_validate
  12138  * Purpose:
  12139  *     Validate MPLS LM/DM endpoint parameters
  12140  * Parameters:
  12141  *     unit           - (IN) BCM device number
  12142  *     endpoint_info  - (IN) Endpoint parameters
  12143  * Returns:
  12144  *      BCM_E_XXX
  12145  */
  12146 STATIC int
  12147 _bcm_fp_oam_mpls_lm_dm_endpoint_params_validate(uint8 unit,
  12148                                                 bcm_oam_endpoint_info_t *ep_info)
  12149 {
  12150     int                               rv = BCM_E_NONE;
  12151     _bcm_fp_oam_control_t            *oc;
  12152     _bcm_fp_oam_mpls_lm_dm_ep_data_t *ep;
  12153     uint32                            pool;
  12154     uint32                            offset_mode;
  12155     uint32                            base_index;
  12156     bcm_stat_object_t                 object;
  12157     bcm_stat_group_mode_t             group_mode;
  12158     bcm_stat_flex_direction_t         flex_direction;
  12159     uint16                            hw_base_session_id;
  12160     int16                             idx;
  12161 
  12162 
  12163     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
  12164     _BCM_OAM_LOCK(oc);
  12165 
  12166     if (!oc->mpls_lm_dm_ukernel_ready) {
  12167         LOG_ERROR(BSL_LS_BCM_OAM,
  12168                   (BSL_META_U(unit,
  12169                               "OAM(unit %d) Error: BTE not ready \n"), unit));
  12170         rv = BCM_E_INIT;
  12171         goto cleanup;
  12172     }
  12173 
  12174     if (ep_info->flags & BCM_OAM_ENDPOINT_WITH_ID) {
  12175 
  12176         /* Check if it is within the range for MPLS LM/DM */
  12177         if (!_MPLS_LM_DM_EP_ID_RANGE(ep_info->id)) {
  12178             LOG_ERROR(BSL_LS_BCM_OAM,
  12179                       (BSL_META_U(unit,
  12180                                   "OAM(unit %d) Error: Invalid id \n"), unit));
  12181             rv = BCM_E_PARAM;
  12182             goto cleanup;
  12183         }
  12184 
  12185         idx = _MPLS_LM_DM_EP_ID_TO_SESS_ID(ep_info->id);
  12186         ep = &(oc->mpls_lm_dm_ep_data[idx]);
  12187 
  12188         /* Check if id is already in use, unless it is a replace operation */
  12189         if (!(ep_info->flags & BCM_OAM_ENDPOINT_REPLACE)) {
  12190             if (ep->in_use) {
  12191                 LOG_ERROR(BSL_LS_BCM_OAM,
  12192                           (BSL_META_U(unit,
  12193                                       "OAM(unit %d) Error: EP in use\n"), unit));
  12194                 rv = BCM_E_PARAM;
  12195                 goto cleanup;
  12196             }
  12197         }
  12198     }
  12199 
  12200     if (ep_info->flags & BCM_OAM_ENDPOINT_REPLACE) {
  12201 
  12202         /* Check if it is within the range for MPLS LM/DM */
  12203         if (!_MPLS_LM_DM_EP_ID_RANGE(ep_info->id)) {
  12204             LOG_ERROR(BSL_LS_BCM_OAM,
  12205                       (BSL_META_U(unit,
  12206                                   "OAM(unit %d) Error: Invalid id \n"), unit));
  12207             rv = BCM_E_PARAM;
  12208             goto cleanup;
  12209         }
  12210 
  12211         ep = &(oc->mpls_lm_dm_ep_data[ep_info->id]);
  12212 
  12213         /* If it is a replace EP must already exist */
  12214         if (!ep->in_use) {
  12215             LOG_ERROR(BSL_LS_BCM_OAM,
  12216                       (BSL_META_U(unit,
  12217                                   "OAM(unit %d) Error: EP not in use\n"), unit));
  12218             rv = BCM_E_PARAM;
  12219             goto cleanup;
  12220         }
  12221     }
  12222 
  12223     /* Validate if the gport is an MPLS port for PW MEP */
  12224     if (ep_info->type == bcmOAMEndpointTypeMplsLmDmPw) {
  12225         if (-1 == BCM_GPORT_MPLS_PORT_ID_GET(ep_info->gport)) {
  12226             LOG_ERROR(BSL_LS_BCM_OAM,
  12227                       (BSL_META_U(unit,
  12228                                   "OAM(unit %d) Error: Invalid gport\n"), unit));
  12229             rv = BCM_E_PARAM;
  12230             goto cleanup;
  12231         }
  12232     }
  12233 
  12234     /* Interface validation check */
  12235     if(ep_info->type == bcmOAMEndpointTypeMplsLmDmLsp) {
  12236         if ((!BCM_XGS3_L3_EGRESS_IDX_VALID(unit, ep_info->intf_id)) &&
  12237             (!BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, ep_info->intf_id))) {
  12238             LOG_ERROR(BSL_LS_BCM_OAM,
  12239                       (BSL_META_U(unit,
  12240                                   "OAM(unit %d) Error: intf type not valid \n"),
  12241                        unit));
  12242             rv = BCM_E_PARAM;
  12243             goto cleanup;
  12244         }
  12245     }
  12246 
  12247     /* At least one session entry needs to be present per endpouint */
  12248     if (ep_info->session_num_entries == 0) {
  12249         LOG_ERROR(BSL_LS_BCM_OAM,
  12250                   (BSL_META_U(unit,
  12251                               "OAM(unit %d) Error: Invalid session entries \n"),
  12252                    unit));
  12253         rv = BCM_E_PARAM;
  12254         goto cleanup;
  12255     }
  12256 
  12257 
  12258     _bcm_esw_stat_get_counter_id_info(unit, ep_info->session_id,
  12259                                       &group_mode, &object, &offset_mode,
  12260                                       &pool, &base_index);
  12261 
  12262     rv = _bcm_esw_stat_validate_object(unit, object, &flex_direction);
  12263     if (rv != BCM_E_NONE) {
  12264         rv = BCM_E_PARAM;
  12265         LOG_ERROR(BSL_LS_BCM_OAM,
  12266                   (BSL_META_U(unit,
  12267                               "OAM(unit %d) Error: Invalid session id\n"),unit));
  12268         goto cleanup;
  12269     }
  12270 
  12271     rv = _bcm_esw_stat_validate_group(unit, group_mode);
  12272     if (rv != BCM_E_NONE) {
  12273         rv = BCM_E_PARAM;
  12274         LOG_ERROR(BSL_LS_BCM_OAM,
  12275                   (BSL_META_U(unit,
  12276                               "OAM(unit %d) Error: Invalid session id\n"),unit));
  12277         goto cleanup;
  12278     }
  12279 
  12280     if (flex_direction != bcmStatFlexDirectionIngress) {
  12281         rv = BCM_E_PARAM;
  12282         LOG_ERROR(BSL_LS_BCM_OAM,
  12283                   (BSL_META_U(unit,
  12284                               "OAM(unit %d) Error: Invalid session id\n"),unit));
  12285         goto cleanup;
  12286     }
  12287 
  12288     /* Check if the session id space for this endpoint is trampling on a
  12289      * different endpoint.
  12290      */
  12291     hw_base_session_id = _MPLS_LM_DM_HW_SESS_ID_GET(pool, base_index);
  12292     _MPLS_LM_DM_EP_ITER(ep, idx) {
  12293 
  12294         if (!ep->in_use) {
  12295             continue;
  12296         }
  12297 
  12298         if (ep_info->flags & BCM_OAM_ENDPOINT_REPLACE) {
  12299             if (idx == ep_info->id) {
  12300                 continue;
  12301             }
  12302         }
  12303 
  12304         if ((ep->hw_base_session_id <= hw_base_session_id) &&
  12305            ((ep->hw_base_session_id +
  12306                          ep->session_num_entries - 1) >= hw_base_session_id)) {
  12307             rv = BCM_E_PARAM;
  12308             LOG_ERROR(BSL_LS_BCM_OAM,
  12309                       (BSL_META_U(unit,
  12310                             "OAM(unit %d) Error: Invalid session id\n"),unit));
  12311             goto cleanup;
  12312         }
  12313 
  12314         if ((ep->hw_base_session_id <=
  12315                      (hw_base_session_id + ep_info->session_num_entries - 1))  &&
  12316            ((ep->hw_base_session_id + ep->session_num_entries - 1) >=
  12317                       (hw_base_session_id + ep_info->session_num_entries - 1))) {
  12318             rv = BCM_E_PARAM;
  12319             LOG_ERROR(BSL_LS_BCM_OAM,
  12320                       (BSL_META_U(unit,
  12321                             "OAM(unit %d) Error: Invalid session id\n"),unit));
  12322             goto cleanup;
  12323         }
  12324     }
  12325 
  12326     /* Only pkt counter is supported */
  12327     if (ep_info->lm_ctr_type != bcmOamLmCounterTypePkt) {
  12328         rv = BCM_E_UNAVAIL;
  12329         goto cleanup;
  12330     }
  12331 
  12332     /* Only 32bit counter is supported */
  12333     if (ep_info->lm_ctr_sample_size != bcmOamLmCounterSize32Bit) {
  12334         rv = BCM_E_UNAVAIL;
  12335         goto cleanup;
  12336     }
  12337 
  12338  cleanup:
  12339     _BCM_OAM_UNLOCK(oc);
  12340     return rv;
  12341 }
  12342 
  12343 /*
  12344  * Function:
  12345  *     _bcm_fp_oam_mpls_lm_dm_endpoint_create
  12346  * Purpose:
  12347  *     Create MPLS LM/DM endpoint
  12348  * Parameters:
  12349  *     unit           - (IN) BCM device number
  12350  *     endpoint_info  - (IN) Endpoint parameters
  12351  * Returns:
  12352  *      BCM_E_XXX
  12353  */
  12354 STATIC int
  12355 _bcm_fp_oam_mpls_lm_dm_endpoint_create(uint8 unit,
  12356                                        bcm_oam_endpoint_info_t *ep_info)
  12357 {
  12358     _bcm_fp_oam_control_t            *oc;
  12359     int                               rv = BCM_E_NONE;
  12360     _bcm_fp_oam_mpls_lm_dm_ep_data_t  ep;
  12361     bcm_stat_object_t                 object;
  12362     uint32                            pool;
  12363     uint32                            offset_mode;
  12364     uint32                            base_index;
  12365     bcm_stat_group_mode_t             group_mode;
  12366     bcm_port_t                        port;
  12367     uint16                            tpid;
  12368     bcm_oam_endpoint_t                id;
  12369     bcm_vlan_control_vlan_t           vc;
  12370     int                               sglp, dglp;
  12371     bcm_trunk_t                       trunk_id = BCM_TRUNK_INVALID;
  12372     bcm_trunk_member_t                trunk_member;
  12373     bcm_mpls_port_t                   mpls_port;
  12374     bcm_l3_egress_t                   l3_egress;
  12375     bcm_l3_intf_t                     l3_intf;
  12376     bcm_pbmp_t                        pbmp, ubmp;
  12377     int                               tpid_select;
  12378     uint16                            idx;
  12379 
  12380     rv = _bcm_fp_oam_mpls_lm_dm_endpoint_params_validate(unit, ep_info);
  12381     if (rv != BCM_E_NONE) {
  12382         return rv;
  12383     }
  12384 
  12385     sal_memset(&ep, 0, sizeof(ep));
  12386 
  12387     /* Copy parameters from user */
  12388     ep.in_use    = 1;
  12389     ep.type      = ep_info->type;
  12390     ep.vccv_type = ep_info->vccv_type;
  12391 
  12392     ep.gport       = ep_info->gport;
  12393     ep.trunk_index = ep_info->trunk_index;
  12394 
  12395     ep.intf_id      = ep_info->intf_id;
  12396     ep.vpn          = ep_info->vpn;
  12397     ep.egress_label = ep_info->egress_label.label;
  12398 
  12399     ep.session_id = ep_info->session_id;
  12400     ep.session_num_entries = ep_info->session_num_entries;
  12401     _bcm_esw_stat_get_counter_id_info(unit, ep_info->session_id,
  12402                                       &group_mode, &object, &offset_mode,
  12403                                       &pool, &base_index);
  12404     ep.hw_base_session_id = _MPLS_LM_DM_HW_SESS_ID_GET(pool, base_index);
  12405 
  12406 
  12407     BCM_IF_ERROR_RETURN(
  12408                    _bcm_fp_oam_endpoint_gport_resolve(unit, ep_info,
  12409                                                       &sglp, &dglp, &(ep.tx_gport),
  12410                                                       &trunk_id, &trunk_member));
  12411     port =  BCM_GPORT_MODPORT_PORT_GET(ep.tx_gport);
  12412     if (port == -1) {
  12413         return BCM_E_PORT;
  12414     }
  12415 
  12416     ep.outer_pri  = ep_info->pkt_pri;
  12417     ep.inner_pri  = ep_info->inner_pkt_pri;
  12418 
  12419     if (_MPLS_LM_DM_SECTION_ENDPOINT_TYPE(ep_info->type)) {
  12420         ep.outer_vlan = ep_info->vlan;
  12421         ep.outer_tpid = ep_info->outer_tpid;
  12422         ep.inner_vlan = ep_info->inner_vlan;
  12423         ep.inner_tpid = ep_info->inner_tpid;
  12424 
  12425         sal_memcpy(&(ep.dst_mac), &(ep_info->dst_mac_address), sizeof(bcm_mac_t));
  12426         sal_memcpy(&(ep.src_mac), &(ep_info->src_mac_address), sizeof(bcm_mac_t));
  12427 
  12428     } else {
  12429         /* Get L3 interfaces */
  12430         bcm_l3_egress_t_init(&l3_egress);
  12431         bcm_l3_intf_t_init(&l3_intf);
  12432 
  12433         if (ep_info->type == bcmOAMEndpointTypeMplsLmDmPw) {
  12434             /* For PW endpoints derive intf_id from DVP */
  12435             bcm_mpls_port_t_init(&mpls_port);
  12436             mpls_port.mpls_port_id = ep_info->gport;
  12437             BCM_IF_ERROR_RETURN(bcm_esw_mpls_port_get(unit, ep_info->vpn,
  12438                                                       &mpls_port));
  12439             ep.intf_id = mpls_port.egress_tunnel_if;
  12440         }
  12441         BCM_IF_ERROR_RETURN(bcm_esw_l3_egress_get(unit,
  12442                                                   ep.intf_id,
  12443                                                   &l3_egress));
  12444         l3_intf.l3a_intf_id = l3_egress.intf;
  12445         BCM_IF_ERROR_RETURN(bcm_esw_l3_intf_get(unit, &l3_intf));
  12446 
  12447         /* Get TPID */
  12448         BCM_IF_ERROR_RETURN(
  12449                         bcm_esw_vlan_control_port_get(unit,
  12450                                                       port,
  12451                                                       bcmVlanPortOuterTpidSelect,
  12452                                                       &tpid_select));
  12453         if (tpid_select == BCM_PORT_OUTER_TPID) {
  12454             BCM_IF_ERROR_RETURN(bcm_esw_port_tpid_get(unit, port, &tpid));
  12455         } else {
  12456             BCM_IF_ERROR_RETURN(bcm_esw_vlan_control_vlan_get(unit,
  12457                                                               l3_intf.l3a_vid,
  12458                                                               &vc));
  12459             tpid = vc.outer_tpid;
  12460         }
  12461 
  12462         sal_memcpy(ep.dst_mac, l3_egress.mac_addr, sizeof(bcm_mac_t));
  12463         sal_memcpy(ep.src_mac, l3_intf.l3a_mac_addr, sizeof(bcm_mac_t));
  12464 
  12465         ep.outer_tpid = tpid;
  12466         ep.outer_vlan = l3_intf.l3a_vid;
  12467 
  12468         BCM_IF_ERROR_RETURN(bcm_esw_vlan_port_get(unit,
  12469                                                   ep.outer_vlan,
  12470                                                   &pbmp,
  12471                                                   &ubmp));
  12472         if (BCM_PBMP_MEMBER(ubmp, port)) {
  12473             ep.outer_tpid = 0;  /* Set to 0 to indicate untagged */
  12474         }
  12475 
  12476         if (l3_intf.l3a_inner_vlan != 0) {
  12477             BCM_IF_ERROR_RETURN(bcm_esw_port_inner_tpid_get(unit, port, &tpid));
  12478             ep.inner_tpid = tpid;
  12479             ep.inner_vlan = l3_intf.l3a_inner_vlan;
  12480         }
  12481     }
  12482 
  12483     /* All validations completed, add the EP */
  12484     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
  12485     _BCM_OAM_LOCK(oc);
  12486 
  12487     if (ep_info->flags & BCM_OAM_ENDPOINT_WITH_ID) {
  12488 
  12489         if (!(ep_info->flags & BCM_OAM_ENDPOINT_REPLACE)) {
  12490             rv = shr_idxres_list_reserve(oc->mpls_lm_dm_pool,
  12491                                          ep_info->id, ep_info->id);
  12492         }
  12493         id = ep_info->id;
  12494     } else {
  12495         rv = shr_idxres_list_alloc(oc->mpls_lm_dm_pool,
  12496                                    (shr_idxres_element_t *)&id);
  12497     }
  12498 
  12499     if (BCM_FAILURE(rv)) {
  12500         rv = (rv == BCM_E_RESOURCE) ? (BCM_E_FULL) : rv;
  12501         LOG_ERROR(BSL_LS_BCM_OAM,
  12502                   (BSL_META_U(unit,
  12503                             "MPLS_LM_DM(unit %d) Error: Endpoint alloc failed - %s.\n"),
  12504                    unit, bcm_errmsg(rv)));
  12505         _BCM_OAM_UNLOCK(oc);
  12506         return rv;
  12507     }
  12508 
  12509     idx = _MPLS_LM_DM_EP_ID_TO_SESS_ID(id);
  12510     sal_memcpy(&(oc->mpls_lm_dm_ep_data[idx]), &ep, sizeof(ep));
  12511 
  12512     /* Set PM profile default value */
  12513     oc->mpls_lm_dm_ep_data[idx].pm_profile = _BCM_OAM_INVALID_INDEX;
  12514     oc->mpls_lm_dm_ep_data[idx].in_use = 1;
  12515 
  12516     _BCM_OAM_UNLOCK(oc);
  12517     return rv;
  12518 }
  12519 
  12520 /*
  12521  * Function:
  12522  *     _bcm_fp_oam_mpls_lm_dm_endpoint_get
  12523  * Purpose:
  12524  *     Create MPLS LM/DM endpoint
  12525  * Parameters:
  12526  *     unit           - (IN)  BCM device number
  12527  *     endpoint       - (IN)  Endpoint id
  12528  *     endpoint_info  - (OUT) Endpoint parameters
  12529  * Returns:
  12530  *      BCM_E_XXX
  12531  */
  12532 STATIC int
  12533 _bcm_fp_oam_mpls_lm_dm_endpoint_get(int unit, bcm_oam_endpoint_t id,
  12534                                     bcm_oam_endpoint_info_t *ep_info)
  12535 {
  12536     _bcm_fp_oam_control_t            *oc;
  12537     _bcm_fp_oam_mpls_lm_dm_ep_data_t *ep;
  12538     uint16                            idx;
  12539 
  12540 
  12541     if (NULL == ep_info) {
  12542         return BCM_E_PARAM;
  12543     }
  12544 
  12545     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
  12546 
  12547     if (!oc->mpls_lm_dm_ukernel_ready) {
  12548         LOG_ERROR(BSL_LS_BCM_OAM,
  12549                   (BSL_META_U(unit,
  12550                               "OAM(unit %d) Error: BTE not ready \n"), unit));
  12551         return BCM_E_INIT;
  12552     }
  12553 
  12554     idx = _MPLS_LM_DM_EP_ID_TO_SESS_ID(id);
  12555     ep = &(oc->mpls_lm_dm_ep_data[idx]);
  12556 
  12557     if (!ep->in_use) {
  12558         return BCM_E_NOT_FOUND;
  12559     }
  12560 
  12561     /* Copy params from EP data */
  12562     bcm_oam_endpoint_info_t_init(ep_info);
  12563     ep_info->id = id;
  12564     ep_info->type = ep->type;
  12565     ep_info->vccv_type = ep->vccv_type;
  12566 
  12567     ep_info->gport       = ep->gport;
  12568     ep_info->trunk_index = ep->trunk_index;
  12569 
  12570     ep_info->intf_id            = ep->intf_id;
  12571     ep_info->vpn                = ep->vpn;
  12572     ep_info->egress_label.label = ep->egress_label;
  12573 
  12574     ep_info->session_id          = ep->session_id;
  12575     ep_info->session_num_entries = ep->session_num_entries;
  12576 
  12577     ep_info->vlan       = ep->outer_vlan;
  12578     ep_info->outer_tpid = ep->outer_tpid;
  12579     ep_info->pkt_pri    = ep->outer_pri;
  12580 
  12581     ep_info->inner_vlan    = ep->inner_vlan;
  12582     ep_info->inner_tpid    = ep->inner_tpid;
  12583     ep_info->inner_pkt_pri = ep->inner_pri;
  12584 
  12585     sal_memcpy(&(ep_info->dst_mac_address), &(ep->dst_mac),  sizeof(bcm_mac_t));
  12586     sal_memcpy(&(ep_info->src_mac_address), &(ep->src_mac),  sizeof(bcm_mac_t));
  12587 
  12588     return BCM_E_NONE;
  12589 }
  12590 
  12591 /*
  12592  * Function:
  12593  *     _bcm_fp_oam_mpls_lm_dm_endpoint_destroy
  12594  * Purpose:
  12595  *     DEstroy MPLS LM/DM endpoint
  12596  * Parameters:
  12597  *     unit           - (IN)  BCM device number
  12598  *     endpoint       - (IN)  Endpoint id
  12599  * Returns:
  12600  *      BCM_E_XXX
  12601  */
  12602 STATIC int
  12603 _bcm_fp_oam_mpls_lm_dm_endpoint_destroy(int unit, bcm_oam_endpoint_t id)
  12604 {
  12605     _bcm_fp_oam_control_t            *oc;
  12606     _bcm_fp_oam_mpls_lm_dm_ep_data_t *ep;
  12607     uint16                            idx;
  12608     int                               rv = BCM_E_NONE;
  12609 
  12610 
  12611     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
  12612     _BCM_OAM_LOCK(oc);
  12613 
  12614     if (!oc->mpls_lm_dm_ukernel_ready) {
  12615         LOG_ERROR(BSL_LS_BCM_OAM,
  12616                   (BSL_META_U(unit,
  12617                               "OAM(unit %d) Error: BTE not ready \n"), unit));
  12618         _BCM_OAM_UNLOCK(oc);
  12619         return BCM_E_INIT;
  12620     }
  12621 
  12622     idx = _MPLS_LM_DM_EP_ID_TO_SESS_ID(id);
  12623     ep = &(oc->mpls_lm_dm_ep_data[idx]);
  12624 
  12625     if (!(ep->in_use)) {
  12626         _BCM_OAM_UNLOCK(oc);
  12627         return BCM_E_PARAM;
  12628     }
  12629 
  12630     if (ep->flags & SHR_MPLS_LM_DM_FLAG_DELAY_ADDED) {
  12631         rv = _bcm_fp_oam_mpls_lm_dm_delay_delete(unit, id);
  12632         if (BCM_FAILURE(rv)) {
  12633             _BCM_OAM_UNLOCK(oc);
  12634             return rv;
  12635         }
  12636     }
  12637 
  12638     if (ep->flags & SHR_MPLS_LM_DM_FLAG_LOSS_ADDED) {
  12639         rv = _bcm_fp_oam_mpls_lm_dm_loss_delete(unit, id);
  12640         if (BCM_FAILURE(rv)) {
  12641             _BCM_OAM_UNLOCK(oc);
  12642             return rv;
  12643         }
  12644     }
  12645 
  12646     /* Free the EP index */
  12647     rv = shr_idxres_list_free(oc->mpls_lm_dm_pool, id);
  12648     if (BCM_FAILURE(rv)) {
  12649         _BCM_OAM_UNLOCK(oc);
  12650         return rv;
  12651     }
  12652 
  12653     sal_memset(ep, 0, sizeof(*ep));
  12654 
  12655     _BCM_OAM_UNLOCK(oc);
  12656     return BCM_E_NONE;
  12657 }
  12658 
  12659 /*
  12660  * Function:
  12661  *      _bcm_fp_oam_mpls_lm_dm_period_validate
  12662  * Purpose:
  12663  *      Validate if the period passed by user is valid
  12664  * Parameters:
  12665  *      period    - (IN) period from user
  12666  *
  12667  * Returns:
  12668  *       BCM_E_NONE  - If the period is valid
  12669  *       BCM_E_PARAM - If the period is invalid
  12670  */
  12671 STATIC int
  12672 _bcm_fp_oam_mpls_lm_dm_period_validate(int period)
  12673 {
  12674     switch(period) {
  12675         case BCM_OAM_ENDPOINT_CCM_PERIOD_DISABLED:
  12676         case BCM_OAM_ENDPOINT_CCM_PERIOD_100MS:
  12677         case BCM_OAM_ENDPOINT_CCM_PERIOD_1S:
  12678         case BCM_OAM_ENDPOINT_CCM_PERIOD_10S:
  12679         case BCM_OAM_ENDPOINT_CCM_PERIOD_1M:
  12680         case BCM_OAM_ENDPOINT_CCM_PERIOD_10M:
  12681             return BCM_E_NONE;
  12682         default:
  12683             return BCM_E_PARAM;
  12684     }
  12685 }
  12686 
  12687 /*
  12688  * Function:
  12689  *      _bcm_fp_oam_mpls_lm_dm_encap_data_dump
  12690  * Purpose:
  12691  *      Dumps MPLS LM/DM encap
  12692  * Parameters:
  12693  *      encap_data      - (IN) Buffer containing MPLS_LM_DM encapsulation.
  12694  *      encap_length    - (IN) Length of the encap constructed
  12695  */
  12696 #if defined(MPLS_LM_DM_DEBUG)
  12697 STATIC void
  12698 _bcm_fp_oam_mpls_lm_dm_encap_data_dump(uint8 *encap_data, uint16 encap_length)
  12699 {
  12700     int i = 0;
  12701 
  12702     LOG_CLI((BSL_META("\nEncapsulation (length=%u):\n"), encap_length));
  12703     for (i = 0; i < encap_length; i++) {
  12704         if (i % 16 == 0) {
  12705             LOG_CLI((BSL_META("\n")));
  12706         }
  12707         LOG_CLI((BSL_META("%02x "), encap_data[i]));
  12708     }
  12709     LOG_CLI((BSL_META("\n")));
  12710 }
  12711 #endif /* MPLS_LM_DM_DEBUG */
  12712 
  12713 STATIC int
  12714 _bcm_fp_oam_mpls_lm_dm_label_get(uint32 label, uint8 exp, uint8 s,
  12715                                  uint8 ttl, _mpls_label_t *mpls_hdr)
  12716 {
  12717     sal_memset(mpls_hdr, 0, sizeof(*mpls_hdr));
  12718 
  12719     mpls_hdr->label = label;
  12720     mpls_hdr->exp   = exp;
  12721     mpls_hdr->s     = s;
  12722     if (ttl) {
  12723         mpls_hdr->ttl   = ttl;
  12724     } else {
  12725         mpls_hdr->ttl   = _MPLS_LM_DM_MPLS_DFLT_TTL;
  12726     }
  12727 
  12728     return (BCM_E_NONE);
  12729 }
  12730 
  12731 /*
  12732  * Function:
  12733  *      _bcm_fp_oam_mpls_lm_dm_lsp_labels_get
  12734  * Purpose:
  12735  *      Get the LSP label stack
  12736  * Parameters:
  12737  *      unit            - (IN)  Unit number.
  12738  *      ep              - (IN)  Endpoint params
  12739  *      max_labels      - (IN)  Max number of supported labels
  12740  *      label_stack     - (OUT) LSP label stack
  12741  *      label_count     - (OUT) Number of LSP labels
  12742  * Returns:
  12743  *      BCM_E_XXX
  12744  */
  12745 STATIC int
  12746 _bcm_fp_oam_mpls_lm_dm_lsp_labels_get(int unit,
  12747                                       _bcm_fp_oam_mpls_lm_dm_ep_data_t *ep,
  12748                                       int max_labels, _mpls_label_t *label_stack,
  12749                                       int *label_count)
  12750 {
  12751 
  12752     bcm_l3_egress_t         l3_egress;
  12753     bcm_l3_intf_t           l3_intf;
  12754     bcm_mpls_egress_label_t label_array[_MPLS_LM_DM_MPLS_MAX_LABELS];
  12755     int                     count = 0;
  12756     int                     i, j;
  12757     int                     egr_label_idx = 0;
  12758 
  12759     bcm_l3_egress_t_init(&l3_egress);
  12760     bcm_l3_intf_t_init(&l3_intf);
  12761 
  12762     BCM_IF_ERROR_RETURN(bcm_esw_l3_egress_get(unit,
  12763                                               ep->intf_id,
  12764                                               &l3_egress));
  12765 
  12766     BCM_IF_ERROR_RETURN(
  12767                    bcm_esw_mpls_tunnel_initiator_get(unit, l3_egress.intf,
  12768                                                      _MPLS_LM_DM_MPLS_MAX_LABELS,
  12769                                                      label_array,
  12770                                                      &count));
  12771     /* LSP endpoint specific */
  12772     if (ep->type == bcmOAMEndpointTypeMplsLmDmLsp) {
  12773         /* Add VRL if applicable */
  12774         if ((l3_egress.mpls_label != BCM_MPLS_LABEL_INVALID) &&
  12775             (count < _MPLS_LM_DM_MPLS_MAX_LABELS)) {
  12776             label_array[count - 1].label = l3_egress.mpls_label;
  12777             label_array[count - 1].exp   = l3_egress.mpls_exp;
  12778             label_array[count - 1].ttl   = l3_egress.mpls_ttl;
  12779             count++;
  12780         }
  12781 
  12782         /* Find label on which OAM is running */
  12783         for (i = 0; i < count; i++) {
  12784             if (label_array[i].label == ep->egress_label) {
  12785                 *label_count = count - i;
  12786                 egr_label_idx = i;
  12787                 break;
  12788             }
  12789         }
  12790         if (i >= count) {
  12791             /* Could not find a matching label */
  12792             return BCM_E_PARAM;
  12793         }
  12794         /* Remove all labels from BoS to egress_label */
  12795         for (i = egr_label_idx, j = 0; i < count; i++, j++) {
  12796             /* Copy labels */
  12797             label_array[j].label = label_array[i].label;
  12798             label_array[j].exp   = label_array[i].exp;
  12799             label_array[j].ttl   = label_array[i].ttl;
  12800         }
  12801     } else { /* PW endpoint */
  12802         *label_count = count;
  12803     }
  12804 
  12805     if ((*label_count) > max_labels) {
  12806         /* Too many labels */
  12807         return BCM_E_PARAM;
  12808     }
  12809 
  12810 
  12811     for (i = 0; i < (*label_count); i++) {
  12812         _bcm_fp_oam_mpls_lm_dm_label_get(label_array[i].label,
  12813                                          label_array[i].exp, 0,
  12814                                          label_array[i].ttl,
  12815                                          &(label_stack[i]));
  12816 
  12817     }
  12818     return BCM_E_NONE;
  12819 }
  12820 
  12821  /*
  12822  * Function:
  12823  *      _bcm_fp_oam_mpls_lm_dm_l2_hdr_pack
  12824  * Purpose:
  12825  *      Packs the L2 header
  12826  * Parameters:
  12827  *      unit            - (IN)  Unit number.
  12828  *      ep              - (IN)  Endpoint params
  12829  *      encap_data      - (OUT) Buffer returning MPLS_LM_DM encapsulation.
  12830  *      encap_length    - (OUT) Length of the encap constructed
  12831  * Returns:
  12832  *      BCM_E_XXX
  12833  */
  12834 STATIC void
  12835 _bcm_fp_oam_mpls_lm_dm_l2_hdr_pack(int unit,
  12836                                    _bcm_fp_oam_mpls_lm_dm_ep_data_t *ep,
  12837                                    uint8 *encap_data, uint16 *encap_length)
  12838 {
  12839     uint32     tmp;
  12840     int        i;
  12841     uint8     *cur_ptr = encap_data;
  12842 
  12843     for (i = 0; i < 6; i++) {
  12844         _SHR_PACK_U8(cur_ptr, ep->dst_mac[i]);
  12845     }
  12846 
  12847     for (i = 0; i < 6; i++) {
  12848         _SHR_PACK_U8(cur_ptr, ep->src_mac[i]);
  12849     }
  12850 
  12851     /* outer_tpid = 0 indicates no outer tag */
  12852     tmp = 0;
  12853     if (0 != ep->outer_tpid) {
  12854         tmp =  (ep->outer_tpid         << 16) |
  12855               ((ep->outer_pri  & 0x7)  << 13) |
  12856                (ep->outer_vlan & 0xfff);
  12857         _SHR_PACK_U32(cur_ptr, tmp);
  12858     }
  12859 
  12860     /* inner_tpid = 0 indicates no inner tag*/
  12861     tmp = 0;
  12862     if (0 != ep->inner_tpid) {
  12863         tmp =  (ep->inner_tpid         << 16) |
  12864               ((ep->inner_pri  & 0x7)  << 13) |
  12865                (ep->inner_vlan & 0xfff);
  12866         _SHR_PACK_U32(cur_ptr, tmp);
  12867     }
  12868 
  12869     _SHR_PACK_U16(cur_ptr, SHR_MPLS_LM_DM_L2_ETYPE_MPLS_UCAST);
  12870 
  12871     *encap_length = cur_ptr - encap_data;
  12872 
  12873 }
  12874 
  12875  /*
  12876  * Function:
  12877  *      _bcm_fp_oam_mpls_lm_dm_ach_header_pack
  12878  * Purpose:
  12879  *      Packs the ACH header.
  12880  * Parameters:
  12881  *      ach_header  - (IN)  ACH header
  12882  *      buffer      - (OUT) Buffer containing packed ACH
  12883  * Returns:
  12884  *      Incremented buffer pointer
  12885  */
  12886 STATIC uint8 *
  12887 _bcm_fp_oam_mpls_lm_dm_ach_header_pack(_ach_header_t *ach, uint8 *buffer)
  12888 {
  12889     uint32  tmp;
  12890 
  12891     tmp = ((ach->f_nibble & 0xf) << 28) |
  12892           ((ach->version & 0xf) << 24)  |
  12893            (ach->reserved << 16)        |
  12894             ach->channel_type;
  12895 
  12896     _SHR_PACK_U32(buffer, tmp);
  12897 
  12898     return (buffer);
  12899 }
  12900 
  12901  /*
  12902  * Function:
  12903  *      _bcm_fp_oam_mpls_lm_dm_label_pack
  12904  * Purpose:
  12905  *      Packs the MPLS label header.
  12906  * Parameters:
  12907  *      label     - (IN)  Label header
  12908  *      buffer    - (OUT) Buffer containing packed Label
  12909  * Returns:
  12910  *      Incremented buffer pointer
  12911  */
  12912 STATIC uint8 *
  12913 _bcm_fp_oam_mpls_lm_dm_mpls_label_pack(_mpls_label_t *label, uint8 *buffer)
  12914 {
  12915     uint32  tmp;
  12916 
  12917     tmp = ((label->label & 0xfffff) << 12) |
  12918           ((label->exp & 0x7) << 9)        |
  12919           ((label->s & 0x1) << 8)          |
  12920             label->ttl;
  12921     _SHR_PACK_U32(buffer, tmp);
  12922 
  12923     return (buffer);
  12924 }
  12925 
  12926  /*
  12927  * Function:
  12928  *      _bcm_fp_oam_mpls_lm_dm_mpls_hdr_build_pack
  12929  * Purpose:
  12930  *      Builds and packs the MPLS header
  12931  * Parameters:
  12932  *      unit            - (IN)  Unit number.
  12933  *      ep              - (IN)  Endpoint params
  12934  *      channel_type    - (IN)  ACH channel type used in the packet
  12935  *      oam_exp         - (IN)  EXP of the label running OAM
  12936  *      oam_ttl         - (IN)  TTL of the label running OAM
  12937  *      encap_data      - (OUT) Buffer returning MPLS_LM_DM encapsulation.
  12938  *      encap_length    - (OUT) Length of the encap constructed
  12939  * Returns:
  12940  *      BCM_E_XXX
  12941  * Notes:
  12942  *      The returning MPLS_LM_DM encapsulation includes only all the
  12943  *      encapsulation headers/labels and does not include
  12944  *      the MPLS_LM_DM control packet.
  12945  */
  12946 STATIC int
  12947 _bcm_fp_oam_mpls_lm_dm_mpls_hdr_build_pack(int unit,
  12948                                            _bcm_fp_oam_mpls_lm_dm_ep_data_t *ep,
  12949                                            uint32 channel_type,
  12950                                            uint8  oam_exp,
  12951                                            uint8 *encap_data,
  12952                                            uint16 *encap_length)
  12953 {
  12954     _mpls_label_t   label_stack[_MPLS_LM_DM_MPLS_MAX_LABELS];
  12955     _ach_header_t   ach;
  12956     uint32          packet_flags = 0;
  12957     int             label_count = 0;
  12958     int             lsp_label_count = 0;
  12959     int             oam_label_idx = -1;
  12960     uint8          *cur_ptr;
  12961     int             i;
  12962     bcm_mpls_port_t mpls_port;
  12963 
  12964 
  12965     /*
  12966      * Get MPLS_LM_DM encapsulation packet format flags
  12967      *
  12968      * Also, perform the following for each MPLS_LM_DM tunnel type:
  12969      * - Check for valid parameter values
  12970      * - Set specific values required by the MPLS_LM_DM tunnel definition 
  12971      *   (e.g. such as ttl=1,...)
  12972      */
  12973     switch (ep->type) {
  12974         case bcmOAMEndpointTypeMplsLmDmLsp:
  12975             packet_flags |= (_MPLS_LM_DM_ENCAP_PKT_GAL |
  12976                              _MPLS_LM_DM_ENCAP_PKT_MPLS_LSP);
  12977             break;
  12978 
  12979         case bcmOAMEndpointTypeMplsLmDmPw:
  12980             packet_flags |= (_MPLS_LM_DM_ENCAP_PKT_PW |
  12981                              _MPLS_LM_DM_ENCAP_PKT_MPLS_LSP);
  12982             switch(ep->vccv_type) {
  12983 
  12984                 case bcmOamBhhVccvChannelAch:
  12985                 case bcmOamBhhVccvTtl:
  12986                     break;
  12987 
  12988                 case bcmOamBhhVccvRouterAlert:
  12989                     packet_flags |= _MPLS_LM_DM_ENCAP_PKT_MPLS_ROUTER_ALERT;
  12990                     break;
  12991 
  12992                 case bcmOamBhhVccvGal13:
  12993                     packet_flags |= _MPLS_LM_DM_ENCAP_PKT_GAL;
  12994                     break;
  12995 
  12996                 default:
  12997                     return (BCM_E_PARAM);
  12998                     break;
  12999             }
  13000             break;
  13001 
  13002         case bcmOAMEndpointTypeMplsLmDmSectionPort:
  13003         case bcmOAMEndpointTypeMplsLmDmSectionInnervlan:
  13004         case bcmOAMEndpointTypeMplsLmDmSectionOuterVlan:
  13005         case bcmOAMEndpointTypeMplsLmDmSectionOuterPlusInnerVlan:
  13006             packet_flags |= _MPLS_LM_DM_ENCAP_PKT_GAL;
  13007             break;
  13008         default:
  13009             return (BCM_E_PARAM);
  13010     }
  13011 
  13012 
  13013     /*
  13014      * Get necessary headers/labels information.
  13015      *
  13016      * The order is important, as the encap is built in this order.
  13017      */
  13018     /* Construct ACH */
  13019     sal_memset(&ach, 0, sizeof(ach));
  13020     ach.f_nibble     = SHR_MPLS_LM_DM_ACH_FIRST_NIBBLE;
  13021     ach.version      = SHR_MPLS_LM_DM_ACH_VERSION;
  13022     ach.reserved     = 0;
  13023     ach.channel_type = channel_type;
  13024 
  13025     /* Construct GAL */
  13026     if (packet_flags & _MPLS_LM_DM_ENCAP_PKT_GAL) {
  13027         _bcm_fp_oam_mpls_lm_dm_label_get(SHR_MPLS_LM_DM_MPLS_GAL_LABEL,
  13028                                          0, 1, 1, &(label_stack[label_count]));
  13029         label_count++;
  13030     }
  13031 
  13032     /* Add PW label */
  13033     if (packet_flags & _MPLS_LM_DM_ENCAP_PKT_PW) {
  13034         bcm_mpls_port_t_init(&mpls_port);
  13035         mpls_port.mpls_port_id = ep->gport;
  13036         BCM_IF_ERROR_RETURN(bcm_esw_mpls_port_get(unit, ep->vpn, &mpls_port));
  13037 
  13038         if (ep->vccv_type == bcmOamBhhVccvTtl) {
  13039             mpls_port.egress_label.ttl = 0x1;
  13040         }
  13041 
  13042         _bcm_fp_oam_mpls_lm_dm_label_get(mpls_port.egress_label.label,
  13043                                          mpls_port.egress_label.exp, 0,
  13044                                          mpls_port.egress_label.ttl,
  13045                                          &(label_stack[label_count]));
  13046         oam_label_idx = label_count; /* OAM label is the PW label */
  13047         label_count++;
  13048     }
  13049 
  13050 
  13051     /* Construct RAL */
  13052     if (packet_flags & _MPLS_LM_DM_ENCAP_PKT_MPLS_ROUTER_ALERT) {
  13053         _bcm_fp_oam_mpls_lm_dm_label_get(SHR_MPLS_LM_DM_MPLS_ROUTER_ALERT_LABEL,
  13054                                          0, 0, 0, &(label_stack[label_count]));
  13055         label_count++;
  13056     }
  13057 
  13058     /* Add LSP labels */
  13059     if (packet_flags & _MPLS_LM_DM_ENCAP_PKT_MPLS_LSP) {
  13060         BCM_IF_ERROR_RETURN(
  13061            _bcm_fp_oam_mpls_lm_dm_lsp_labels_get(
  13062                                        unit, ep,
  13063                                        _MPLS_LM_DM_MPLS_MAX_LABELS - label_count,
  13064                                        &(label_stack[label_count]),
  13065                                        &lsp_label_count));
  13066 
  13067         /* Find the OAM label */
  13068         if (ep->type == bcmOAMEndpointTypeMplsLmDmLsp) {
  13069             oam_label_idx = label_count;
  13070         }
  13071         label_count += lsp_label_count;
  13072     }
  13073 
  13074     /* Set the EXP of OAM label to user specified value */
  13075     if ((ep->type == bcmOAMEndpointTypeMplsLmDmLsp) ||
  13076         (ep->type == bcmOAMEndpointTypeMplsLmDmPw)) {
  13077         label_stack[oam_label_idx].exp = oam_exp;
  13078     }
  13079 
  13080     label_stack[0].s = 1; /* Set BoS*/
  13081 
  13082     /* Pack the MPLS header in Network Byte Order */
  13083     cur_ptr = encap_data;
  13084     for (i = (label_count -1); i >= 0; i--) {
  13085         cur_ptr = _bcm_fp_oam_mpls_lm_dm_mpls_label_pack(&(label_stack[i]),
  13086                                                          cur_ptr);
  13087     }
  13088     cur_ptr = _bcm_fp_oam_mpls_lm_dm_ach_header_pack(&ach, cur_ptr);
  13089     *encap_length = cur_ptr - encap_data;
  13090 
  13091     return BCM_E_NONE;
  13092 }
  13093 
  13094 /*
  13095  * Function:
  13096  *      _bcm_fp_oam_mpls_lm_dm_encap_create
  13097  * Purpose:
  13098  *      Creates a MPLS_LM_DM packet encapsulation.
  13099  * Parameters:
  13100  *      unit            - (IN)  Unit number.
  13101  *      ep              - (IN)  Endpoint params
  13102  *      encap_data      - (OUT) Buffer returning MPLS_LM_DM encapsulation.
  13103  *      encap_length    - (OUT) Length of the encap constructed
  13104  *      ach             - (IN)  ACH of the packet
  13105  * Returns:
  13106  *      BCM_E_XXX
  13107  * Notes:
  13108  *      The returning MPLS_LM_DM encapsulation buffer includes all the
  13109  *      corresponding headers/labels EXCEPT for the MPLS_LM_DM control packet.
  13110  */
  13111 STATIC int
  13112 _bcm_fp_oam_mpls_lm_dm_encap_create(int unit,
  13113                                     _bcm_fp_oam_mpls_lm_dm_ep_data_t *ep,
  13114                                     uint8 *encap_data, uint16 *encap_length,
  13115                                     uint32 ach, uint8 oam_exp)
  13116 {
  13117     uint16 l2_encap_length, mpls_encap_length;
  13118 
  13119     /* Build and pack l2 header */
  13120     _bcm_fp_oam_mpls_lm_dm_l2_hdr_pack(unit, ep, encap_data, &l2_encap_length);
  13121 
  13122     /* Build and pack MPLS header */
  13123     BCM_IF_ERROR_RETURN(
  13124          _bcm_fp_oam_mpls_lm_dm_mpls_hdr_build_pack(unit, ep, ach, oam_exp,
  13125                                                     encap_data + l2_encap_length,
  13126                                                     &mpls_encap_length));
  13127 
  13128     *encap_length = l2_encap_length + mpls_encap_length;
  13129 
  13130 #if defined(MPLS_LM_DM_DEBUG)
  13131     _bcm_fp_oam_mpls_lm_dm_encap_data_dump(encap_data, *encap_length);
  13132 #endif /* MPLS_LM_DM_DEBUG */
  13133     return (BCM_E_NONE);
  13134 }
  13135 
  13136 /*
  13137  * Function:
  13138  *     _bcm_fp_oam_mpls_lm_dm_loss_add
  13139  * Purpose:
  13140  *     Create MPLS LM/DM Loss session
  13141  * Parameters:
  13142  *     unit    - (IN) BCM device number
  13143  *     loss_p  - (IN) Loss params
  13144  * Returns:
  13145  *      BCM_E_XXX
  13146  */
  13147 int
  13148 _bcm_fp_oam_mpls_lm_dm_loss_add(uint8 unit, bcm_oam_loss_t *loss_p)
  13149 {
  13150     _bcm_fp_oam_control_t              *oc = NULL;
  13151     uint8                               num_sample_action = 0;
  13152     mpls_lm_dm_sdk_msg_ctrl_loss_add_t  msg;
  13153     _bcm_fp_oam_mpls_lm_dm_ep_data_t   *ep;
  13154     uint32                              ach = 0;
  13155     uint32                              lm_int_flags = 0;
  13156     bcm_module_t                        my_modid = 0;
  13157     bcm_gport_t                         cpu_dglp;
  13158     soc_olp_l2_hdr_t                    olp_l2_hdr;
  13159     soc_olp_tx_hdr_t                    olp_oam_hdr;
  13160     uint8                              *buffer, *cur_ptr;
  13161     uint16                              buffer_len, reply_len;
  13162     uint32                              ctr_pool;
  13163     uint32                              ctr_mode;
  13164     uint32                              base_index;
  13165     bcm_stat_group_mode_t               ctr_group;
  13166     bcm_stat_object_t                   ctr_object;
  13167     uint16                              idx;
  13168     int                                 rv = BCM_E_NONE;
  13169     int                                 i;
  13170 
  13171 
  13172     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
  13173 
  13174     /* Validation checks */
  13175     if (!oc->mpls_lm_dm_ukernel_ready) {
  13176         return BCM_E_INIT;
  13177     }
  13178 
  13179     idx = _MPLS_LM_DM_EP_ID_TO_SESS_ID(loss_p->id);
  13180     ep = &(oc->mpls_lm_dm_ep_data[idx]);
  13181 
  13182     if (!ep->in_use) {
  13183         return BCM_E_PARAM;
  13184     }
  13185 
  13186     if (loss_p->lm_counter_size > BCM_OAM_LM_COUNTER_MAX) {
  13187         return BCM_E_PARAM;
  13188     }
  13189 
  13190     if ((loss_p->flags & BCM_OAM_COMBINED_LOSS_DELAY) &&
  13191        !(loss_p->flags & BCM_OAM_LOSS_SLM)) {
  13192         /* DLM + DM not supported */
  13193         return BCM_E_PARAM;
  13194     }
  13195 
  13196     /* ILM, only possible action is Increment */
  13197     if ((loss_p->flags & BCM_OAM_LOSS_SLM)) {
  13198         for(i = 0; i < loss_p->lm_counter_size; i++) {
  13199             if (loss_p->lm_counter_action[i] != bcmOamCounterActionIncrement) {
  13200                 return BCM_E_PARAM;
  13201             }
  13202         }
  13203     } else { /* DLM, exactly one sample action must be present */
  13204         for(i = 0; i < loss_p->lm_counter_size; i++) {
  13205             if (loss_p->lm_counter_action[i] == bcmOamCounterActionSample) {
  13206                 num_sample_action++;
  13207             }
  13208         }
  13209         if (num_sample_action != 1) {
  13210             return BCM_E_PARAM;
  13211         }
  13212     }
  13213 
  13214     if (ep->flags & SHR_MPLS_LM_DM_FLAG_DELAY_ADDED) {
  13215         if (loss_p->flags & BCM_OAM_COMBINED_LOSS_DELAY) {
  13216             if (!(ep->flags & SHR_MPLS_LM_DM_FLAG_PKT_TYPE_COMBINED)) {
  13217                 /* Delay created without COMBINED flag, reject loss add with
  13218                  * COMBINED flag
  13219                  */
  13220                 return BCM_E_PARAM;
  13221             }
  13222         } else {
  13223             if (ep->flags & SHR_MPLS_LM_DM_FLAG_PKT_TYPE_COMBINED) {
  13224                 /* Delay created with COMBINED flag, reject loss add without
  13225                  * COMBINED flag
  13226                  */
  13227                 return BCM_E_PARAM;
  13228             }
  13229         }
  13230     }
  13231 
  13232     /* Validate period */
  13233     BCM_IF_ERROR_RETURN(_bcm_fp_oam_mpls_lm_dm_period_validate(loss_p->period));
  13234 
  13235     /* Set internal flags */
  13236     if (loss_p->flags & BCM_OAM_COMBINED_LOSS_DELAY) {
  13237         lm_int_flags |= SHR_MPLS_LM_DM_FLAG_PKT_TYPE_COMBINED;
  13238         lm_int_flags |= SHR_MPLS_LM_DM_FLAG_PKT_TYPE_ILM_DM;
  13239         ach = SHR_MPLS_LM_DM_ACH_TYPE_ILM_DM;
  13240     } else if (loss_p->flags & BCM_OAM_LOSS_SLM) {
  13241         lm_int_flags |= SHR_MPLS_LM_DM_FLAG_PKT_TYPE_ILM;
  13242         ach = SHR_MPLS_LM_DM_ACH_TYPE_ILM;
  13243     } else {
  13244         lm_int_flags |= SHR_MPLS_LM_DM_FLAG_PKT_TYPE_DLM;
  13245         ach = SHR_MPLS_LM_DM_ACH_TYPE_DLM;
  13246     }
  13247 
  13248     /* Active or passive mode */
  13249     if (!(loss_p->flags & BCM_OAM_LOSS_TX_ENABLE)) {
  13250         lm_int_flags |= SHR_MPLS_LM_DM_PASSIVE_FLAG;
  13251     }
  13252 
  13253     /* Single or dual ended mode */
  13254     if (loss_p->flags & BCM_OAM_LOSS_SINGLE_ENDED) {
  13255         lm_int_flags |= SHR_MPLS_LM_DM_SINGLE_ENDED_FLAG;
  13256     }
  13257 
  13258     /* Copy user given values */
  13259     ep->lm_exp     = loss_p->pkt_pri;
  13260     ep->lm_int_pri = loss_p->int_pri;
  13261 
  13262 
  13263     for(i = 0; i < loss_p->lm_counter_size; i++) {
  13264         ep->lm_ctr_base_id[i] = loss_p->lm_counter_base_id[i];
  13265         ep->lm_ctr_offset[i]  = loss_p->lm_counter_offset[i];
  13266         ep->lm_ctr_action[i]  = loss_p->lm_counter_action[i];
  13267     }
  13268     ep->lm_ctr_size = loss_p->lm_counter_size;
  13269 
  13270     /* Construct the message */
  13271     sal_memset(&msg, 0, sizeof(msg));
  13272     msg.sess_id             = _MPLS_LM_DM_EP_ID_TO_SESS_ID(loss_p->id);
  13273     msg.flags               = lm_int_flags;
  13274     msg.period              = loss_p->period;
  13275     msg.session_id          = ep->hw_base_session_id;
  13276     msg.session_num_entries = ep->session_num_entries;
  13277 
  13278     /* Create packet encap */
  13279     BCM_IF_ERROR_RETURN(
  13280                       _bcm_fp_oam_mpls_lm_dm_encap_create(unit, ep,
  13281                                                           msg.l2_encap_data,
  13282                                                           &(msg.l2_encap_length),
  13283                                                           ach, ep->lm_exp));
  13284 
  13285     /* Create OLP encap */
  13286     BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_modid));
  13287     BCM_IF_ERROR_RETURN(_bcm_esw_glp_construct(unit, BCM_TRUNK_INVALID, my_modid,
  13288                                                CMIC_PORT(unit), &cpu_dglp));
  13289     BCM_IF_ERROR_RETURN(_bcm_olp_l2_hdr_get(unit, cpu_dglp, 0, &olp_l2_hdr));
  13290 
  13291     cur_ptr = _bcm_fp_oam_olp_l2_header_pack(msg.olp_encap_data, &olp_l2_hdr);
  13292 
  13293     /* Construct OLP OAM header */
  13294     sal_memset(&olp_oam_hdr, 0, sizeof(olp_oam_hdr));
  13295     SOC_OLP_TX_PORT(&olp_oam_hdr)  = BCM_GPORT_MODPORT_PORT_GET(ep->tx_gport);
  13296     SOC_OLP_TX_MODID(&olp_oam_hdr) = BCM_GPORT_MODPORT_MODID_GET(ep->tx_gport);
  13297 
  13298     /* Pack counter information in OLP header */
  13299     for (i=0; i< ep->lm_ctr_size; i++) {
  13300         _bcm_esw_stat_get_counter_id_info(unit, ep->lm_ctr_base_id[i],
  13301                                           &ctr_group, &ctr_object,
  13302                                           &ctr_mode, &ctr_pool,
  13303                                           &base_index);
  13304         if (i == 0) {
  13305             SOC_OLP_TX_CTR1_ID(&olp_oam_hdr) =
  13306                      SOC_OLP_TX_CTR(ctr_pool, base_index + ep->lm_ctr_offset[i]);
  13307             SOC_OLP_TX_CTR1_ACTION(&olp_oam_hdr) = ep->lm_ctr_action[i];
  13308             SOC_OLP_TX_CTR1_LOCATION(&olp_oam_hdr) = 1; /* Egress */
  13309 
  13310         } else if (i == 1) {
  13311             SOC_OLP_TX_CTR2_ID_SET(&olp_oam_hdr,
  13312                                    SOC_OLP_TX_CTR(ctr_pool,
  13313                                                   base_index +
  13314                                                      ep->lm_ctr_offset[i]));
  13315             SOC_OLP_TX_CTR2_ACTION(&olp_oam_hdr) = ep->lm_ctr_action[i];
  13316             SOC_OLP_TX_CTR2_LOCATION(&olp_oam_hdr) = 1; /* Egress */
  13317         } else if (i == 2) {
  13318             SOC_OLP_TX_CTR3_ID_SET(&olp_oam_hdr,
  13319                                    SOC_OLP_TX_CTR(ctr_pool,
  13320                                                   base_index +
  13321                                                      ep->lm_ctr_offset[i]));
  13322             SOC_OLP_TX_CTR3_ACTION(&olp_oam_hdr) = ep->lm_ctr_action[i];
  13323             SOC_OLP_TX_CTR3_LOCATION(&olp_oam_hdr) = 1; /* Egress */
  13324         }
  13325     }
  13326     SOC_OLP_TX_PRI(&olp_oam_hdr) = ep->lm_int_pri;
  13327 
  13328     /* Set generic repl. offset, BTE will adjust offset if it is LM+DM */
  13329     SOC_OLP_TX_OAM_OFFSET(&olp_oam_hdr) =
  13330                ((msg.l2_encap_length + _MPLS_LM_DM_OLP_REPL_OFFSET_DLM - 14) / 2);
  13331 
  13332     /* Pack OLP OAM Encap */
  13333     shr_olp_tx_header_pack(cur_ptr, &olp_oam_hdr);
  13334 
  13335 #if defined(MPLS_LM_DM_DEBUG)
  13336     _bcm_fp_oam_mpls_lm_dm_encap_data_dump(msg.olp_encap_data,
  13337                                            MPLS_LM_DM_OLP_HDR_LEN);
  13338 #endif /* MPLS_LM_DM_DEBUG */
  13339     /* Send Loss Add message */
  13340     buffer = oc->mpls_lm_dm_dma_buffer;
  13341     buffer_len = mpls_lm_dm_sdk_msg_ctrl_loss_add_pack(buffer, &msg) - buffer;
  13342 
  13343     rv = _bcm_fp_oam_msg_send_receive(unit,
  13344                           MOS_MSG_CLASS_MPLS_LM_DM,
  13345                           MOS_MSG_SUBCLASS_MPLS_LM_DM_LOSS_MEASUREMENT_ADD,
  13346                           buffer_len, 0,
  13347                           MOS_MSG_SUBCLASS_MPLS_LM_DM_LOSS_MEASUREMENT_ADD_REPLY,
  13348                           &reply_len);
  13349 
  13350     if ((BCM_SUCCESS(rv)) && (reply_len != 0)) {
  13351         rv =  BCM_E_INTERNAL;
  13352     }
  13353     if (BCM_FAILURE(rv)) {
  13354         return rv;
  13355     }
  13356 
  13357     ep->flags |= lm_int_flags;
  13358     ep->flags |= SHR_MPLS_LM_DM_FLAG_LOSS_ADDED;
  13359 
  13360     return rv;
  13361 }
  13362 
  13363 /*
  13364  * Function:
  13365  *     _bcm_fp_oam_mpls_lm_dm_loss_get
  13366  * Purpose:
  13367  *     Get MPLS LM/DM Loss session
  13368  * Parameters:
  13369  *     unit    - (IN) BCM device number
  13370  *     loss_p  - (IN) Loss params
  13371  * Returns:
  13372  *      BCM_E_XXX
  13373  */
  13374 int
  13375 _bcm_fp_oam_mpls_lm_dm_loss_get(uint8 unit, bcm_oam_loss_t *loss_p)
  13376 {
  13377     _bcm_fp_oam_control_t               *oc = NULL;
  13378     shr_mpls_lm_dm_msg_ctrl_loss_get_t   msg_req;
  13379     shr_mpls_lm_dm_msg_ctrl_loss_data_t  msg_rsp;
  13380     _bcm_fp_oam_mpls_lm_dm_ep_data_t    *ep;
  13381     uint8                               *buffer = NULL;
  13382     uint16                               req_len, rsp_len, reply_len;
  13383     uint16                               idx;
  13384     int                                  rv = 0;
  13385     int                                  i = 0;
  13386 
  13387     /* Get OAM control pointer */
  13388     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
  13389 
  13390     /* Validation checks */
  13391     if (!oc->mpls_lm_dm_ukernel_ready) {
  13392         return BCM_E_INIT;
  13393     }
  13394 
  13395     idx = _MPLS_LM_DM_EP_ID_TO_SESS_ID(loss_p->id);
  13396     ep = &(oc->mpls_lm_dm_ep_data[idx]);
  13397     if (!ep->in_use) {
  13398         return BCM_E_PARAM;
  13399     }
  13400 
  13401     /* Check if the LM is enabled for this EP */
  13402     if (!(ep->flags & SHR_MPLS_LM_DM_FLAG_LOSS_ADDED)) {
  13403         return BCM_E_NOT_FOUND;
  13404     }
  13405 
  13406     sal_memset(&msg_req, 0, sizeof(msg_req));
  13407     msg_req.sess_id = _MPLS_LM_DM_EP_ID_TO_SESS_ID(loss_p->id);
  13408 
  13409     buffer = oc->mpls_lm_dm_dma_buffer;
  13410     req_len = shr_mpls_lm_dm_msg_ctrl_loss_get_pack(buffer, &msg_req) - buffer;
  13411 
  13412     /* Send Loss GET request */
  13413     rv = _bcm_fp_oam_msg_send_receive(unit,
  13414                           MOS_MSG_CLASS_MPLS_LM_DM,
  13415                           MOS_MSG_SUBCLASS_MPLS_LM_DM_LOSS_MEASUREMENT_GET,
  13416                           req_len, 0,
  13417                           MOS_MSG_SUBCLASS_MPLS_LM_DM_LOSS_MEASUREMENT_GET_REPLY,
  13418                           &reply_len);
  13419 
  13420     if (BCM_FAILURE(rv)) {
  13421         LOG_ERROR(BSL_LS_BCM_OAM,
  13422                   (BSL_META_U(unit, "MPLS_LM_DM (unit %d) Error:"
  13423                               " Loss get Msg failed EP:%d %s.\n"),
  13424                    unit, loss_p->id, bcm_errmsg(rv)));
  13425         return rv;
  13426     }
  13427 
  13428     /* Initialize the receive Message structure */
  13429     sal_memset(&msg_rsp, 0, sizeof(msg_rsp));
  13430 
  13431     /* Unpack loss get data   */
  13432     buffer = oc->mpls_lm_dm_dma_buffer;
  13433     rsp_len = shr_mpls_lm_dm_msg_ctrl_loss_data_unpack(buffer, &msg_rsp) - buffer;
  13434 
  13435     if (reply_len != rsp_len) {
  13436         rv =  BCM_E_INTERNAL;
  13437     }
  13438 
  13439     /* Copy data from msg_rsp */
  13440     if (msg_rsp.flags & (SHR_MPLS_LM_DM_FLAG_PKT_TYPE_ILM_DM |
  13441                          SHR_MPLS_LM_DM_FLAG_PKT_TYPE_ILM )) {
  13442         loss_p->flags |= BCM_OAM_LOSS_SLM;
  13443     }
  13444 
  13445     if (!(msg_rsp.flags & SHR_MPLS_LM_DM_PASSIVE_FLAG)) {
  13446         loss_p->flags |= BCM_OAM_LOSS_TX_ENABLE;
  13447     }
  13448 
  13449     if (msg_rsp.flags & SHR_MPLS_LM_DM_SINGLE_ENDED_FLAG) {
  13450        loss_p->flags |= BCM_OAM_LOSS_SINGLE_ENDED;
  13451     }
  13452 
  13453     if (msg_rsp.flags & SHR_MPLS_LM_DM_FLAG_PKT_TYPE_COMBINED) {
  13454        loss_p->flags |= BCM_OAM_COMBINED_LOSS_DELAY;
  13455     }
  13456 
  13457     loss_p->period         = msg_rsp.period;
  13458     loss_p->rx_oam_packets = msg_rsp.rx_oam_packets;
  13459     loss_p->tx_oam_packets = msg_rsp.tx_oam_packets;
  13460     loss_p->loss_nearend   = msg_rsp.loss_nearend;
  13461     loss_p->loss_farend    = msg_rsp.loss_farend;
  13462     loss_p->tx_nearend     = msg_rsp.tx_nearend;
  13463     loss_p->rx_nearend     = msg_rsp.rx_nearend;
  13464     loss_p->tx_farend      = msg_rsp.tx_farend;
  13465     loss_p->rx_farend      = msg_rsp.rx_farend;
  13466 
  13467 
  13468     /* Copy data from local SW copy */
  13469     loss_p->int_pri = ep->lm_int_pri;
  13470     loss_p->pkt_pri = ep->lm_exp;
  13471 
  13472     loss_p->lm_counter_size = ep->lm_ctr_size;
  13473     for (i=0; i < ep->lm_ctr_size; i++) {
  13474         loss_p->lm_counter_base_id[i] = ep->lm_ctr_base_id[i];
  13475         loss_p->lm_counter_offset[i]  = ep->lm_ctr_offset[i];
  13476         loss_p->lm_counter_action[i]  = ep->lm_ctr_action[i];
  13477     }
  13478 
  13479     loss_p->pm_id = _MPLS_LM_DM_EP_ID_TO_SESS_ID(loss_p->id);;
  13480 
  13481     return rv;
  13482 }
  13483 
  13484 /*
  13485  * Function:
  13486  *     _bcm_fp_oam_mpls_lm_dm_loss_delete
  13487  * Purpose:
  13488  *     Deletes MPLS LM/DM Loss session
  13489  * Parameters:
  13490  *     unit    - (IN) BCM device number
  13491  *     loss_p  - (IN) Loss params
  13492  * Returns:
  13493  *      BCM_E_XXX
  13494  */
  13495 STATIC int
  13496 _bcm_fp_oam_mpls_lm_dm_loss_delete(int unit, bcm_oam_endpoint_t id)
  13497 {
  13498     _bcm_fp_oam_control_t                  *oc = NULL;
  13499     shr_mpls_lm_dm_msg_ctrl_loss_delete_t   msg;
  13500     _bcm_fp_oam_mpls_lm_dm_ep_data_t       *ep;
  13501     uint8                                  *buffer = NULL;
  13502     uint16                                  buffer_len, reply_len;
  13503     uint16                                  idx;
  13504     int                                     rv = BCM_E_NONE;
  13505     int                                     i  = 0;
  13506 
  13507     /* Get OAM control pointer */
  13508     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
  13509 
  13510     /* Validation checks */
  13511     if (!oc->mpls_lm_dm_ukernel_ready) {
  13512         return BCM_E_INIT;
  13513     }
  13514 
  13515     idx = _MPLS_LM_DM_EP_ID_TO_SESS_ID(id);
  13516     ep = &(oc->mpls_lm_dm_ep_data[idx]);
  13517     if (!ep->in_use) {
  13518         return BCM_E_PARAM;
  13519     }
  13520 
  13521     /* Check if the LM is enabled for this EP */
  13522     if (!(ep->flags & SHR_MPLS_LM_DM_FLAG_LOSS_ADDED)) {
  13523         return BCM_E_NOT_FOUND;
  13524     }
  13525 
  13526     /* Initialize the Message structure */
  13527     sal_memset(&msg, 0, sizeof(msg));
  13528     msg.sess_id = _MPLS_LM_DM_EP_ID_TO_SESS_ID(id);
  13529 
  13530     /* Send loss delete message */
  13531     buffer = oc->mpls_lm_dm_dma_buffer;
  13532     buffer_len = shr_mpls_lm_dm_msg_ctrl_loss_delete_pack(buffer, &msg) - buffer;
  13533 
  13534     rv = _bcm_fp_oam_msg_send_receive(unit,
  13535                        MOS_MSG_CLASS_MPLS_LM_DM,
  13536                        MOS_MSG_SUBCLASS_MPLS_LM_DM_LOSS_MEASUREMENT_DELETE,
  13537                        buffer_len, 0,
  13538                        MOS_MSG_SUBCLASS_MPLS_LM_DM_LOSS_MEASUREMENT_DELETE_REPLY,
  13539                        &reply_len);
  13540 
  13541     if ((BCM_SUCCESS(rv)) && (reply_len != 0)) {
  13542         rv =  BCM_E_INTERNAL;
  13543     }
  13544     if (BCM_FAILURE(rv)) {
  13545         return rv;
  13546     }
  13547 
  13548     /* Clear the loss data from EP data */
  13549     ep->flags &= ~(SHR_MPLS_LM_DM_FLAG_PKT_TYPE_DLM);
  13550     ep->flags &= ~(SHR_MPLS_LM_DM_FLAG_PKT_TYPE_ILM);
  13551     ep->flags &= ~(SHR_MPLS_LM_DM_FLAG_PKT_TYPE_ILM_DM);
  13552     ep->flags &= ~(SHR_MPLS_LM_DM_FLAG_LOSS_ADDED);
  13553 
  13554     if (!(ep->flags & SHR_MPLS_LM_DM_FLAG_DELAY_ADDED)) {
  13555         ep->flags &= ~(SHR_MPLS_LM_DM_FLAG_PKT_TYPE_COMBINED);
  13556     }
  13557 
  13558     ep->lm_exp     = 0;
  13559     ep->lm_int_pri = 0;
  13560     for (i = 0; i < ep->lm_ctr_size; i++) {
  13561         ep->lm_ctr_base_id[i] = 0;
  13562         ep->lm_ctr_offset[i]  = 0;
  13563         ep->lm_ctr_action[i]  = bcmOamCounterActionNone;
  13564     }
  13565     ep->lm_ctr_size = 0;
  13566 
  13567     return rv;
  13568 }
  13569 
  13570 /*
  13571  * Function:
  13572  *     _bcm_fp_oam_mpls_lm_dm_delay_add
  13573  * Purpose:
  13574  *     Create MPLS LM/DM Delay session
  13575  * Parameters:
  13576  *     unit    - (IN) BCM device number
  13577  *     delay_p - (IN) Delay params
  13578  * Returns:
  13579  *      BCM_E_XXX
  13580  */
  13581 int
  13582 _bcm_fp_oam_mpls_lm_dm_delay_add(uint8 unit, bcm_oam_delay_t *delay_p)
  13583 {
  13584     _bcm_fp_oam_control_t              *oc = NULL;
  13585     mpls_lm_dm_sdk_msg_ctrl_delay_add_t msg;
  13586     _bcm_fp_oam_mpls_lm_dm_ep_data_t   *ep;
  13587     uint32                              ach = 0;
  13588     uint32                              dm_int_flags = 0;
  13589     bcm_module_t                        my_modid = 0;
  13590     bcm_gport_t                         cpu_dglp;
  13591     soc_olp_l2_hdr_t                    olp_l2_hdr;
  13592     soc_olp_tx_hdr_t                    olp_oam_hdr;
  13593     uint8                              *buffer, *cur_ptr;
  13594     uint16                              buffer_len, reply_len;
  13595     uint32                              ctr_pool;
  13596     uint32                              ctr_mode;
  13597     uint32                              base_index;
  13598     bcm_stat_group_mode_t               ctr_group;
  13599     bcm_stat_object_t                   ctr_object;
  13600     uint16                              idx;
  13601     int                                 rv = BCM_E_NONE;
  13602     int                                 i;
  13603 
  13604 
  13605     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
  13606 
  13607     /* Validation checks */
  13608     if (!oc->mpls_lm_dm_ukernel_ready) {
  13609         return BCM_E_INIT;
  13610     }
  13611 
  13612     idx = _MPLS_LM_DM_EP_ID_TO_SESS_ID(delay_p->id);
  13613     ep = &(oc->mpls_lm_dm_ep_data[idx]);
  13614 
  13615     if (!ep->in_use) {
  13616         return BCM_E_PARAM;
  13617     }
  13618 
  13619     if (delay_p->dm_tx_update_lm_counter_size > BCM_OAM_LM_COUNTER_MAX) {
  13620         return BCM_E_PARAM;
  13621     }
  13622 
  13623     if (ep->flags & SHR_MPLS_LM_DM_FLAG_LOSS_ADDED) {
  13624         if (delay_p->flags & BCM_OAM_COMBINED_LOSS_DELAY) {
  13625             if (!(ep->flags & SHR_MPLS_LM_DM_FLAG_PKT_TYPE_COMBINED)) {
  13626                 /* Loss created without COMBINED flag, reject delay add with
  13627                  * COMBINED flag
  13628                  */
  13629                 return BCM_E_PARAM;
  13630             }
  13631         } else {
  13632             if (ep->flags & SHR_MPLS_LM_DM_FLAG_PKT_TYPE_COMBINED) {
  13633                 /* Loss created with COMBINED flag, reject delay add without
  13634                  * COMBINED flag
  13635                  */
  13636                 return BCM_E_PARAM;
  13637             }
  13638         }
  13639     }
  13640 
  13641     /* Validate period, for combined Loss/Delay period is taken from loss_add */
  13642     if (delay_p->flags & BCM_OAM_COMBINED_LOSS_DELAY) {
  13643         BCM_IF_ERROR_RETURN(
  13644                         _bcm_fp_oam_mpls_lm_dm_period_validate(delay_p->period));
  13645     }
  13646 
  13647     /* Set internal flags */
  13648     if (delay_p->flags & BCM_OAM_COMBINED_LOSS_DELAY) {
  13649         /* For combined loss, delay the common flags are derived from loss_add */
  13650         dm_int_flags |= SHR_MPLS_LM_DM_FLAG_PKT_TYPE_COMBINED;
  13651     } else {
  13652         ach = SHR_MPLS_LM_DM_ACH_TYPE_DM;
  13653 
  13654         dm_int_flags |= SHR_MPLS_LM_DM_FLAG_PKT_TYPE_DM;
  13655 
  13656         /* Active or passive mode */
  13657         if (!(delay_p->flags & BCM_OAM_DELAY_TX_ENABLE)) {
  13658             dm_int_flags |= SHR_MPLS_LM_DM_PASSIVE_FLAG;
  13659         }
  13660 
  13661         /* Single or dual ended mode */
  13662         if (!(delay_p->flags & BCM_OAM_DELAY_ONE_WAY)) {
  13663             dm_int_flags |= SHR_MPLS_LM_DM_SINGLE_ENDED_FLAG;
  13664         }
  13665     }
  13666 
  13667 
  13668     /* Copy user given values */
  13669     ep->dm_exp     = delay_p->pkt_pri;
  13670     ep->dm_int_pri = delay_p->int_pri;
  13671 
  13672     for(i = 0; i < delay_p->dm_tx_update_lm_counter_size; i++) {
  13673         ep->dm_ctr_base_id[i] = delay_p->dm_tx_update_lm_counter_base_id[i];
  13674         ep->dm_ctr_offset[i]  = delay_p->dm_tx_update_lm_counter_offset[i];
  13675     }
  13676     ep->dm_ctr_size = delay_p->dm_tx_update_lm_counter_size;
  13677 
  13678     /* Construct the message */
  13679     sal_memset(&msg, 0, sizeof(msg));
  13680     msg.flags     = dm_int_flags;
  13681     msg.sess_id   = _MPLS_LM_DM_EP_ID_TO_SESS_ID(delay_p->id);
  13682     msg.dm_format = delay_p->timestamp_format;
  13683 
  13684     /* In case of combined loss,delay the rest of the parameters are taken from
  13685      * loss_add
  13686      */
  13687     if (!(delay_p->flags & BCM_OAM_COMBINED_LOSS_DELAY)) {
  13688         msg.period              = delay_p->period;
  13689         msg.session_id          = ep->hw_base_session_id;
  13690         msg.session_num_entries = ep->session_num_entries;
  13691 
  13692         /* Create packet encap */
  13693         BCM_IF_ERROR_RETURN(
  13694                       _bcm_fp_oam_mpls_lm_dm_encap_create(unit, ep,
  13695                                                           msg.l2_encap_data,
  13696                                                           &(msg.l2_encap_length),
  13697                                                           ach, ep->dm_exp));
  13698         /* Create OLP encap */
  13699         BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_modid));
  13700         BCM_IF_ERROR_RETURN(_bcm_esw_glp_construct(unit, BCM_TRUNK_INVALID,
  13701                                                    my_modid, CMIC_PORT(unit),
  13702                                                    &cpu_dglp));
  13703         BCM_IF_ERROR_RETURN(_bcm_olp_l2_hdr_get(unit, cpu_dglp, 0, &olp_l2_hdr));
  13704 
  13705         cur_ptr = _bcm_fp_oam_olp_l2_header_pack(msg.olp_encap_data, &olp_l2_hdr);
  13706 
  13707         /* Construct OLP OAM header */
  13708         sal_memset(&olp_oam_hdr, 0, sizeof(olp_oam_hdr));
  13709         SOC_OLP_TX_PORT(&olp_oam_hdr) = BCM_GPORT_MODPORT_PORT_GET(ep->tx_gport);
  13710         SOC_OLP_TX_MODID(&olp_oam_hdr)= BCM_GPORT_MODPORT_MODID_GET(ep->tx_gport);
  13711 
  13712         /* Pack counter information in OLP header */
  13713 
  13714         for (i=0; i< ep->dm_ctr_size; i++) {
  13715             _bcm_esw_stat_get_counter_id_info(unit, ep->dm_ctr_base_id[i],
  13716                                               &ctr_group, &ctr_object,
  13717                                               &ctr_mode, &ctr_pool,
  13718                                               &base_index);
  13719             if (i == 0) {
  13720                 SOC_OLP_TX_CTR1_ID(&olp_oam_hdr) =
  13721                     SOC_OLP_TX_CTR(ctr_pool, base_index + ep->dm_ctr_offset[i]);
  13722                 SOC_OLP_TX_CTR1_ACTION(&olp_oam_hdr)   = 1; /* Increment */
  13723                 SOC_OLP_TX_CTR1_LOCATION(&olp_oam_hdr) = 1; /* Egress */
  13724 
  13725             }
  13726             if (i == 1) {
  13727                 SOC_OLP_TX_CTR2_ID_SET(&olp_oam_hdr,
  13728                                        SOC_OLP_TX_CTR(ctr_pool,
  13729                                                       base_index +
  13730                                                       ep->dm_ctr_offset[i]));
  13731                 SOC_OLP_TX_CTR2_ACTION(&olp_oam_hdr)   = 1; /* Increment */
  13732                 SOC_OLP_TX_CTR2_LOCATION(&olp_oam_hdr) = 1; /* Egress */
  13733             }
  13734             if (i == 2) {
  13735                 SOC_OLP_TX_CTR3_ID_SET(&olp_oam_hdr,
  13736                                        SOC_OLP_TX_CTR(ctr_pool,
  13737                                                       base_index +
  13738                                                       ep->dm_ctr_offset[i]));
  13739                 SOC_OLP_TX_CTR3_ACTION(&olp_oam_hdr)   = 1; /* Increment */
  13740                 SOC_OLP_TX_CTR3_LOCATION(&olp_oam_hdr) = 1; /* Egress */
  13741             }
  13742         }
  13743         SOC_OLP_TX_PRI(&olp_oam_hdr) = ep->dm_int_pri;
  13744 
  13745         /* Set Sample timestamp action */
  13746         SOC_OLP_TX_TIMESTAMP_ACTION(&olp_oam_hdr) =
  13747                          ((delay_p->timestamp_format == bcmOAMTimestampFormatNTP)
  13748                                                         ? 2:1);
  13749 
  13750         /* Timestamp replacement offset */
  13751         SOC_OLP_TX_OAM_OFFSET(&olp_oam_hdr) =
  13752             ((msg.l2_encap_length + _MPLS_LM_DM_OLP_REPL_OFFSET_DM - 14) / 2);
  13753 
  13754         /* Pack OLP OAM Encap */
  13755         shr_olp_tx_header_pack(cur_ptr, &olp_oam_hdr);
  13756     }
  13757 
  13758     /* Send Delay Add message */
  13759     buffer = oc->mpls_lm_dm_dma_buffer;
  13760     buffer_len = mpls_lm_dm_sdk_msg_ctrl_delay_add_pack(buffer, &msg) - buffer;
  13761 
  13762     rv = _bcm_fp_oam_msg_send_receive(unit,
  13763                          MOS_MSG_CLASS_MPLS_LM_DM,
  13764                          MOS_MSG_SUBCLASS_MPLS_LM_DM_DELAY_MEASUREMENT_ADD,
  13765                          buffer_len, 0,
  13766                          MOS_MSG_SUBCLASS_MPLS_LM_DM_DELAY_MEASUREMENT_ADD_REPLY,
  13767                          &reply_len);
  13768 
  13769     if ((BCM_SUCCESS(rv)) && (reply_len != 0)) {
  13770         rv =  BCM_E_INTERNAL;
  13771     }
  13772     if (BCM_FAILURE(rv)) {
  13773         return rv;
  13774     }
  13775 
  13776     ep->flags |= dm_int_flags;
  13777     ep->flags |= SHR_MPLS_LM_DM_FLAG_DELAY_ADDED;
  13778 
  13779     return rv;
  13780 }
  13781 
  13782 /*
  13783  * Function:
  13784  *     _bcm_fp_oam_mpls_lm_dm_delay_get
  13785  * Purpose:
  13786  *     Get MPLS LM/DM Delay session
  13787  * Parameters:
  13788  *     unit    - (IN) BCM device number
  13789  *     delay_p - (IN) Delay params
  13790  * Returns:
  13791  *      BCM_E_XXX
  13792  */
  13793 int
  13794 _bcm_fp_oam_mpls_lm_dm_delay_get(uint8 unit, bcm_oam_delay_t *delay_p)
  13795 {
  13796     _bcm_fp_oam_control_t               *oc;
  13797     _bcm_fp_oam_mpls_lm_dm_ep_data_t    *ep;
  13798     uint8                               *buffer;
  13799     uint16                               reply_len, req_len, rsp_len;
  13800     shr_mpls_lm_dm_msg_ctrl_delay_get_t  msg_req;
  13801     mpls_lm_dm_sdk_msg_ctrl_delay_data_t msg_rsp;
  13802     uint16                               idx;
  13803     int                                  rv = BCM_E_NONE;
  13804     int                                  i;
  13805 
  13806     /* Get OAM control pointer */
  13807     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
  13808 
  13809     /* Validation checks */
  13810     if (!oc->mpls_lm_dm_ukernel_ready) {
  13811         return BCM_E_INIT;
  13812     }
  13813 
  13814     idx = _MPLS_LM_DM_EP_ID_TO_SESS_ID(delay_p->id);
  13815     ep = &(oc->mpls_lm_dm_ep_data[idx]);
  13816     if (!ep->in_use) {
  13817         return BCM_E_PARAM;
  13818     }
  13819 
  13820     /* Check if DM is enabled for this EP */
  13821     if (!(ep->flags & SHR_MPLS_LM_DM_FLAG_DELAY_ADDED)) {
  13822         return BCM_E_NOT_FOUND;
  13823     }
  13824 
  13825     sal_memset(&msg_req, 0, sizeof(msg_req));
  13826     msg_req.sess_id = _MPLS_LM_DM_EP_ID_TO_SESS_ID(delay_p->id);
  13827 
  13828     buffer = oc->mpls_lm_dm_dma_buffer;
  13829     req_len = shr_mpls_lm_dm_msg_ctrl_delay_get_pack(buffer, &msg_req) - buffer;
  13830 
  13831     /* Send Delay get request */
  13832     rv = _bcm_fp_oam_msg_send_receive(unit,
  13833                          MOS_MSG_CLASS_MPLS_LM_DM,
  13834                          MOS_MSG_SUBCLASS_MPLS_LM_DM_DELAY_MEASUREMENT_GET,
  13835                          req_len, 0,
  13836                          MOS_MSG_SUBCLASS_MPLS_LM_DM_DELAY_MEASUREMENT_GET_REPLY,
  13837                          &reply_len);
  13838 
  13839     if (BCM_FAILURE(rv)) {
  13840         LOG_ERROR(BSL_LS_BCM_OAM,
  13841                   (BSL_META_U(unit, "MPLS_LM_DM (unit %d) Error:"
  13842                               " Delay get Msg failed EP:%d %s.\n"),
  13843                    unit, delay_p->id, bcm_errmsg(rv)));
  13844         return rv;
  13845     }
  13846 
  13847     /* Initialize the receive Message structure */
  13848     sal_memset(&msg_rsp, 0, sizeof(msg_rsp));
  13849 
  13850     /* Unpack loss get data   */
  13851     buffer = oc->mpls_lm_dm_dma_buffer;
  13852     rsp_len = mpls_lm_dm_sdk_msg_ctrl_delay_data_unpack(buffer, &msg_rsp) - buffer;
  13853 
  13854     if (reply_len != rsp_len) {
  13855         return BCM_E_INTERNAL;
  13856     }
  13857 
  13858     if (msg_rsp.flags & SHR_MPLS_LM_DM_FLAG_PKT_TYPE_COMBINED) {
  13859         delay_p->flags |= BCM_OAM_COMBINED_LOSS_DELAY;
  13860     } else {
  13861         if (!(msg_rsp.flags & SHR_MPLS_LM_DM_PASSIVE_FLAG)) {
  13862             delay_p->flags |= BCM_OAM_DELAY_TX_ENABLE;
  13863         }
  13864         if (!(msg_rsp.flags & SHR_MPLS_LM_DM_SINGLE_ENDED_FLAG)) {
  13865             delay_p->flags |= BCM_OAM_DELAY_ONE_WAY;
  13866         }
  13867     }
  13868 
  13869     delay_p->period = msg_rsp.period;
  13870     delay_p->timestamp_format = msg_rsp.dm_format;
  13871     rv = bcm_fp_oam_convert_ep_to_time_spec(&(delay_p->delay),
  13872                                             msg_rsp.delay_seconds,
  13873                                             msg_rsp.delay_nanoseconds);
  13874     if (BCM_SUCCESS(rv)) {
  13875         rv = bcm_fp_oam_convert_ep_to_time_spec(&(delay_p->txf),
  13876                                                 msg_rsp.txf_seconds,
  13877                                                 msg_rsp.txf_nanoseconds);
  13878     }
  13879     if (BCM_SUCCESS(rv)) {
  13880         rv = bcm_fp_oam_convert_ep_to_time_spec(&(delay_p->rxf),
  13881                                                 msg_rsp.rxf_seconds,
  13882                                                 msg_rsp.rxf_nanoseconds);
  13883     }
  13884     if (BCM_SUCCESS(rv)) {
  13885         rv = bcm_fp_oam_convert_ep_to_time_spec(&(delay_p->txb),
  13886                                                 msg_rsp.txb_seconds,
  13887                                                 msg_rsp.txb_nanoseconds);
  13888     }
  13889     if (BCM_SUCCESS(rv)) {
  13890         rv = bcm_fp_oam_convert_ep_to_time_spec(&(delay_p->rxb),
  13891                                                 msg_rsp.rxb_seconds,
  13892                                                 msg_rsp.rxb_nanoseconds);
  13893     }
  13894     if (BCM_FAILURE(rv)) {
  13895         return rv;
  13896     }
  13897 
  13898     delay_p->rx_oam_packets = msg_rsp.rx_oam_packets;
  13899     delay_p->tx_oam_packets = msg_rsp.tx_oam_packets;
  13900 
  13901     /* Copy data from local SW copy */
  13902     delay_p->int_pri = ep->dm_int_pri;
  13903     delay_p->pkt_pri = ep->dm_exp;
  13904 
  13905     delay_p->dm_tx_update_lm_counter_size = ep->dm_ctr_size;
  13906     for (i=0; i < ep->dm_ctr_size; i++) {
  13907         delay_p->dm_tx_update_lm_counter_base_id[i] = ep->dm_ctr_base_id[i];
  13908         delay_p->dm_tx_update_lm_counter_offset[i]  = ep->dm_ctr_offset[i];
  13909     }
  13910 
  13911     delay_p->pm_id = _MPLS_LM_DM_EP_ID_TO_SESS_ID(delay_p->id);
  13912 
  13913     return rv;
  13914 }
  13915 
  13916 /*
  13917  * Function:
  13918  *     _bcm_fp_oam_mpls_lm_dm_delay_delete
  13919  * Purpose:
  13920  *     Delete MPLS LM/DM Delay session
  13921  * Parameters:
  13922  *     unit    - (IN) BCM device number
  13923  *     delay_p - (IN) Delay params
  13924  * Returns:
  13925  *      BCM_E_XXX
  13926  */
  13927 STATIC int
  13928 _bcm_fp_oam_mpls_lm_dm_delay_delete(int unit, bcm_oam_endpoint_t id)
  13929 {
  13930     _bcm_fp_oam_control_t                  *oc = NULL;
  13931     shr_mpls_lm_dm_msg_ctrl_delay_delete_t  msg;
  13932     _bcm_fp_oam_mpls_lm_dm_ep_data_t       *ep;
  13933     uint8                                  *buffer = NULL;
  13934     uint16                                  buffer_len, reply_len;
  13935     uint16                                  idx;
  13936     int                                     rv = BCM_E_NONE;
  13937     int                                     i = 0;
  13938 
  13939     /* Get OAM control pointer */
  13940     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
  13941 
  13942     /* Validation checks */
  13943     if (!oc->mpls_lm_dm_ukernel_ready) {
  13944         return BCM_E_INIT;
  13945     }
  13946 
  13947     idx = _MPLS_LM_DM_EP_ID_TO_SESS_ID(id);
  13948     ep = &(oc->mpls_lm_dm_ep_data[idx]);
  13949     if (!ep->in_use) {
  13950         return BCM_E_PARAM;
  13951     }
  13952 
  13953     /* Check if DM is enabled for this EP */
  13954     if (!(ep->flags & SHR_MPLS_LM_DM_FLAG_DELAY_ADDED)) {
  13955         return BCM_E_NOT_FOUND;
  13956     }
  13957 
  13958     /* Initialize the Message structure */
  13959     sal_memset(&msg, 0, sizeof(msg));
  13960     msg.sess_id = _MPLS_LM_DM_EP_ID_TO_SESS_ID(id);
  13961 
  13962     /* Send delay delete message */
  13963     buffer = oc->mpls_lm_dm_dma_buffer;
  13964     buffer_len = shr_mpls_lm_dm_msg_ctrl_delay_delete_pack(buffer, &msg) - buffer;
  13965 
  13966     rv = _bcm_fp_oam_msg_send_receive(unit,
  13967                       MOS_MSG_CLASS_MPLS_LM_DM,
  13968                       MOS_MSG_SUBCLASS_MPLS_LM_DM_DELAY_MEASUREMENT_DELETE,
  13969                       buffer_len, 0,
  13970                       MOS_MSG_SUBCLASS_MPLS_LM_DM_DELAY_MEASUREMENT_DELETE_REPLY,
  13971                       &reply_len);
  13972 
  13973     if ((BCM_SUCCESS(rv)) && (reply_len != 0)) {
  13974         rv =  BCM_E_INTERNAL;
  13975     }
  13976     if (BCM_FAILURE(rv)) {
  13977         return rv;
  13978     }
  13979 
  13980     /* Clear the delay data from EP data */
  13981     ep->flags &= ~(SHR_MPLS_LM_DM_FLAG_PKT_TYPE_DM);
  13982     ep->flags &= ~(SHR_MPLS_LM_DM_FLAG_DELAY_ADDED);
  13983 
  13984     if (!(ep->flags & SHR_MPLS_LM_DM_FLAG_LOSS_ADDED)) {
  13985         ep->flags &= ~(SHR_MPLS_LM_DM_FLAG_PKT_TYPE_COMBINED);
  13986     }
  13987 
  13988     ep->dm_int_pri = 0;
  13989     for (i = 0; i < ep->dm_ctr_size; i++) {
  13990         ep->dm_ctr_base_id[i] = 0;
  13991         ep->dm_ctr_offset[i]  = 0;
  13992     }
  13993     ep->dm_ctr_size = 0;
  13994 
  13995     return rv;
  13996 }
  13997 
  13998 /*
  13999  * Function:
  14000  *      _bcm_fp_oam_mpls_lm_dm_appl_callback
  14001  * Purpose:
  14002  *      Update FW BHH appl state
  14003  * Parameters:
  14004  *      unit  - (IN) Unit number.
  14005  *      uC    - (IN) core number.
  14006  *      stage - (IN) core reset stage.
  14007  *      user_data - (IN) data pointer.
  14008  * Returns:
  14009  *      BCM_E_XXX
  14010  * Notes:
  14011  */
  14012 
  14013 int _bcm_fp_oam_mpls_lm_dm_appl_callback(int unit,
  14014                                     int uC,
  14015                                     soc_cmic_uc_shutdown_stage_t stage,
  14016                                     void *user_data) {
  14017     _bcm_fp_oam_control_t *oc;
  14018 
  14019     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
  14020     _BCM_OAM_LOCK(oc);
  14021     oc->mpls_lm_dm_ukernel_ready = 0;
  14022 
  14023     _BCM_OAM_UNLOCK(oc);
  14024 
  14025     return BCM_E_NONE;
  14026 }
  14027 
  14028 /*
  14029  * Function:
  14030  *      _bcm_fp_mpls_lm_dm_event_mask_set
  14031  * Purpose:
  14032  *      Set the MPLS_LM_DM Events mask.
  14033  *      Events are set per BHH module.
  14034  * Parameters:
  14035  *      unit        - (IN) Unit number.
  14036  * Returns:
  14037  *      BCM_E_NONE Operation completed successfully
  14038  *      BCM_E_XXX  Operation failed
  14039  * Notes:
  14040  */
  14041 STATIC int
  14042 _bcm_fp_mpls_lm_dm_event_mask_set(int unit)
  14043 {
  14044     _bcm_fp_oam_control_t    *oc;
  14045     _bcm_oam_event_handler_t *event_handler_p;
  14046     uint16 reply_len;
  14047     int rv = BCM_E_NONE;
  14048 
  14049     /* Lock already taken by the calling routine. */
  14050     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
  14051     _BCM_OAM_LOCK(oc);
  14052 
  14053     /* Get event mask from all callbacks */
  14054     for (event_handler_p = oc->event_handler_list_p;
  14055             event_handler_p != NULL;
  14056             event_handler_p = event_handler_p->next_p) {
  14057 
  14058         /* Update MPLS_LM_DM event mask in uKernel */
  14059         if (SHR_BITGET(event_handler_p->event_types.w,
  14060                        bcmOAMEventMplsLmDmPmCounterRollover)) {
  14061             /* Send MPLS_LM_DM Event Mask message to uC */
  14062             rv = _bcm_fp_oam_pm_msg_send_receive(unit,
  14063                             MOS_MSG_CLASS_MPLS_LM_DM,
  14064                             MOS_MSG_SUBCLASS_MPLS_LM_DM_EVENT_MASK_SET,
  14065                             0, MPLS_LM_DM_BTE_EVENT_PM_STATS_COUNTER_ROLLOVER,
  14066                             MOS_MSG_SUBCLASS_MPLS_LM_DM_EVENT_MASK_SET_REPLY,
  14067                             &reply_len);
  14068             if(BCM_SUCCESS(rv) && (reply_len != 0)) {
  14069                 rv = BCM_E_INTERNAL;
  14070             }
  14071             _BCM_OAM_UNLOCK(oc);
  14072             return (rv);
  14073         }
  14074     }
  14075     _BCM_OAM_UNLOCK(oc);
  14076     return (rv);
  14077 }
  14078 
  14079 #endif /* INCLUDE_MPLS_LM_DM */
  14080 /*******************************************************************************/
  14081 /* MPLS LM/DM App specific routines end                                        */
  14082 /*******************************************************************************/
  14083 
  14084 /*******************************************************************************/
  14085 /* Common routines for BHH & MPLS LM/DM App end                                */
  14086 /*******************************************************************************/
  14087 
  14088 /*******************************************************************************/
  14089 /* Common routines for CCM, BHH & MPLS LM/DM App start */
  14090 /*******************************************************************************/
  14091 #if defined (INCLUDE_CCM) || defined (INCLUDE_BHH) || defined(INCLUDE_MPLS_LM_DM)
  14092 
  14093 /*
  14094  * Function:
  14095  *     bcm_fp_oam_event_register
  14096  * Purpose:
  14097  *     Register a callback for handling OAM events
  14098  * Parameters:
  14099  *     unit        - (IN) BCM device number
  14100  *     event_types - (IN) The set of OAM events for which the specified
  14101  *                        callback should be called.
  14102  *     cb          - (IN) A pointer to the callback function to call for
  14103  *                        the specified OAM events
  14104  *     user_data   - (IN) Pointer to user data to supply in the callback
  14105  * Returns:
  14106  *      BCM_E_XXX
  14107  */
  14108 int
  14109 bcm_fp_oam_event_register(int unit, bcm_oam_event_types_t event_types,
  14110                         bcm_oam_event_cb cb, void *user_data)
  14111 {
  14112     _bcm_fp_oam_control_t    *oc;
  14113     _bcm_oam_event_handler_t *event_h_p;
  14114     _bcm_oam_event_handler_t *prev_p = NULL;
  14115     bcm_oam_event_type_t     e_type;
  14116     uint32                   event_bmp;
  14117     int                      rv = 0;
  14118 #if defined (INCLUDE_CCM)
  14119     int                      update_event_mask = 0;
  14120 #endif
  14121 #if defined (INCLUDE_BHH)
  14122     int                      update_bhh_event_mask = 0;
  14123 #endif
  14124 #if defined(INCLUDE_MPLS_LM_DM)
  14125     int                      update_mpls_lm_dm_event_mask = 0;
  14126 #endif
  14127     /* Validate event callback input parameter. */
  14128     if (NULL == cb) {
  14129         return (BCM_E_PARAM);
  14130     }
  14131 
  14132     /* Check if an event is set for register in the events bitmap. */
  14133     SHR_BITTEST_RANGE(event_types.w, 0, bcmOAMEventCount, event_bmp);
  14134     if (0 == event_bmp) {
  14135         /* No events specified. */
  14136         LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM(unit %d) Error: "
  14137             "No events specified for register.\n"), unit));
  14138         return (BCM_E_PARAM);
  14139     }
  14140 
  14141     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
  14142     _BCM_OAM_LOCK(oc);
  14143 
  14144     for (event_h_p = oc->event_handler_list_p; event_h_p != NULL;
  14145          event_h_p = event_h_p->next_p) {
  14146         if (event_h_p->cb == cb) {
  14147             break;
  14148         }
  14149         prev_p = event_h_p;
  14150     }
  14151 
  14152     if (NULL == event_h_p) {
  14153 
  14154         _BCM_OAM_ALLOC(event_h_p, _bcm_oam_event_handler_t,
  14155              sizeof(_bcm_oam_event_handler_t), "OAM event handler");
  14156 
  14157         if (NULL == event_h_p) {
  14158             LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM(unit %d) Error: "
  14159                 "Event handler alloc failed - %s.\n"), unit,
  14160                 bcm_errmsg(BCM_E_MEMORY)));
  14161             _BCM_OAM_UNLOCK(oc);
  14162             return (BCM_E_MEMORY);
  14163         }
  14164 
  14165         event_h_p->next_p = NULL;
  14166         event_h_p->cb = cb;
  14167         event_h_p->user_data = user_data;
  14168 
  14169         SHR_BITCLR_RANGE(event_h_p->event_types.w, 0, bcmOAMEventCount);
  14170         if (prev_p != NULL) {
  14171             prev_p->next_p = event_h_p;
  14172         } else {
  14173             oc->event_handler_list_p = event_h_p;
  14174         }
  14175     }
  14176 
  14177     for (e_type = 0; e_type < bcmOAMEventCount; ++e_type) {
  14178         if (SHR_BITGET(event_types.w, e_type)) {
  14179 #if defined(INCLUDE_BHH)
  14180             if(soc_feature(unit, soc_feature_bhh)) {
  14181                 /*
  14182                  * BHH events are generated by the uKernel
  14183                  */
  14184                 if ((e_type == bcmOAMEventBHHLBTimeout) ||
  14185                     (e_type == bcmOAMEventBHHLBDiscoveryUpdate) ||
  14186                     (e_type == bcmOAMEventBHHCCMTimeout) ||
  14187                     (e_type == bcmOAMEventBHHCCMTimeoutClear) ||
  14188                     (e_type == bcmOAMEventBHHCCMState) ||
  14189                     (e_type == bcmOAMEventBHHCCMRdi) ||
  14190                     (e_type == bcmOAMEventBHHCCMUnknownMegLevel) ||
  14191                     (e_type == bcmOAMEventBHHCCMUnknownMegId) ||
  14192                     (e_type == bcmOAMEventBHHCCMUnknownMepId) ||
  14193                     (e_type == bcmOAMEventBHHCCMUnknownPeriod) ||
  14194                     (e_type == bcmOAMEventBHHCCMUnknownPriority) ||
  14195                     (e_type == bcmOAMEventBHHCCMRdiClear) ||
  14196                     (e_type == bcmOAMEventBHHCCMUnknownMegLevelClear) ||
  14197                     (e_type == bcmOAMEventBHHCCMUnknownMegIdClear) ||
  14198                     (e_type == bcmOAMEventBHHCCMUnknownMepIdClear) ||
  14199                     (e_type == bcmOAMEventBHHCCMUnknownPeriodClear) ||
  14200                     (e_type == bcmOAMEventBHHCCMUnknownPriorityClear) ||
  14201                     (e_type == bcmOAMEventBhhPmCounterRollover) ||
  14202                     (e_type == bcmOAMEventCsfLos) ||
  14203                     (e_type == bcmOAMEventCsfFdi) ||
  14204                     (e_type == bcmOAMEventCsfRdi) ||
  14205                     (e_type == bcmOAMEventCsfDci)) {
  14206                     SHR_BITSET(event_h_p->event_types.w, e_type);
  14207                     oc->event_handler_cnt[e_type] += 1;
  14208                     update_bhh_event_mask = 1;
  14209                     continue;
  14210                 }
  14211             }
  14212 #endif
  14213 
  14214 #if defined(INCLUDE_CCM)
  14215             if(soc_feature(unit, soc_feature_uc_ccm)) {
  14216                 /* CCM events are generated by the uKernel */
  14217                 if ((e_type == bcmOAMEventEndpointPortDown) ||
  14218                     (e_type == bcmOAMEventEndpointPortUp) ||
  14219                     (e_type == bcmOAMEventEndpointInterfaceDown) ||
  14220                     (e_type == bcmOAMEventEndpointInterfaceUp) ||
  14221                     (e_type == bcmOAMEventEndpointInterfaceTesting) ||
  14222                     (e_type == bcmOAMEventEndpointInterfaceUnkonwn) ||
  14223                     (e_type == bcmOAMEventEndpointInterfaceDormant) ||
  14224                     (e_type == bcmOAMEventEndpointInterfaceNotPresent) ||
  14225                     (e_type == bcmOAMEventEndpointInterfaceLLDown) ||
  14226                     (e_type == bcmOAMEventGroupCCMxcon) ||
  14227                     (e_type == bcmOAMEventGroupCCMError) ||
  14228                     (e_type == bcmOAMEventGroupRemote) ||
  14229                     (e_type == bcmOAMEventGroupCCMTimeout) ||
  14230                     (e_type == bcmOAMEventGroupMACStatus) ||
  14231                     (e_type == bcmOAMEventGroupCCMxconClear) ||
  14232                     (e_type == bcmOAMEventGroupCCMErrorClear) ||
  14233                     (e_type == bcmOAMEventGroupRemoteClear) ||
  14234                     (e_type == bcmOAMEventGroupCCMTimeoutClear) ||
  14235                     (e_type == bcmOAMEventGroupMACStatusClear) ||
  14236                     (e_type == bcmOAMEventEndpointCCMTimeout) ||
  14237                     (e_type == bcmOAMEventEndpointCCMTimein) ||
  14238                     (e_type == bcmOAMEventEndpointRemote) ||
  14239                     (e_type == bcmOAMEventEndpointRemoteUp)) {
  14240 
  14241                     SHR_BITSET(event_h_p->event_types.w, e_type);
  14242                     oc->event_handler_cnt[e_type] += 1;
  14243                     update_event_mask = 1;
  14244                     continue;
  14245                 }
  14246             }
  14247 #endif /* INCLUDE_CCM */
  14248 
  14249 #if defined(INCLUDE_MPLS_LM_DM)
  14250             if (soc_feature(unit, soc_feature_mpls_lm_dm)) {
  14251                 if ((e_type == bcmOAMEventMplsLmDmPmCounterRollover)) {
  14252                     /*
  14253                      * MPLS_LM_DM events are generated by the uKernel
  14254                      */
  14255                     SHR_BITSET(event_h_p->event_types.w, e_type);
  14256                     oc->event_handler_cnt[e_type] += 1;
  14257                     update_mpls_lm_dm_event_mask = 1;
  14258                     continue;
  14259                 }
  14260             }
  14261 #endif /* INCLUDE_MPLS_LM_DM */
  14262         }
  14263     }
  14264 
  14265 #if defined(INCLUDE_BHH)
  14266     if (soc_feature(unit, soc_feature_bhh) && 
  14267         update_bhh_event_mask) {
  14268         /*
  14269          * Update BHH Events mask
  14270          */
  14271         rv = _bcm_fp_oam_bhh_event_mask_set(unit);
  14272     }
  14273 #endif /* INCLUDE_BHH */
  14274 
  14275 #if defined(INCLUDE_CCM)
  14276     if ((soc_feature(unit, soc_feature_uc_ccm)) && (update_event_mask)) {
  14277         /* Update CCM Events mask */
  14278         rv = _bcm_fp_oam_ccm_event_mask_set(unit);
  14279     }
  14280 #endif /* INCLUDE_CCM */
  14281 
  14282 #if defined(INCLUDE_MPLS_LM_DM)
  14283     if ((soc_feature(unit, soc_feature_mpls_lm_dm)) &&
  14284         update_mpls_lm_dm_event_mask) {
  14285         /*
  14286          * Update MPLS_LM_DM Events mask
  14287          */
  14288         rv = _bcm_fp_mpls_lm_dm_event_mask_set(unit);
  14289         if (BCM_FAILURE(rv)) {
  14290             _BCM_OAM_UNLOCK(oc);
  14291             LOG_ERROR(BSL_LS_BCM_OAM,
  14292                     (BSL_META_U(unit,
  14293                                 "OAM(unit %d) Error: failed to set MPLS LM DM event mask-"
  14294                                 " %s.\n"), unit, bcm_errmsg(rv)));
  14295             return (rv);
  14296         }
  14297     }
  14298 #endif /* INCLUDE_MPLS_LM_DM */
  14299 
  14300     _BCM_OAM_UNLOCK(oc);
  14301     return (rv);
  14302 }
  14303 
  14304 /*
  14305  * Function:
  14306  *     bcm_fp_oam_event_unregister
  14307  * Purpose:
  14308  *     Unregister event and its callback from the event handler list
  14309  * Parameters:
  14310  *     unit        - (IN) BCM device number
  14311  *     event_types - (IN) The set of OAM events for which the specified
  14312  *                        callback should not be called.
  14313  *     cb          - (IN) A pointer to the callback function to unregister
  14314  *                        from the specified OAM events
  14315  * Returns:
  14316  *      BCM_E_XXX
  14317  */
  14318 int
  14319 bcm_fp_oam_event_unregister(int unit, bcm_oam_event_types_t event_types,
  14320                         bcm_oam_event_cb cb)
  14321 {
  14322     _bcm_fp_oam_control_t    *oc;
  14323     _bcm_oam_event_handler_t *event_h_p;
  14324     _bcm_oam_event_handler_t *prev_p = NULL;
  14325     bcm_oam_event_type_t     e_type;
  14326     uint32                   event_bmp;
  14327     int                      rv = 0;
  14328 #if defined (INCLUDE_CCM)
  14329     int                      update_event_mask = 0;
  14330 #endif
  14331 #if defined (INCLUDE_BHH)
  14332     int                      update_bhh_event_mask = 0;
  14333 #endif
  14334 #if defined(INCLUDE_MPLS_LM_DM)
  14335     int                      update_mpls_lm_dm_event_mask = 0;
  14336 #endif
  14337     /* Validate event callback input parameter. */
  14338     if (NULL == cb) {
  14339         return (BCM_E_PARAM);
  14340     }
  14341 
  14342     /* Check if an event is set for unregister in the events bitmap. */
  14343     SHR_BITTEST_RANGE(event_types.w, 0, bcmOAMEventCount, event_bmp);
  14344     if (0 == event_bmp) {
  14345         /* No events specified. */
  14346         LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM(unit %d) Error: "
  14347             "No events specified for unregister.\n"), unit));
  14348         return (BCM_E_PARAM);
  14349     }
  14350 
  14351     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
  14352     _BCM_OAM_LOCK(oc);
  14353 
  14354     for (event_h_p = oc->event_handler_list_p; event_h_p != NULL;
  14355          event_h_p = event_h_p->next_p) {
  14356         if (event_h_p->cb == cb) {
  14357             break;
  14358         }
  14359         prev_p = event_h_p;
  14360     }
  14361 
  14362     if (NULL == event_h_p) {
  14363         _BCM_OAM_UNLOCK(oc);
  14364         return (BCM_E_NOT_FOUND);
  14365     }
  14366 
  14367     for (e_type = 0; e_type < bcmOAMEventCount; ++e_type) {
  14368         if (SHR_BITGET(event_types.w, e_type)) {
  14369 #if defined(INCLUDE_BHH)
  14370             if(soc_feature(unit, soc_feature_bhh)) {
  14371                 /*
  14372                  * BHH events are generated by the uKernel
  14373                  */
  14374                 if ((e_type == bcmOAMEventBHHLBTimeout) ||
  14375                     (e_type == bcmOAMEventBHHLBDiscoveryUpdate) ||
  14376                     (e_type == bcmOAMEventBHHCCMTimeout) ||
  14377                     (e_type == bcmOAMEventBHHCCMTimeoutClear) ||
  14378                     (e_type == bcmOAMEventBHHCCMState) ||
  14379                     (e_type == bcmOAMEventBHHCCMRdi) ||
  14380                     (e_type == bcmOAMEventBHHCCMUnknownMegLevel) ||
  14381                     (e_type == bcmOAMEventBHHCCMUnknownMegId) ||
  14382                     (e_type == bcmOAMEventBHHCCMUnknownMepId) ||
  14383                     (e_type == bcmOAMEventBHHCCMUnknownPeriod) ||
  14384                     (e_type == bcmOAMEventBHHCCMUnknownPriority) ||
  14385                     (e_type == bcmOAMEventBHHCCMRdiClear) ||
  14386                     (e_type == bcmOAMEventBHHCCMUnknownMegLevelClear) ||
  14387                     (e_type == bcmOAMEventBHHCCMUnknownMegIdClear) ||
  14388                     (e_type == bcmOAMEventBHHCCMUnknownMepIdClear) ||
  14389                     (e_type == bcmOAMEventBHHCCMUnknownPeriodClear) ||
  14390                     (e_type == bcmOAMEventBHHCCMUnknownPriorityClear) ||
  14391                     (e_type == bcmOAMEventBhhPmCounterRollover)) {
  14392                     SHR_BITCLR(event_h_p->event_types.w, e_type);
  14393                     oc->event_handler_cnt[e_type] -= 1;
  14394                     update_bhh_event_mask = 1;
  14395                     continue;
  14396                 }
  14397             }
  14398 #endif
  14399 
  14400 #if defined(INCLUDE_CCM)
  14401             if(soc_feature(unit, soc_feature_uc_ccm)) {
  14402                 /* CCM events are generated by the uKernel */
  14403                 if ((e_type == bcmOAMEventEndpointPortDown) ||
  14404                     (e_type == bcmOAMEventEndpointPortUp) ||
  14405                     (e_type == bcmOAMEventEndpointInterfaceDown) ||
  14406                     (e_type == bcmOAMEventEndpointInterfaceUp) ||
  14407                     (e_type == bcmOAMEventEndpointInterfaceTestingToUp) ||
  14408                     (e_type == bcmOAMEventEndpointInterfaceUnknownToUp) ||
  14409                     (e_type == bcmOAMEventEndpointInterfaceDormantToUp) ||
  14410                     (e_type == bcmOAMEventEndpointInterfaceNotPresentToUp) ||
  14411                     (e_type == bcmOAMEventEndpointInterfaceLLDownToUp) ||
  14412                     (e_type == bcmOAMEventEndpointInterfaceTesting) ||
  14413                     (e_type == bcmOAMEventEndpointInterfaceUnkonwn) ||
  14414                     (e_type == bcmOAMEventEndpointInterfaceDormant) ||
  14415                     (e_type == bcmOAMEventEndpointInterfaceNotPresent) ||
  14416                     (e_type == bcmOAMEventEndpointInterfaceLLDown) ||
  14417                     (e_type == bcmOAMEventGroupCCMxcon) ||
  14418                     (e_type == bcmOAMEventGroupCCMError) ||
  14419                     (e_type == bcmOAMEventGroupRemote) ||
  14420                     (e_type == bcmOAMEventGroupCCMTimeout) ||
  14421                     (e_type == bcmOAMEventEndpointCCMTimeout) ||
  14422                     (e_type == bcmOAMEventEndpointCCMTimein) ||
  14423                     (e_type == bcmOAMEventEndpointRemote) ||
  14424                     (e_type == bcmOAMEventEndpointRemoteUp)) {
  14425 
  14426                     SHR_BITCLR(event_h_p->event_types.w, e_type);
  14427                     oc->event_handler_cnt[e_type] -= 1;
  14428                     update_event_mask = 1;
  14429                     continue;
  14430                 }
  14431             }
  14432 #endif /* INCLUDE_CCM */
  14433 
  14434 #if defined(INCLUDE_MPLS_LM_DM)
  14435             if (soc_feature(unit, soc_feature_mpls_lm_dm)) {
  14436                 if ((e_type == bcmOAMEventMplsLmDmPmCounterRollover)) {
  14437                     /*
  14438                      * MPLS_LM_DM events are generated by the uKernel
  14439                      */
  14440                     SHR_BITCLR(event_h_p->event_types.w, e_type);
  14441                     oc->event_handler_cnt[e_type] -= 1;
  14442                     update_mpls_lm_dm_event_mask = 1;
  14443                     continue;
  14444                 }
  14445             }
  14446 #endif /* INCLUDE_MPLS_LM_DM */
  14447         }
  14448     }
  14449     SHR_BITTEST_RANGE(event_h_p->event_types.w, 0, bcmOAMEventCount, event_bmp);
  14450 
  14451     if (0 == event_bmp) {
  14452 
  14453         if (NULL != prev_p) {
  14454 
  14455             prev_p->next_p = event_h_p->next_p;
  14456 
  14457         } else {
  14458 
  14459             oc->event_handler_list_p = event_h_p->next_p;
  14460 
  14461         }
  14462         sal_free(event_h_p);
  14463     }
  14464 
  14465 #if defined(INCLUDE_BHH)
  14466     if (soc_feature(unit, soc_feature_bhh) && 
  14467         update_bhh_event_mask) {
  14468         /*
  14469          * Update BHH Events mask
  14470          */
  14471         rv = _bcm_fp_oam_bhh_event_mask_set(unit);
  14472     }
  14473 #endif /* INCLUDE_BHH */
  14474 
  14475 #if defined(INCLUDE_CCM)
  14476     if ((soc_feature(unit, soc_feature_uc_ccm)) && (update_event_mask)) {
  14477         /* Update CCM Events mask */
  14478         rv = _bcm_fp_oam_ccm_event_mask_set(unit);
  14479     }
  14480 #endif /* INCLUDE_CCM */
  14481 
  14482 #if defined(INCLUDE_MPLS_LM_DM)
  14483     if ((soc_feature(unit, soc_feature_mpls_lm_dm)) &&
  14484         update_mpls_lm_dm_event_mask) {
  14485         /*
  14486          * Update MPLS_LM_DM Events mask
  14487          */
  14488         rv = _bcm_fp_mpls_lm_dm_event_mask_set(unit);
  14489         if (BCM_FAILURE(rv)) {
  14490             _BCM_OAM_UNLOCK(oc);
  14491             LOG_ERROR(BSL_LS_BCM_OAM,
  14492                     (BSL_META_U(unit,
  14493                                 "OAM(unit %d) Error: failed to set MPLS LM DM event mask-"
  14494                                 " %s.\n"), unit, bcm_errmsg(rv)));
  14495             return (rv);
  14496         }
  14497     }
  14498 #endif /* INCLUDE_MPLS_LM_DM */
  14499 
  14500     _BCM_OAM_UNLOCK(oc);
  14501     return (rv);
  14502 }
  14503 
  14504 /*
  14505  * Function:
  14506  *     _bcm_fp_oam_resource_count_init
  14507  * Purpose:
  14508  *     Retrieves and initializes endpoint count information for this device.
  14509  * Parameters:
  14510  *     unit -  (IN) BCM unit number.
  14511  *     oc   -  (IN) Pointer to device OAM control structure.
  14512  * Retruns:
  14513  *     BCM_E_XXX
  14514  */
  14515 STATIC int
  14516 _bcm_fp_oam_resource_count_init(int unit, _bcm_fp_oam_control_t *oc)
  14517 {
  14518     /* Input parameter check. */
  14519     if (NULL == oc) {
  14520         return (BCM_E_PARAM);
  14521     }
  14522 
  14523 #if defined(INCLUDE_CCM)
  14524     if (soc_feature(unit, soc_feature_uc_ccm)) {
  14525         /*
  14526          * Get endpoint firmware table index count values and
  14527          * initialize device OAM control structure members variables.
  14528          */
  14529         oc->mep_count = soc_property_get(unit, spn_OAM_CCM_MAX_MEPS, 256);
  14530         oc->group_count = soc_property_get(unit, spn_OAM_CCM_MAX_GROUPS, 256);
  14531     }
  14532 #endif /* INCLUDE_CCM */
  14533 #if defined(INCLUDE_BHH)
  14534     if (soc_feature(unit, soc_feature_bhh)) {
  14535 
  14536     /* Get SOC properties for BHH */
  14537     oc->bhh_endpoint_count = soc_property_get(unit, spn_BHH_NUM_SESSIONS, 128);
  14538     oc->bhh_base_group_id  = soc_property_get(unit, spn_BHH_BASE_GROUP_ID, 256);
  14539     oc->bhh_base_endpoint_id  = soc_property_get(unit, spn_BHH_BASE_ENDPOINT_ID,
  14540                                                  512);
  14541     }
  14542 #endif /* INCLUDE_BHH */
  14543 
  14544     return (BCM_E_NONE);
  14545 }
  14546 
  14547 /*
  14548  * Function:
  14549  *     _bcm_fp_oam_control_free
  14550  * Purpose:
  14551  *     Free OAM control structure resources allocated by this unit.
  14552  * Parameters:
  14553  *     unit -  (IN) BCM unit number.
  14554  *     oc   -  (IN) Pointer to OAM control structure.
  14555  * Retruns:
  14556  *     BCM_E_XXX
  14557  */
  14558 STATIC int
  14559 _bcm_fp_oam_control_free(int unit, _bcm_fp_oam_control_t *oc)
  14560 {
  14561     _fp_oam_control[unit] = NULL;
  14562 
  14563 #if defined(INCLUDE_BHH)
  14564     int status = 0;
  14565 #endif
  14566 
  14567     if (NULL == oc) {
  14568         /* Module already un-initialized */
  14569         return (BCM_E_NONE);
  14570     }
  14571 
  14572     /* Free protection mutex */
  14573     if (NULL != oc->oc_lock) {
  14574         sal_mutex_destroy(oc->oc_lock);
  14575         oc->oc_lock = NULL;
  14576     }
  14577 
  14578     /* Destory group indices list */
  14579     if (NULL != oc->group_pool) {
  14580        shr_idxres_list_destroy(oc->group_pool);
  14581        oc->group_pool = NULL;
  14582     }
  14583 
  14584     /* Free group memory. */
  14585     if (NULL != oc->group_data) {
  14586         sal_free(oc->group_data);
  14587         oc->group_data = NULL;
  14588     }
  14589 
  14590     /* Destroy LMEP indices list */
  14591     if (NULL != oc->mep_pool) {
  14592         shr_idxres_list_destroy(oc->mep_pool);
  14593         oc->mep_pool = NULL;
  14594     }
  14595 
  14596     /* Free LMEP memory. */
  14597     if (NULL != oc->mep_data) {
  14598         sal_free(oc->mep_data);
  14599     }
  14600 #if 0
  14601     /* Free hash data storage memory */
  14602     if (NULL != oc->oam_hash_data) {
  14603         sal_free(oc->oam_hash_data);
  14604     }
  14605 #endif
  14606 #if defined(INCLUDE_BHH)
  14607     /* Free BHH hash data storage memory */
  14608     if (NULL != oc->bhh_ep_data) {
  14609         sal_free(oc->bhh_ep_data);
  14610     }
  14611     /* Destory endpoint hash table. */
  14612     if (NULL != oc->bhh_mep_htbl) {
  14613         status = shr_htb_destroy(&oc->bhh_mep_htbl, NULL);
  14614         if (BCM_FAILURE(status)) {
  14615             LOG_ERROR(BSL_LS_BCM_OAM,
  14616                     (BSL_META_U(unit,
  14617                                 "Freeing bhh_mep_htbl failed\n")));
  14618         }
  14619     }
  14620     /* Free BHH group memory. */
  14621     if (NULL != oc->bhh_group_data) {
  14622         sal_free(oc->bhh_group_data);
  14623     }
  14624     /* Destroy BHH EP indices list */
  14625     if (NULL != oc->bhh_pool) {
  14626         shr_idxres_list_destroy(oc->bhh_pool);
  14627         oc->bhh_pool = NULL;
  14628     }
  14629     /* Free BHH DMA buffer */
  14630     if (NULL != oc->bhh_dma_buffer) {
  14631         soc_cm_sfree(oc->unit, oc->bhh_dma_buffer);
  14632     }
  14633     /* Free BHH reply DMA buffer */
  14634     if (NULL != oc->bhh_dmabuf_reply) {
  14635         soc_cm_sfree(oc->unit, oc->bhh_dmabuf_reply);
  14636     }
  14637     if (soc_feature(unit, soc_feature_oam_pm)) {
  14638         if (_BCM_FP_OAM_PM_BHH_DATA_COLLECTION_MODE_ENABLED(oc)) {
  14639             soc_cm_sfree(oc->unit, oc->pm_bhh_dma_buffer);
  14640         }
  14641     }
  14642 #endif
  14643 
  14644 #if defined(INCLUDE_MPLS_LM_DM)
  14645     if (NULL != oc->mpls_lm_dm_dma_buffer) {
  14646         soc_cm_sfree(oc->unit, oc->mpls_lm_dm_dma_buffer);
  14647         oc->mpls_lm_dm_dma_buffer = NULL;
  14648     }
  14649 
  14650     if (NULL != oc->mpls_lm_dm_pool) {
  14651         shr_idxres_list_destroy(oc->mpls_lm_dm_pool);
  14652         oc->mpls_lm_dm_pool = NULL;
  14653     }
  14654 
  14655     if (NULL != oc->mpls_lm_dm_ep_data) {
  14656         sal_free(oc->mpls_lm_dm_ep_data);
  14657         oc->mpls_lm_dm_ep_data = NULL;
  14658     }
  14659 #endif /* INCLUDE_MPLS_LM_DM */
  14660 
  14661 #if defined(INCLUDE_BHH) || defined(INCLUDE_MPLS_LM_DM)
  14662     if (soc_feature(unit, soc_feature_oam_pm)) {
  14663         if (pm_profile_control[unit]) {
  14664             sal_free(pm_profile_control[unit]);
  14665             pm_profile_control[unit] = NULL;
  14666         }
  14667     }
  14668 #endif /* INCLUDE_BHH || INCLUDE_MPLS_LM_DM */
  14669 
  14670     /* Free OAM control structure memory. */
  14671     sal_free(oc);
  14672     oc = NULL;
  14673 
  14674     return (BCM_E_NONE);
  14675 
  14676 }
  14677 
  14678 
  14679 /*
  14680  * Function:
  14681  *     bcm_fp_oam_detach
  14682  * Purpose:
  14683  *     Shut down OAM subsystem
  14684  * Parameters:
  14685  *     unit - (IN) BCM device number
  14686  * Returns:
  14687  *     BCM_E_XXX
  14688  */
  14689 int
  14690 bcm_fp_oam_detach(int unit)
  14691 {
  14692     int rv = 0;
  14693     _bcm_fp_oam_control_t    *oc = NULL;
  14694 #if defined(INCLUDE_CCM) || defined(INCLUDE_BHH)
  14695     uint16 reply_len;
  14696 #endif /* INCLUDE_CCM || INCLUDE_BHH */
  14697 
  14698     /* Get OAM Control Structure. */
  14699     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
  14700 
  14701     /* Stop CCM Event Thread */
  14702 #if defined(INCLUDE_CCM)
  14703         if (soc_feature(unit, soc_feature_uc_ccm)) {
  14704             if (oc->ccm_ukernel_ready) {
  14705                 /* Event Handler thread exit signal */
  14706                 sal_usecs_t timeout = sal_time_usecs() + 5000000;
  14707                 while (NULL !=  oc->event_thread_id) {
  14708                     soc_cmic_uc_msg_receive_cancel(unit, oc->ccm_uc_num,
  14709                                                    MOS_MSG_CLASS_CCM_EVENT);
  14710 
  14711                     if (sal_time_usecs() < timeout) {
  14712                         /*give some time to already running CCM callback thread
  14713                          * to schedule and exit */
  14714                         sal_usleep(10000);
  14715                     } else {
  14716                         /*timeout*/
  14717                         LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit,
  14718                                   "CCM event thread did not exit.\n")));
  14719                         _BCM_OAM_UNLOCK(oc);
  14720                         return BCM_E_INTERNAL;
  14721                     }
  14722                 }
  14723 
  14724                 if (!SOC_WARM_BOOT(unit)) {
  14725                     /*
  14726                      * Send CCM Uninit message to uC
  14727                      * Ignore error since that may indicate uKernel was reloaded.
  14728                      */
  14729                     rv = _bcm_fp_oam_msg_send_receive(unit,
  14730                             MOS_MSG_CLASS_CCM,
  14731                             MOS_MSG_SUBCLASS_CCM_UNINIT,
  14732                             0, 0,
  14733                             MOS_MSG_SUBCLASS_CCM_UNINIT_REPLY,
  14734                             &reply_len);
  14735                     if (BCM_SUCCESS(rv) && (reply_len != 0)) {
  14736                         if (NULL != oc->oc_lock) {
  14737                             _BCM_OAM_UNLOCK(oc);
  14738                         }
  14739                         return BCM_E_INTERNAL;
  14740                     } else {
  14741                         if ((rv == BCM_E_TIMEOUT) || (rv == BCM_E_INIT)) {
  14742                             LOG_DEBUG(BSL_LS_BCM_OAM, (BSL_META_U(unit, "CCM: "
  14743                                 "Uninit error - %s\n"), bcm_errmsg(rv)));
  14744                             rv = BCM_E_NONE;
  14745                         }
  14746                     }
  14747                 }
  14748             }
  14749         }
  14750 #endif /* INCLUDE_CCM */
  14751 
  14752 
  14753      /* Stop BHH Event Thread */
  14754 #if defined(INCLUDE_BHH)
  14755     if (soc_feature(unit, soc_feature_bhh)) {
  14756         int uc_status;
  14757         if (oc->ukernel_not_ready == 0) {
  14758             /*
  14759              * Event Handler thread exit signal
  14760              */
  14761             sal_usecs_t timeout = sal_time_usecs() + 5000000;
  14762             while (NULL !=  oc->bhh_event_thread_id) {
  14763                 soc_cmic_uc_msg_receive_cancel(unit, oc->bhh_uc_num,
  14764                                                MOS_MSG_CLASS_BHH_EVENT);
  14765 
  14766                 if (sal_time_usecs() < timeout) {
  14767                     /*give some time to already running bhh callback thread
  14768                      * to schedule and exit */
  14769                     sal_usleep(10000);
  14770                 } else {
  14771                     /*timeout*/
  14772                     LOG_ERROR(BSL_LS_BCM_OAM,
  14773                               (BSL_META_U(unit,
  14774                                           "BHH event thread did not exit.\n")));
  14775                     return BCM_E_INTERNAL;
  14776                 }
  14777             }
  14778             if (!SOC_WARM_BOOT(unit)) {
  14779                 /*
  14780                  * Send BHH Uninit message to uC
  14781                  */
  14782                 SOC_IF_ERROR_RETURN(soc_uc_status(unit, oc->bhh_uc_num, &uc_status));
  14783                 if (uc_status) {
  14784                     rv = _bcm_fp_oam_msg_send_receive(unit,
  14785                                MOS_MSG_CLASS_BHH,
  14786                                MOS_MSG_SUBCLASS_BHH_UNINIT,
  14787                                0, 0,
  14788                                MOS_MSG_SUBCLASS_BHH_UNINIT_REPLY,
  14789                               &reply_len);
  14790                     if (BCM_SUCCESS(rv) && (reply_len != 0)) {
  14791                         LOG_ERROR(BSL_LS_BCM_OAM,
  14792                               (BSL_META_U(unit,
  14793                                           "BHH UNINIT failed - error %s\n"),
  14794                                           bcm_errmsg(rv)));
  14795                         return BCM_E_INTERNAL;
  14796                     }
  14797                 }
  14798                  /* Ignore timeout/init error since that may indicate
  14799                   * uKernel was reloaded/msging is not up.*/
  14800                 if ((rv == BCM_E_TIMEOUT) || (rv == BCM_E_INIT)) {
  14801                     LOG_DEBUG(BSL_LS_BCM_OAM,
  14802                             (BSL_META_U(unit,
  14803                                         "BHH UNINIT failed - %s\n"),
  14804                              bcm_errmsg(rv)));
  14805                     rv = BCM_E_NONE;
  14806                 }
  14807 
  14808             }
  14809         }
  14810 
  14811     }
  14812 #endif /* INCLUDE_BHH */
  14813 
  14814 #if defined(INCLUDE_MPLS_LM_DM)
  14815     if (soc_feature(unit, soc_feature_mpls_lm_dm)) {
  14816         rv = _bcm_fp_oam_mpls_lm_dm_detach(unit);
  14817         if (rv != BCM_E_NONE) {
  14818             LOG_ERROR(BSL_LS_BCM_OAM,
  14819                       (BSL_META_U(unit,
  14820                                   "MPLS LM/DM UNINIT failed - error %s\n"),
  14821                        bcm_errmsg(rv)));
  14822         }
  14823     }
  14824 #endif /* INCLUDE_MPLS_LM_DM */
  14825 
  14826 
  14827     _bcm_fp_oam_control_free(unit, oc);
  14828     return rv;
  14829 }
  14830 
  14831 /*
  14832  * Function:
  14833  *     bcm_fp_oam_endpoint_create
  14834  * Purpose:
  14835  *     Create or replace an OAM endpoint object
  14836  * Parameters:
  14837  *     unit          - (IN) BCM device number
  14838  *     endpoint_info - (IN/OUT) Pointer to endpoint information buffer.
  14839  * Returns:
  14840  *      BCM_E_XXX
  14841  */
  14842 int
  14843 bcm_fp_oam_endpoint_create(int unit, bcm_oam_endpoint_info_t *endpoint_info)
  14844 {
  14845     int rv = BCM_E_PARAM;
  14846 
  14847 #if defined (INCLUDE_CCM)
  14848     if (soc_feature(unit, soc_feature_uc_ccm) &&
  14849         (endpoint_info->type  == bcmOAMEndpointTypeEthernet)) {
  14850         rv = bcm_fp_oam_ccm_endpoint_create(unit, endpoint_info);
  14851     }
  14852 #endif
  14853   
  14854 #if defined (INCLUDE_BHH)
  14855     if (soc_feature(unit, soc_feature_bhh) && 
  14856              BHH_EP_TYPE (endpoint_info)){
  14857         rv = _bcm_fp_oam_bhh_endpoint_create (unit, endpoint_info);
  14858     }
  14859 #endif
  14860 
  14861 #if defined(INCLUDE_MPLS_LM_DM)
  14862     if (soc_feature(unit, soc_feature_mpls_lm_dm)) {
  14863         if (_MPLS_LM_DM_ENDPOINT_TYPE(endpoint_info->type)) {
  14864             rv = _bcm_fp_oam_mpls_lm_dm_endpoint_create(unit, endpoint_info);
  14865         }
  14866     }
  14867 #endif /* INCLUDE_MPLS_LM_DM */
  14868     return rv;
  14869 }
  14870 
  14871 /*
  14872  * Function:
  14873  *     bcm_fp_oam_endpoint_get
  14874  * Purpose:
  14875  *     Fetches an OAM endpoint object
  14876  * Parameters:
  14877  *     unit     - (IN) BCM device number
  14878  *     endpoint - (IN) Endpoint ID to get.
  14879  * result =s:
  14880  *     BCM_E_XXX
  14881  */
  14882 int
  14883 bcm_fp_oam_endpoint_get(int unit, bcm_oam_endpoint_t endpoint,
  14884                          bcm_oam_endpoint_info_t *endpoint_info)
  14885 {
  14886     int rv = BCM_E_PARAM; /* Operation return status */
  14887     _bcm_fp_oam_control_t *oc = NULL;
  14888 
  14889     /* Get OAM control structure handle. */
  14890     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
  14891     
  14892     _BCM_OAM_LOCK(oc);
  14893 
  14894 
  14895 #if defined (INCLUDE_CCM)
  14896     if (soc_feature(unit, soc_feature_uc_ccm) && 
  14897         ((endpoint >= 0) &&  (endpoint < oc->mep_count))) {
  14898         endpoint_info->id = endpoint;
  14899         rv = bcm_fp_oam_ccm_endpoint_get(unit, endpoint_info);     
  14900     }
  14901 #endif
  14902 
  14903 #if defined (INCLUDE_BHH)
  14904     if (soc_feature(unit, soc_feature_bhh) &&
  14905         ((endpoint >= oc->bhh_base_endpoint_id) &&  
  14906         (endpoint < (oc->bhh_base_endpoint_id + oc->bhh_endpoint_count)))) {
  14907         if (oc->ukernel_not_ready == 1){
  14908             LOG_ERROR(BSL_LS_BCM_OAM,
  14909                     (BSL_META_U(unit,
  14910                                 "OAM(unit %d) Error: BTE(ukernel) "
  14911                                 "not ready.\n"), unit));
  14912             _BCM_OAM_UNLOCK(oc);
  14913             return (BCM_E_INIT);
  14914         }
  14915         endpoint_info->id = endpoint;
  14916         rv = _bcm_fp_oam_bhh_endpoint_get(unit, endpoint_info);
  14917     }
  14918 #endif
  14919 
  14920 #if defined (INCLUDE_MPLS_LM_DM)
  14921     if(soc_feature(unit, soc_feature_mpls_lm_dm)) {
  14922         if(_MPLS_LM_DM_EP_ID_RANGE(endpoint)) {
  14923             rv = _bcm_fp_oam_mpls_lm_dm_endpoint_get(unit, endpoint,
  14924                                                      endpoint_info);
  14925         }
  14926     }
  14927 #endif /* INCLUDE_MPLS_LM_DM */
  14928 
  14929     _BCM_OAM_UNLOCK(oc);
  14930     return (rv);
  14931 }
  14932 
  14933 /*
  14934  * Function:
  14935  *     bcm_fp_oam_endpoint_destroy
  14936  * Purpose:
  14937  *     Destroy an OAM endpoint object
  14938  * Parameters:
  14939  *     unit     - (IN) BCM device number
  14940  *     endpoint - (IN) Endpoint ID to destroy.
  14941  * result =s:
  14942  *     BCM_E_XXX
  14943  */
  14944 int
  14945 bcm_fp_oam_endpoint_destroy(int unit, bcm_oam_endpoint_t endpoint)
  14946 {
  14947     int rv = BCM_E_PARAM; /* Operation return status */
  14948     _bcm_fp_oam_control_t *oc = NULL;
  14949 
  14950     /* Get OAM control structure handle. */
  14951     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
  14952     
  14953     _BCM_OAM_LOCK(oc);
  14954 
  14955 
  14956 #if defined (INCLUDE_CCM)
  14957     if (soc_feature(unit, soc_feature_uc_ccm) && 
  14958         ((endpoint >= 0) &&  (endpoint < oc->mep_count))) {
  14959         rv = bcm_fp_oam_ccm_endpoint_destroy(unit, endpoint);
  14960     }
  14961 #endif
  14962 
  14963 #if defined (INCLUDE_BHH)
  14964     if (soc_feature(unit, soc_feature_bhh) &&
  14965         ((endpoint >= oc->bhh_base_endpoint_id) &&  
  14966         (endpoint < (oc->bhh_base_endpoint_id + oc->bhh_endpoint_count)))) {
  14967         if (oc->ukernel_not_ready == 1){
  14968             LOG_ERROR(BSL_LS_BCM_OAM,
  14969                     (BSL_META_U(unit,
  14970                                 "OAM(unit %d) Error: BTE(ukernel) "
  14971                                 "not ready.\n"), unit));
  14972             _BCM_OAM_UNLOCK(oc);
  14973             return (BCM_E_INIT);
  14974         }
  14975         rv = _bcm_fp_oam_bhh_endpoint_destroy(unit, endpoint);
  14976     }
  14977 #endif
  14978 
  14979 #if defined (INCLUDE_MPLS_LM_DM)
  14980     if(soc_feature(unit, soc_feature_mpls_lm_dm)) {
  14981         if(_MPLS_LM_DM_EP_ID_RANGE(endpoint)) {
  14982             rv = _bcm_fp_oam_mpls_lm_dm_endpoint_destroy(unit, endpoint);
  14983         }
  14984     }
  14985 #endif /* INCLUDE_MPLS_LM_DM */
  14986 
  14987     _BCM_OAM_UNLOCK(oc);
  14988     return (rv);
  14989 }
  14990 
  14991 /*  
  14992  * Function:
  14993  *     bcm_fp_oam_endpoint_destroy_all
  14994  * Purpose:
  14995  *     Destroy all OAM endpoint objects associated with a group.
  14996  * Parameters:
  14997  *     unit  - (IN) BCM device number
  14998  *     group - (IN) The OAM group whose endpoints should be destroyed
  14999  * Returns:
  15000  *     BCM_E_XXX
  15001  */
  15002 int
  15003 bcm_fp_oam_endpoint_destroy_all(int unit, bcm_oam_group_t group)
  15004 {
  15005     int rv = BCM_E_PARAM; /* Operation return status */
  15006     _bcm_fp_oam_control_t *oc = NULL;
  15007 
  15008     /* Get OAM control structure handle. */
  15009     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
  15010 
  15011     _BCM_OAM_LOCK(oc);
  15012 
  15013 #if defined (INCLUDE_BHH)
  15014     if (soc_feature(unit, soc_feature_bhh) &&
  15015         ((group >= oc->bhh_base_group_id) &&
  15016         (group < (oc->bhh_base_group_id + oc->bhh_endpoint_count)))) {
  15017         if (oc->ukernel_not_ready == 1){
  15018             LOG_ERROR(BSL_LS_BCM_OAM,
  15019                     (BSL_META_U(unit,
  15020                                 "OAM(unit %d) Error: BTE(ukernel) "
  15021                                 "not ready.\n"), unit));
  15022             _BCM_OAM_UNLOCK(oc);
  15023             return (BCM_E_INIT);
  15024         }
  15025         rv = _bcm_fp_oam_bhh_endpoint_destroy_all(unit, group);
  15026     }
  15027 #endif
  15028     _BCM_OAM_UNLOCK(oc);
  15029 
  15030     return (rv);
  15031 }
  15032 
  15033 /*
  15034  * Function:
  15035  *     bcm_fp_oam_endpoint_traverse
  15036  * Purpose:
  15037  *     Traverse the entire set of BHH endpoints associated with BHH group
  15038  *     and calls specified callback for each one
  15039  * Parameters:
  15040  *     unit  - (IN) BCM device number
  15041  *     cb        - (IN) Pointer to call back function.
  15042  *     user_data - (IN) Pointer to user supplied data.
  15043  * Returns:
  15044  *     BCM_E_XXX
  15045  */
  15046 int
  15047 bcm_fp_oam_endpoint_traverse(int unit, bcm_oam_group_t group,
  15048                              bcm_oam_endpoint_traverse_cb cb,
  15049                              void *user_data)
  15050 {    int rv = BCM_E_PARAM; /* Operation return status */
  15051     _bcm_fp_oam_control_t *oc = NULL;
  15052 
  15053     /* Get OAM control structure handle. */
  15054     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
  15055     
  15056     _BCM_OAM_LOCK(oc);
  15057 #if defined (INCLUDE_CCM)
  15058     if (soc_feature(unit, soc_feature_uc_ccm)
  15059         && (group > 0 && group <= oc->group_count)) {
  15060         if (!oc->ccm_ukernel_ready) {
  15061             LOG_ERROR(BSL_LS_BCM_OAM,
  15062                     (BSL_META_U(unit,
  15063                                 "CCM(unit %d) Error: BTE(ukernel) "
  15064                                 "not ready.\n"), unit));
  15065             _BCM_OAM_UNLOCK(oc);
  15066             return (BCM_E_INIT);
  15067         }
  15068 
  15069         rv = _bcm_fp_oam_ccm_endpoint_traverse(unit, group, cb,user_data);
  15070 
  15071         if (BCM_FAILURE(rv)) {
  15072             LOG_ERROR(BSL_LS_BCM_OAM,
  15073                         (BSL_META_U(unit,
  15074                                     "CCM(unit %d) Error: Endpoint traverse "
  15075                                     "routine : %s.\n"), unit, bcm_errmsg(rv)));
  15076         }
  15077     }
  15078 #endif
  15079 
  15080 #if defined (INCLUDE_BHH)
  15081     if (soc_feature(unit, soc_feature_bhh) &&
  15082             ((group >= oc->bhh_base_group_id) &&  
  15083              (group < (oc->bhh_base_group_id + oc->bhh_endpoint_count)))) {
  15084         if (oc->ukernel_not_ready == 1){
  15085             LOG_ERROR(BSL_LS_BCM_OAM,
  15086                     (BSL_META_U(unit,
  15087                                 "OAM(unit %d) Error: BTE(ukernel) "
  15088                                 "not ready.\n"), unit));
  15089             _BCM_OAM_UNLOCK(oc);
  15090             return (BCM_E_INIT);
  15091         }
  15092         rv = _bcm_fp_oam_bhh_endpoint_traverse (unit, group, cb, user_data);
  15093     }
  15094 #endif
  15095     _BCM_OAM_UNLOCK(oc);
  15096     return (rv);
  15097 }
  15098 
  15099 /*
  15100  * Function:
  15101  *     bcm_fp_oam_group_create
  15102  * Purpose:
  15103  *     Create or replace an OAM group object
  15104  * Parameters:
  15105  *     unit          - (IN) BCM device number
  15106  *     group_info - (IN/OUT) Pointer to group information buffer.
  15107  * Returns:
  15108  *      BCM_E_XXX
  15109  */
  15110 int
  15111 bcm_fp_oam_group_create(int unit, bcm_oam_group_info_t *group_info)
  15112 {
  15113     int rv = BCM_E_PARAM;
  15114 
  15115 #if defined (INCLUDE_CCM)
  15116     if (soc_feature(unit, soc_feature_uc_ccm) &&
  15117         !(group_info->flags  & BCM_OAM_GROUP_TYPE_BHH)) {
  15118         rv = bcm_fp_oam_ccm_group_create(unit, group_info);
  15119     }
  15120 #endif
  15121   
  15122 #if defined (INCLUDE_BHH)
  15123     if (soc_feature(unit, soc_feature_bhh) && 
  15124         (group_info->flags  & BCM_OAM_GROUP_TYPE_BHH)) {
  15125         rv = _bcm_fp_oam_bhh_group_create (unit, group_info);
  15126     }
  15127 #endif
  15128     return rv;
  15129 }
  15130 
  15131 /*
  15132  * Function:
  15133  *     bcm_fp_oam_group_get
  15134  * Purpose:
  15135  *     Fetches an OAM group object
  15136  * Parameters:
  15137  *     unit     - (IN) BCM device number
  15138  *     group - (IN) Group ID to get.
  15139  * result =s:
  15140  *     BCM_E_XXX
  15141  */
  15142 int
  15143 bcm_fp_oam_group_get(int unit,  bcm_oam_group_t group,
  15144                          bcm_oam_group_info_t *group_info)
  15145 {
  15146     int rv = BCM_E_PARAM; /* Operation return status */
  15147     _bcm_fp_oam_control_t *oc = NULL;
  15148 
  15149     /* Get OAM control structure handle. */
  15150     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
  15151     
  15152     _BCM_OAM_LOCK(oc);
  15153 
  15154 
  15155 #if defined (INCLUDE_CCM)
  15156     if (soc_feature(unit, soc_feature_uc_ccm) && 
  15157         ((group >= 0) &&  (group < oc->group_count))) {
  15158         group_info->id = group;
  15159         rv = bcm_fp_oam_ccm_group_get(unit, group_info);     
  15160     }
  15161 #endif
  15162 
  15163 #if defined (INCLUDE_BHH)
  15164     if (soc_feature(unit, soc_feature_bhh) &&
  15165         ((group >= oc->bhh_base_group_id) &&  
  15166         (group < (oc->bhh_base_group_id + oc->bhh_endpoint_count)))) {
  15167         if (oc->ukernel_not_ready == 1){
  15168             LOG_ERROR(BSL_LS_BCM_OAM,
  15169                     (BSL_META_U(unit,
  15170                                 "OAM(unit %d) Error: BTE(ukernel) "
  15171                                 "not ready.\n"), unit));
  15172             _BCM_OAM_UNLOCK(oc);
  15173             return (BCM_E_INIT);
  15174         }
  15175         group_info->id = group;
  15176         rv = _bcm_fp_oam_bhh_group_get(unit, group_info);
  15177     }
  15178 #endif
  15179     _BCM_OAM_UNLOCK(oc);
  15180     return (rv);
  15181 }
  15182 
  15183 /*
  15184  * Function:
  15185  *     bcm_fp_oam_group_destroy
  15186  * Purpose:
  15187  *     Destroy an OAM group object
  15188  * Parameters:
  15189  *     unit     - (IN) BCM device number
  15190  *     group    - (IN) Group ID to destroy.
  15191  * result =s:
  15192  *     BCM_E_XXX
  15193  */
  15194 int
  15195 bcm_fp_oam_group_destroy(int unit, bcm_oam_group_t group)
  15196 {
  15197     int rv = BCM_E_PARAM; /* Operation return status */
  15198     _bcm_fp_oam_control_t *oc = NULL;
  15199 
  15200     /* Get OAM control structure handle. */
  15201     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
  15202     
  15203     _BCM_OAM_LOCK(oc);
  15204 
  15205 
  15206 #if defined (INCLUDE_CCM)
  15207     if (soc_feature(unit, soc_feature_uc_ccm) && 
  15208         ((group >= 0) &&  (group < oc->group_count))) {
  15209         rv = bcm_fp_oam_ccm_group_destroy(unit, group);
  15210     }
  15211 #endif
  15212 
  15213 #if defined (INCLUDE_BHH)
  15214     if (soc_feature(unit, soc_feature_bhh) &&
  15215         ((group >= oc->bhh_base_group_id) &&  
  15216         (group < (oc->bhh_base_group_id + oc->bhh_endpoint_count)))) {
  15217         if (oc->ukernel_not_ready == 1){
  15218             LOG_ERROR(BSL_LS_BCM_OAM,
  15219                     (BSL_META_U(unit,
  15220                                 "OAM(unit %d) Error: BTE(ukernel) "
  15221                                 "not ready.\n"), unit));
  15222             _BCM_OAM_UNLOCK(oc);
  15223             return (BCM_E_INIT);
  15224         }
  15225         rv = _bcm_fp_oam_bhh_group_destroy(unit, group);
  15226     }
  15227 #endif
  15228     _BCM_OAM_UNLOCK(oc);
  15229     return (rv);
  15230 }
  15231 
  15232 /*
  15233  * Function:
  15234  *     bcm_fp_oam_group_destroy_all
  15235  * Purpose:
  15236  *     Destroy all OAM groups
  15237  * Parameters:
  15238  *     unit  - (IN) BCM device number
  15239  * Returns:
  15240  *     BCM_E_XXX
  15241  */
  15242 int
  15243 bcm_fp_oam_group_destroy_all(int unit)
  15244 {
  15245     int rv = BCM_E_UNAVAIL; /* Operation return status */
  15246     _bcm_fp_oam_control_t *oc = NULL;
  15247 
  15248     /* Get OAM control structure handle. */
  15249     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
  15250     
  15251     _BCM_OAM_LOCK(oc);
  15252 
  15253 #if defined (INCLUDE_BHH)
  15254     if (soc_feature(unit, soc_feature_bhh) &&
  15255         (oc->ukernel_not_ready == 0)){
  15256         rv = _bcm_fp_oam_bhh_group_destroy_all(unit);
  15257     }
  15258 #endif
  15259     _BCM_OAM_UNLOCK(oc);
  15260     return (rv);
  15261 
  15262 }
  15263 
  15264 /*
  15265  * Function:
  15266  *     bcm_fp_oam_group_traverse
  15267  * Purpose:
  15268  *     Traverse the entire set of OAM groups, calling a specified
  15269  *     callback for each one
  15270  * Parameters:
  15271  *     unit  - (IN) BCM device number
  15272  *     cb        - (IN) Pointer to call back function.
  15273  *     user_data - (IN) Pointer to user supplied data.
  15274  * Returns:
  15275  *     BCM_E_XXX
  15276  */
  15277 int
  15278 bcm_fp_oam_group_traverse(int unit, bcm_oam_group_traverse_cb cb,
  15279                            void *user_data)
  15280 {
  15281     int rv = BCM_E_UNAVAIL; /* Operation return status */
  15282     _bcm_fp_oam_control_t *oc = NULL;
  15283 
  15284     /* Get OAM control structure handle. */
  15285     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
  15286     
  15287     _BCM_OAM_LOCK(oc);
  15288 #if defined (INCLUDE_CCM)
  15289     if (soc_feature(unit, soc_feature_uc_ccm)) {
  15290         if (oc->ccm_ukernel_ready) {
  15291             rv = _bcm_fp_oam_ccm_group_traverse(unit, cb, user_data);
  15292 
  15293             if (BCM_FAILURE(rv)) {
  15294                 LOG_ERROR(BSL_LS_BCM_OAM,
  15295                             (BSL_META_U(unit,
  15296                                         "CCM(unit %d) Error: Group traverse "
  15297                                         "routine : %s.\n"), unit, bcm_errmsg(rv)));
  15298             }
  15299         }
  15300     }
  15301 #endif
  15302 #if defined (INCLUDE_BHH)
  15303     if (soc_feature(unit, soc_feature_bhh) &&
  15304         (oc->ukernel_not_ready == 0)){
  15305         rv = _bcm_fp_oam_bhh_group_traverse (unit, cb, user_data);
  15306     }
  15307 #endif
  15308     _BCM_OAM_UNLOCK(oc);
  15309     return (rv);
  15310 
  15311 }
  15312 
  15313 
  15314 /*
  15315  * Function:
  15316  *     bcm_fp_oam_loss_add
  15317  * Purpose:
  15318  *        Loss Measurement add
  15319  * Parameters:
  15320  *     unit - Device unit number
  15321  * Returns:
  15322  *     None
  15323  */
  15324 int
  15325 bcm_fp_oam_loss_add(int unit, bcm_oam_loss_t *loss_p)
  15326 {
  15327     int                    rv = BCM_E_UNAVAIL;
  15328 #if defined(INCLUDE_BHH) || defined(INCLUDE_MPLS_LM_DM)
  15329     _bcm_fp_oam_control_t *oc = NULL;
  15330 
  15331     /* Get OAM control structure handle. */
  15332     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
  15333     _BCM_OAM_LOCK(oc);
  15334 
  15335 #if defined (INCLUDE_BHH)
  15336     if (soc_feature(unit, soc_feature_bhh) &&
  15337         ((loss_p->id >= oc->bhh_base_endpoint_id) &&
  15338         (loss_p->id < (oc->bhh_base_endpoint_id + oc->bhh_endpoint_count)))) {
  15339         if (oc->ukernel_not_ready == 1){
  15340             LOG_ERROR(BSL_LS_BCM_OAM,
  15341                     (BSL_META_U(unit,
  15342                                 "OAM(unit %d) Error: BTE(ukernel) "
  15343                                 "not ready.\n"), unit));
  15344             _BCM_OAM_UNLOCK(oc);
  15345             return (BCM_E_INIT);
  15346         }
  15347         rv = _bcm_fp_oam_bhh_loss_add(unit, loss_p);
  15348     }
  15349 #endif /* INCLUDE_BHH */
  15350 
  15351 #if defined (INCLUDE_MPLS_LM_DM)
  15352     if(soc_feature(unit, soc_feature_mpls_lm_dm)) {
  15353         if(_MPLS_LM_DM_EP_ID_RANGE(loss_p->id)) {
  15354             rv = _bcm_fp_oam_mpls_lm_dm_loss_add(unit, loss_p);
  15355         }
  15356     }
  15357 #endif /* INCLUDE_MPLS_LM_DM */
  15358 
  15359     _BCM_OAM_UNLOCK(oc);
  15360 #endif /* INCLUDE_BHH || INCLUDE_MPLS_LM_DM */
  15361     return rv;
  15362 }
  15363 
  15364 /*
  15365  * Function:
  15366  *     bcm_fp_oam_loss_get
  15367  * Purpose:
  15368  *     Loss Measurement get
  15369  * Parameters:
  15370  *     unit - Device unit number
  15371  * Returns:
  15372  *     None
  15373  */
  15374 int
  15375 bcm_fp_oam_loss_get(int unit, bcm_oam_loss_t *loss_p)
  15376 {
  15377     int rv = BCM_E_UNAVAIL;
  15378 #if defined(INCLUDE_BHH) || defined(INCLUDE_MPLS_LM_DM)
  15379     _bcm_fp_oam_control_t *oc = NULL;
  15380 
  15381     /* Get OAM control structure handle. */
  15382     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
  15383     _BCM_OAM_LOCK(oc);
  15384 
  15385 #if defined (INCLUDE_BHH)
  15386     if (soc_feature(unit, soc_feature_bhh) &&
  15387         ((loss_p->id >= oc->bhh_base_endpoint_id) &&
  15388         (loss_p->id < (oc->bhh_base_endpoint_id + oc->bhh_endpoint_count)))) {
  15389         if (oc->ukernel_not_ready == 1){
  15390             LOG_ERROR(BSL_LS_BCM_OAM,
  15391                     (BSL_META_U(unit,
  15392                                 "OAM(unit %d) Error: BTE(ukernel) "
  15393                                 "not ready.\n"), unit));
  15394             _BCM_OAM_UNLOCK(oc);
  15395             return (BCM_E_INIT);
  15396         }
  15397         rv = _bcm_fp_oam_bhh_loss_get(unit, loss_p);
  15398     }
  15399 #endif /* INCLUDE_BHH */
  15400 
  15401 #if defined (INCLUDE_MPLS_LM_DM)
  15402     if(soc_feature(unit, soc_feature_mpls_lm_dm)) {
  15403         if(_MPLS_LM_DM_EP_ID_RANGE(loss_p->id)) {
  15404             rv = _bcm_fp_oam_mpls_lm_dm_loss_get(unit, loss_p);
  15405         }
  15406     }
  15407 #endif /* INCLUDE_MPLS_LM_DM */
  15408 
  15409     _BCM_OAM_UNLOCK(oc);
  15410 #endif /* INCLUDE_BHH || INCLUDE_MPLS_LM_DM */
  15411     return rv;
  15412 }
  15413 
  15414 /*
  15415  * Function:
  15416  *     bcm_fp_oam_loss_delete
  15417  * Purpose:
  15418  *    Loss Measurement Delete
  15419  * Parameters:
  15420  *     unit - Device unit number
  15421  * Returns:
  15422  *     None
  15423  */
  15424 int
  15425 bcm_fp_oam_loss_delete(int unit, bcm_oam_loss_t *loss_p)
  15426 {
  15427     int rv = BCM_E_UNAVAIL;
  15428 #if defined(INCLUDE_BHH) || defined(INCLUDE_MPLS_LM_DM)
  15429     _bcm_fp_oam_control_t *oc = NULL;
  15430 
  15431     /* Get OAM control structure handle. */
  15432     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
  15433     _BCM_OAM_LOCK(oc);
  15434 
  15435 #if defined (INCLUDE_BHH)
  15436     if (soc_feature(unit, soc_feature_bhh) &&
  15437         ((loss_p->id >= oc->bhh_base_endpoint_id) &&
  15438         (loss_p->id < (oc->bhh_base_endpoint_id + oc->bhh_endpoint_count)))) {
  15439         if (oc->ukernel_not_ready == 1){
  15440             LOG_ERROR(BSL_LS_BCM_OAM,
  15441                     (BSL_META_U(unit,
  15442                                 "OAM(unit %d) Error: BTE(ukernel) "
  15443                                 "not ready.\n"), unit));
  15444             _BCM_OAM_UNLOCK(oc);
  15445             return (BCM_E_INIT);
  15446         }
  15447         rv = _bcm_fp_oam_bhh_loss_delete(unit, loss_p);
  15448     }
  15449 #endif /* INCLUDE_BHH */
  15450 
  15451 #if defined (INCLUDE_MPLS_LM_DM)
  15452     if(soc_feature(unit, soc_feature_mpls_lm_dm)) {
  15453         if(_MPLS_LM_DM_EP_ID_RANGE(loss_p->id)) {
  15454             rv =  _bcm_fp_oam_mpls_lm_dm_loss_delete(unit, loss_p->id);
  15455         }
  15456     }
  15457 #endif /* INCLUDE_MPLS_LM_DM */
  15458 
  15459     _BCM_OAM_UNLOCK(oc);
  15460 #endif /* INCLUDE_BHH || INCLUDE_MPLS_LM_DM */
  15461     return rv;
  15462 }
  15463 
  15464 /*
  15465  * Function:
  15466  *     bcm_fp_oam_delay_add
  15467  * Purpose:
  15468  *     Delay Measurement add
  15469  * Parameters:
  15470  *     unit - Device unit number
  15471  * Returns:
  15472  *     None
  15473  */
  15474 int
  15475 bcm_fp_oam_delay_add(int unit, bcm_oam_delay_t *delay_p)
  15476 {
  15477     int rv = BCM_E_UNAVAIL;
  15478 #if defined(INCLUDE_BHH) || defined(INCLUDE_MPLS_LM_DM)
  15479     _bcm_fp_oam_control_t *oc = NULL;
  15480 
  15481     /* Get OAM control structure handle. */
  15482     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
  15483     _BCM_OAM_LOCK(oc);
  15484 
  15485 #if defined (INCLUDE_BHH)
  15486     if (soc_feature(unit, soc_feature_bhh) &&
  15487         ((delay_p->id >= oc->bhh_base_endpoint_id) &&
  15488         (delay_p->id < (oc->bhh_base_endpoint_id + oc->bhh_endpoint_count)))) {
  15489         if (oc->ukernel_not_ready == 1){
  15490             LOG_ERROR(BSL_LS_BCM_OAM,
  15491                     (BSL_META_U(unit,
  15492                                 "OAM(unit %d) Error: BTE(ukernel) "
  15493                                 "not ready.\n"), unit));
  15494             _BCM_OAM_UNLOCK(oc);
  15495             return (BCM_E_INIT);
  15496         }
  15497         rv = _bcm_fp_oam_bhh_delay_add(unit, delay_p);
  15498     }
  15499 #endif /* INCLUDE_BHH */
  15500 
  15501 #if defined (INCLUDE_MPLS_LM_DM)
  15502     if(soc_feature(unit, soc_feature_mpls_lm_dm)) {
  15503         if(_MPLS_LM_DM_EP_ID_RANGE(delay_p->id)) {
  15504             rv =  _bcm_fp_oam_mpls_lm_dm_delay_add(unit, delay_p);
  15505         }
  15506     }
  15507 #endif /* INCLUDE_MPLS_LM_DM */
  15508 
  15509     _BCM_OAM_UNLOCK(oc);
  15510 #endif /* INCLUDE_BHH || INCLUDE_MPLS_LM_DM */
  15511     return rv;
  15512 }
  15513 
  15514 /*
  15515  * Function:
  15516  *     bcm_fp_oam_delay_get
  15517  * Purpose:
  15518  *     Delay Measurements get
  15519  * Parameters:
  15520  *     unit - Device unit number
  15521  * Returns:
  15522  *     None
  15523  */
  15524 int
  15525 bcm_fp_oam_delay_get(int unit, bcm_oam_delay_t *delay_p)
  15526 {
  15527     int rv = BCM_E_UNAVAIL;
  15528 #if defined(INCLUDE_BHH) || defined(INCLUDE_MPLS_LM_DM)
  15529     _bcm_fp_oam_control_t *oc = NULL;
  15530 
  15531     /* Get OAM control structure handle. */
  15532     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
  15533     _BCM_OAM_LOCK(oc);
  15534 
  15535 #if defined (INCLUDE_BHH)
  15536     if (soc_feature(unit, soc_feature_bhh) &&
  15537         ((delay_p->id >= oc->bhh_base_endpoint_id) &&
  15538         (delay_p->id < (oc->bhh_base_endpoint_id + oc->bhh_endpoint_count)))) {
  15539         if (oc->ukernel_not_ready == 1){
  15540             LOG_ERROR(BSL_LS_BCM_OAM,
  15541                     (BSL_META_U(unit,
  15542                                 "OAM(unit %d) Error: BTE(ukernel) "
  15543                                 "not ready.\n"), unit));
  15544             _BCM_OAM_UNLOCK(oc);
  15545             return (BCM_E_INIT);
  15546         }
  15547         rv = _bcm_fp_oam_bhh_delay_get(unit, delay_p);
  15548     }
  15549 #endif /* INCLUDE_BHH */
  15550 
  15551 #if defined (INCLUDE_MPLS_LM_DM)
  15552     if(soc_feature(unit, soc_feature_mpls_lm_dm)) {
  15553         if(_MPLS_LM_DM_EP_ID_RANGE(delay_p->id)) {
  15554             rv = _bcm_fp_oam_mpls_lm_dm_delay_get(unit, delay_p);
  15555         }
  15556     }
  15557 #endif /* INCLUDE_MPLS_LM_DM */
  15558 
  15559     _BCM_OAM_UNLOCK(oc);
  15560 #endif /* INCLUDE_BHH || INCLUDE_MPLS_LM_DM */
  15561     return rv;
  15562 }
  15563 
  15564 /*
  15565  * Function:
  15566  *     bcm_fp_oam_delay_delete
  15567  * Purpose:
  15568  *     Delay Measurement Delete
  15569  * Parameters:
  15570  *     unit - Device unit number
  15571  * Returns:
  15572  *     None
  15573  */
  15574 int
  15575 bcm_fp_oam_delay_delete(int unit, bcm_oam_delay_t *delay_p)
  15576 {
  15577     int rv = BCM_E_UNAVAIL;
  15578 #if defined(INCLUDE_BHH) || defined(INCLUDE_MPLS_LM_DM)
  15579     _bcm_fp_oam_control_t *oc = NULL;
  15580 
  15581     /* Get OAM control structure handle. */
  15582     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
  15583     _BCM_OAM_LOCK(oc);
  15584 
  15585 #if defined (INCLUDE_BHH)
  15586     if (soc_feature(unit, soc_feature_bhh) &&
  15587         ((delay_p->id >= oc->bhh_base_endpoint_id) &&
  15588         (delay_p->id < (oc->bhh_base_endpoint_id + oc->bhh_endpoint_count)))) {
  15589         if (oc->ukernel_not_ready == 1){
  15590             LOG_ERROR(BSL_LS_BCM_OAM,
  15591                     (BSL_META_U(unit,
  15592                                 "OAM(unit %d) Error: BTE(ukernel) "
  15593                                 "not ready.\n"), unit));
  15594             _BCM_OAM_UNLOCK(oc);
  15595             return (BCM_E_INIT);
  15596         }
  15597         rv = _bcm_fp_oam_bhh_delay_delete(unit, delay_p);
  15598     }
  15599 #endif /* INCLUDE_BHH */
  15600 
  15601 #if defined (INCLUDE_MPLS_LM_DM)
  15602     if(soc_feature(unit, soc_feature_mpls_lm_dm)) {
  15603         if(_MPLS_LM_DM_EP_ID_RANGE(delay_p->id)) {
  15604             rv = _bcm_fp_oam_mpls_lm_dm_delay_delete(unit, delay_p->id);
  15605         }
  15606     }
  15607 #endif /* INCLUDE_MPLS_LM_DM */
  15608 
  15609     _BCM_OAM_UNLOCK(oc);
  15610 #endif /* INCLUDE_BHH || INCLUDE_MPLS_LM_DM */
  15611     return rv;
  15612 }
  15613 
  15614 /*
  15615  * Function:
  15616  *     _bcm_fp_oam_sync
  15617  * Purpose:
  15618  *     Store OAM configuration to level two storage cache memory.
  15619  * Parameters:
  15620  *     unit - (IN) Device unit number
  15621  * Returns:
  15622  *     BCM_E_XXX
  15623  */
  15624 int
  15625 _bcm_fp_oam_sync(int unit)
  15626 {
  15627     int rv = BCM_E_UNAVAIL;
  15628 
  15629 #if defined(BCM_WARM_BOOT_SUPPORT)
  15630 #if defined(INCLUDE_BHH)
  15631     if (soc_feature(unit, soc_feature_bhh)) {
  15632         BCM_IF_ERROR_RETURN(_bcm_fp_oam_bhh_sync(unit));
  15633     }
  15634 #endif /* INCLUDE_BHH */
  15635 
  15636 #if defined(INCLUDE_MPLS_LM_DM)
  15637     if (soc_feature(unit, soc_feature_mpls_lm_dm)) {
  15638         BCM_IF_ERROR_RETURN(_bcm_fp_oam_mpls_lm_dm_sync(unit));
  15639     }
  15640 #endif /* INCLUDE_MPLS_LM_DM */
  15641 #endif /* BCM_WARM_BOOT_SUPPORT */
  15642 
  15643     return rv;
  15644 }
  15645 
  15646 
  15647 #endif /*INCLUDE_CCM || INCLUDE_BHH || INCLUDE_MPLS_LM_DM */
  15648 /*******************************************************************************/
  15649 /* Common routines for CCM, BHH & MPLS LM/DM App end */
  15650 /*******************************************************************************/
  15651 
  15652 
  15653 
  15654 /*
  15655  * Function: bcm_td2p_oam_init
  15656  *
  15657  * Purpose:
  15658  *     Initialize OAM module.
  15659  * Parameters:
  15660  *     unit - (IN) BCM device number
  15661  * Returns:
  15662  *     BCM_E_UNIT    - Invalid BCM unit number.
  15663  *     BCM_E_UNAVAIL - OAM not support on this device.
  15664  *     BCM_E_MEMORY  - Allocation failure
  15665  *     CM_E_XXX     - Error code from bcm_XX_oam_init()
  15666  *     BCM_E_NONE    - Success
  15667  */
  15668 int
  15669 bcm_td2p_oam_init(int unit)
  15670 {
  15671     int rv;             /* Operation return value. */
  15672 #if defined (INCLUDE_CCM) || defined (INCLUDE_BHH)
  15673     uint32 size = 0;    /* Size of memory allocation. */
  15674 #endif /* INCLUDE_CCM || INCLUDE_BHH */
  15675 
  15676 #if defined(INCLUDE_CCM) || defined(INCLUDE_BHH) || defined(INCLUDE_MPLS_LM_DM)
  15677     _bcm_fp_oam_control_t *oc = NULL;  /* OAM control structure. */
  15678 #endif /* INCLUDE_CCM || INCLUDE_BHH || INCLUDE_MPLS_LM_DM */
  15679 
  15680 #if defined (INCLUDE_BHH)
  15681     int uc = 0;
  15682     uint8 *buffer, *buffer_ptr;
  15683     uint16 buffer_len, reply_len;
  15684 #endif /* INCLUDE_BHH */
  15685 
  15686 #if defined (INCLUDE_CCM) || defined (INCLUDE_BHH) || defined(INCLUDE_MPLS_LM_DM)
  15687     if(soc_feature(unit, soc_feature_uc_ccm) ||
  15688        soc_feature(unit, soc_feature_bhh)    ||
  15689        soc_feature(unit, soc_feature_mpls_lm_dm)) {
  15690 
  15691         /* Detach first if the module has been previously initialized. */
  15692         if (NULL != _fp_oam_control[unit]) {
  15693             _fp_oam_control[unit]->init = FALSE;
  15694             rv = bcm_fp_oam_detach(unit);
  15695             if (BCM_FAILURE(rv)) {
  15696                 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: "
  15697                                 "Module deinit - %s.\n"), bcm_errmsg(rv)));
  15698                 return (rv);
  15699             }
  15700         }
  15701 
  15702 
  15703         /* Allocate OAM control memory for this unit. */
  15704         _BCM_OAM_ALLOC(oc, _bcm_fp_oam_control_t,
  15705                 sizeof(_bcm_fp_oam_control_t), "OAM control");
  15706         if (NULL == oc) {
  15707             return (BCM_E_MEMORY);
  15708         }
  15709 
  15710         /* Create protection mutex. */
  15711         oc->oc_lock = sal_mutex_create("oam_control.lock");
  15712         if (NULL == oc->oc_lock) {
  15713             _bcm_fp_oam_control_free(unit, oc);
  15714             return (BCM_E_MEMORY);
  15715         }
  15716 
  15717         /* Set up the unit OAM control structure. */
  15718         _fp_oam_control[unit] = oc;
  15719 
  15720         /* Get number of endpoints and groups supported by this unit. */
  15721         rv = _bcm_fp_oam_resource_count_init(unit, oc);
  15722         if (BCM_FAILURE(rv)) {
  15723             _bcm_fp_oam_control_free(unit, oc);
  15724             return (rv);
  15725         }
  15726         oc->unit = unit;
  15727 
  15728     }
  15729 #endif /* INCLUDE_CCM || INCLUDE_BHH || INCLUDE_MPLS_LM_DM */
  15730 
  15731     /* Initialize PM */
  15732 #if defined (INCLUDE_BHH) || defined(INCLUDE_MPLS_LM_DM)
  15733     if (soc_feature(unit, soc_feature_oam_pm)) {
  15734         rv = _bcm_fp_oam_pm_init(unit);
  15735         if (BCM_FAILURE(rv)) {
  15736             _bcm_fp_oam_control_free(unit, oc);
  15737             return (rv);
  15738         }
  15739     }
  15740 #endif /* INCLUDE_BHH || INCLUDE_MPLS_LM_DM */
  15741 
  15742 #if defined (INCLUDE_CCM)
  15743     if(soc_feature(unit, soc_feature_uc_ccm)) {
  15744         shr_ccm_msg_ctrl_init_t ccm_init_msg;
  15745         uint8 *buffer_p1 = NULL;
  15746         uint8 *buffer_p2 = NULL;
  15747         uint16 s_len = 0;
  15748         uint16 r_len = 0;
  15749 
  15750         
  15751         /* Core #0 is used for CCM in Saber2*/
  15752         if (soc_uc_in_reset(unit, _CCM_UC_NUM)) {
  15753 
  15754             LOG_WARN(BSL_LS_BCM_OAM, (BSL_META_U(unit, "CCM Warn:"
  15755                       " uKernel Not Ready, CCM not started.\n If CCM"
  15756                       " app is not not needed, compile SDK by excluding CCM"
  15757                       " from FEATURE_LIST.\n")));
  15758 
  15759         } else {
  15760 
  15761             /* Initialize uController side
  15762              * Start CCM application in BTE (Broadcom Task Engine) uController.
  15763              * _CCM_UC_NUM runs the CCM Application.
  15764              */
  15765             rv = soc_cmic_uc_appl_init(unit, _CCM_UC_NUM, MOS_MSG_CLASS_CCM,
  15766                     _UC_MSG_TIMEOUT_USECS, _CCM_SDK_VERSION,
  15767                     _CCM_UC_MIN_VERSION, NULL, NULL);
  15768 
  15769             if (!(BCM_FAILURE(rv))) {
  15770 
  15771                 /* Create Group list.*/
  15772                 rv = shr_idxres_list_create(&oc->group_pool, 0, 
  15773                                         oc->group_count - 1,
  15774                                         0, oc->group_count - 1, "group pool");
  15775                 if (BCM_FAILURE(rv)) {
  15776                     _bcm_fp_oam_control_free(unit, oc);
  15777                     return (rv);
  15778                 }
  15779                 
  15780                 /* Allocate group memory */
  15781                 size = sizeof(_bcm_fp_oam_group_data_t) * oc->group_count;
  15782                 _BCM_OAM_ALLOC(oc->group_data, _bcm_fp_oam_group_data_t, size,
  15783                         "Group Info");
  15784                 if (BCM_FAILURE(rv)) {
  15785                     LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "CCM Error: "
  15786                         "Group data Alloca failed - %s.\n"), bcm_errmsg(rv)));
  15787                     _bcm_fp_oam_control_free(unit, oc);
  15788                     return (rv);
  15789                 }
  15790 
  15791                 /* Create Mep list. */
  15792                 rv = shr_idxres_list_create(&oc->mep_pool, 0, oc->mep_count - 1,
  15793                                             0, oc->mep_count - 1, "mep pool");
  15794                 if (BCM_FAILURE(rv)) {
  15795                     _bcm_fp_oam_control_free(unit, oc);
  15796                     return (rv);
  15797                 }
  15798 
  15799                 /* Allocate group memory */
  15800                 size = sizeof(_bcm_fp_oam_mep_data_t) * oc->mep_count;
  15801                 _BCM_OAM_ALLOC(oc->mep_data, _bcm_fp_oam_mep_data_t, size,
  15802                         "MEP Info");
  15803                 if (BCM_FAILURE(rv)) {
  15804                     LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "CCM Error: "
  15805                         "MEP data Alloca failed - %s.\n"), bcm_errmsg(rv)));
  15806                     _bcm_fp_oam_control_free(unit, oc);
  15807                     return (rv);
  15808                 }            
  15809 
  15810                 /* Allocate DMA Memory */
  15811                 oc->dma_buffer_len = sizeof(shr_ccm_msg_ctrl_t);
  15812                 oc->dma_buffer = soc_cm_salloc(unit, oc->dma_buffer_len,
  15813                                                "CCM DMA buffer");
  15814                 if (!oc->dma_buffer) {
  15815                     _bcm_fp_oam_control_free(unit, oc);
  15816                     return (BCM_E_MEMORY);
  15817                 }
  15818 
  15819                 oc->ccm_ukernel_ready = 1;
  15820                 oc->ccm_uc_num = _CCM_UC_NUM;
  15821 
  15822                 /* Send Initialize CCM App on UKERNEL */
  15823                 /* Set control message data */
  15824                 sal_memset(&ccm_init_msg, 0, sizeof(ccm_init_msg));
  15825                 ccm_init_msg.max_groups = oc->group_count;
  15826                 ccm_init_msg.max_meps = oc->mep_count;
  15827                 ccm_init_msg.rx_channel = _CCM_RX_CHANNEL_ID;
  15828 
  15829                 /* Pack control message data into DMA buffer */
  15830                 buffer_p1 = oc->dma_buffer;
  15831                 buffer_p2 = shr_ccm_msg_ctrl_init_pack(buffer_p1, &ccm_init_msg);
  15832                 s_len = buffer_p2 - buffer_p1;
  15833 
  15834                 /* Send CCM Init message to uC */
  15835                 rv = _bcm_fp_oam_msg_send_receive(unit, MOS_MSG_CLASS_CCM,
  15836                        MOS_MSG_SUBCLASS_CCM_INIT, s_len, 0,
  15837                        MOS_MSG_SUBCLASS_CCM_INIT_REPLY, &r_len);
  15838 
  15839                 if (BCM_FAILURE(rv) || (r_len != 0)) {
  15840                    /* Could not start MPLS_LM_DM appl */
  15841                    LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: "
  15842                        "CCM Session alloc failed\n")));
  15843                    BCM_IF_ERROR_RETURN(bcm_fp_oam_detach(unit));
  15844                    return rv;
  15845                 }
  15846 
  15847                 /* If we have Warmrebooted, recover S/w state from UKENREL */
  15848 #ifdef BCM_WARM_BOOT_SUPPORT
  15849                 if (SOC_WARM_BOOT(unit)) {
  15850                     rv = _bcm_fp_oam_ccm_reinit(unit);
  15851                     if (BCM_FAILURE(rv)) {
  15852                         BCM_IF_ERROR_RETURN(bcm_fp_oam_detach(unit));
  15853                         return (rv);
  15854                     }
  15855                 }
  15856 #endif
  15857                 /* Start event message callback thread */
  15858                 if (oc->event_thread_id == NULL) {
  15859                     oc->event_thread_id =  sal_thread_create("bcmCCM",
  15860                         SAL_THREAD_STKSZ, _FP_OAM_CCM_EVENT_THREAD_PRIO,
  15861                         _bcm_fp_oam_ccm_callback_thread, (void*)oc);
  15862                     if (oc->event_thread_id == SAL_THREAD_ERROR) {
  15863                          oc->event_thread_id = NULL;
  15864                          BCM_IF_ERROR_RETURN(bcm_fp_oam_detach(unit));
  15865                         return (BCM_E_MEMORY);
  15866                     }
  15867                 }
  15868 
  15869             } else {
  15870                 /* Could not start CCM appl */
  15871                 LOG_WARN(BSL_LS_BCM_OAM, (BSL_META_U(unit,
  15872                          "OAM WARN: CCM Application not available\n")));
  15873                 /* Most likely core 0 has a different Application image */
  15874             }
  15875         }
  15876     } /* soc_feature_ccm */
  15877 #endif /* INCLUDE_CCM */
  15878 
  15879 #if defined (INCLUDE_BHH)
  15880     if (soc_feature(unit, soc_feature_bhh)) {
  15881 
  15882         uint8 carrier_code[] = {0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF};
  15883         char *carrier_code_str;
  15884         uint32 node_id = 0;
  15885         bhh_sdk_msg_ctrl_init_t msg_init;
  15886         int priority;
  15887         int ukernel_not_ready = 0;
  15888         uint8 bhh_consolidate_final_event = 0;
  15889         int uc_status;
  15890  
  15891         /*
  15892          * Start BHH application in BTE (Broadcom Task Engine) uController,
  15893          * if not already running (warm boot).
  15894          * Determine which uController is running BHH  by choosing the first
  15895          * uC that returns successfully.
  15896          */
  15897         for (uc = 0; uc < SOC_INFO(unit).num_ucs; uc++) {
  15898             rv = soc_uc_status(unit, uc, &uc_status);
  15899             if ((rv == SOC_E_NONE) && (uc_status != 0)) {
  15900                 rv = soc_cmic_uc_appl_init(unit, uc, MOS_MSG_CLASS_BHH,
  15901                         _BHH_UC_MSG_TIMEOUT_USECS,
  15902                         BHH_SDK_VERSION,
  15903                         BHH_UC_MIN_VERSION, _bcm_oam_bhh_appl_callback, NULL);
  15904                 if (SOC_E_NONE == rv) {
  15905                     /* BHH started successfully */
  15906                     oc->bhh_uc_num = uc;
  15907                     break;
  15908                 }
  15909             }
  15910         }
  15911 
  15912         if (uc >= SOC_INFO(unit).num_ucs) {/* Could not find or start BHH appl */
  15913             ukernel_not_ready = 1;
  15914             LOG_ERROR(BSL_LS_BCM_OAM,
  15915                     (BSL_META_U(unit,
  15916                                 "uKernel Not Ready, bhh not started\n")));
  15917         }
  15918         oc->ukernel_not_ready = ukernel_not_ready;
  15919 
  15920         if(ukernel_not_ready == 0){
  15921             /* Create BHH Group list.*/
  15922             /* BHH groups are equalent to BHH endpoints - 1 to 1 mapping*/
  15923             rv = shr_idxres_list_create(&oc->bhh_group_pool, 0, 
  15924                     oc->bhh_endpoint_count - 1,
  15925                     0, oc->bhh_endpoint_count - 1, "BHH group pool");
  15926             if (BCM_FAILURE(rv)) {
  15927                 BCM_IF_ERROR_RETURN(bcm_fp_oam_detach(unit));
  15928                 return (rv);
  15929             }
  15930             /* Allocate BHH group memory */
  15931             size = sizeof(_bhh_fp_oam_group_data_t) * oc->bhh_endpoint_count;
  15932             _BCM_OAM_ALLOC(oc->bhh_group_data, _bhh_fp_oam_group_data_t, size,
  15933                     "BHH Group Info");
  15934 
  15935             if (NULL == oc->bhh_group_data) {
  15936                 BCM_IF_ERROR_RETURN(bcm_fp_oam_detach(unit));
  15937                 return (BCM_E_MEMORY);
  15938             }
  15939 
  15940             /* Mem_1: Allocate BHH endpoints hash data memory */
  15941             size = sizeof(_bhh_fp_oam_ep_data_t) * oc->bhh_endpoint_count;
  15942             _BCM_OAM_ALLOC(oc->bhh_ep_data, _bhh_fp_oam_ep_data_t, 
  15943                     size, "Hash data");
  15944             if (NULL == oc->bhh_ep_data) {
  15945                 BCM_IF_ERROR_RETURN(bcm_fp_oam_detach(unit));
  15946                 return (BCM_E_MEMORY);
  15947             }
  15948             /*Calculating hash table size (which should be power of 2) 
  15949               from the given number of BHH 
  15950               endpoints to the nearest power of 2*/
  15951             int hash_size = 1;
  15952             if (oc->bhh_endpoint_count && !(oc->bhh_endpoint_count & 
  15953                                            (oc->bhh_endpoint_count - 1))){
  15954                 hash_size = oc->bhh_endpoint_count;
  15955             } else {
  15956                 while (hash_size < oc->bhh_endpoint_count) {
  15957                     hash_size <<= 1;
  15958                 }
  15959             }
  15960             rv = shr_htb_create(&oc->bhh_mep_htbl, hash_size,
  15961                     sizeof(_bhh_fp_oam_hash_key_t), "BHH MEP Hash");
  15962             if (BCM_FAILURE(rv)) {
  15963                 BCM_IF_ERROR_RETURN(bcm_fp_oam_detach(unit));
  15964                 return (rv);
  15965             }
  15966 
  15967             /* Create BHH endpoint indices list. */
  15968             rv = shr_idxres_list_create(&oc->bhh_pool, 0, 
  15969                     oc->bhh_endpoint_count - 1,
  15970                     0, oc->bhh_endpoint_count - 1, "bhh pool");
  15971             if (BCM_FAILURE(rv)) {
  15972                 LOG_ERROR(BSL_LS_BCM_OAM,
  15973                         (BSL_META_U(unit,
  15974                                     "OAM(unit %d) Error: Creating BHH pool " 
  15975                                     "failed \n"),
  15976                          unit));
  15977                 BCM_IF_ERROR_RETURN(bcm_fp_oam_detach(unit));
  15978                 return (rv);
  15979             }
  15980 
  15981             node_id = soc_property_get(unit, spn_BHH_NODE_ID, 0);
  15982             bhh_consolidate_final_event = soc_property_get(unit, 
  15983                                            spn_BHH_CONSOLIDATED_FINAL_EVENT, 0);
  15984 
  15985             carrier_code_str = soc_property_get_str(unit, spn_BHH_CARRIER_CODE);
  15986             if (carrier_code_str != NULL) {
  15987                 /*
  15988                  * Note that the carrier code is specified in colon separated
  15989                  * MAC address format.
  15990                  */
  15991                 if (_shr_parse_macaddr(carrier_code_str, carrier_code) < 0) {
  15992                     BCM_IF_ERROR_RETURN(bcm_fp_oam_detach(unit));
  15993                     return (BCM_E_INTERNAL);
  15994                 }
  15995             }
  15996 
  15997             oc->bhh_max_encap_length =
  15998                              soc_property_get(unit,
  15999                                               spn_BHH_ENCAP_MAX_LENGTH,
  16000                                               _BCM_OAM_BHH_DEFAULT_ENCAP_LENGTH);
  16001 
  16002             if(oc->bhh_max_encap_length > _BCM_OAM_BHH_MAX_ENCAP_LENGTH) {
  16003                 LOG_ERROR(BSL_LS_BCM_OAM,
  16004                           (BSL_META_U(unit,
  16005                                       "Invalid max encap_length=%u\n"),
  16006                                       oc->bhh_max_encap_length));
  16007                 return BCM_E_CONFIG;
  16008             }
  16009 
  16010             if (soc_feature(unit, soc_feature_oam_pm)) {
  16011                 rv = _bcm_fp_oam_bhh_pm_init(unit);
  16012                 if (BCM_FAILURE(rv)) {
  16013                     BCM_IF_ERROR_RETURN(bcm_fp_oam_detach(unit));
  16014                     return (BCM_E_INTERNAL);
  16015                 }
  16016             }
  16017 
  16018             /*
  16019              * Allocate DMA buffers
  16020              *
  16021              * DMA buffer will be used to send and receive 'long' messages
  16022              * between SDK Host and uController (BTE).
  16023              */
  16024             oc->bhh_dma_buffer_len = sizeof(bhh_sdk_msg_ctrl_t);
  16025             oc->bhh_dma_buffer = soc_cm_salloc(unit, oc->bhh_dma_buffer_len,
  16026                                            "BHH DMA buffer");
  16027             if (!oc->bhh_dma_buffer) {
  16028                 BCM_IF_ERROR_RETURN(bcm_fp_oam_detach(unit));
  16029                 LOG_ERROR(BSL_LS_BCM_OAM,
  16030                         (BSL_META_U(unit,
  16031                                     "OAM(unit %d) Error: Allocating BHH buffer" 
  16032                                     " failed \n"),
  16033                          unit));
  16034                 return (BCM_E_MEMORY);
  16035             }
  16036             sal_memset(oc->bhh_dma_buffer, 0, oc->bhh_dma_buffer_len);
  16037 
  16038             oc->bhh_dmabuf_reply = soc_cm_salloc(unit, sizeof(bhh_sdk_msg_ctrl_t),
  16039                                              "BHH uC reply");
  16040             if (!oc->bhh_dmabuf_reply) {
  16041                 LOG_ERROR(BSL_LS_BCM_OAM,
  16042                         (BSL_META_U(unit,
  16043                                     "OAM(unit %d) Error: Allocating BHH reply " 
  16044                                     "buffer failed \n"),
  16045                          unit));
  16046                 BCM_IF_ERROR_RETURN(bcm_fp_oam_detach(unit));
  16047                 return (BCM_E_MEMORY);
  16048             }
  16049             sal_memset(oc->bhh_dmabuf_reply, 0, sizeof(bhh_sdk_msg_ctrl_t));
  16050 
  16051 
  16052             /* RX DMA channel (0..3) local to the uC */
  16053             oc->rx_channel = BCM_KT_BHH_RX_CHANNEL;
  16054 #ifdef BCM_WARM_BOOT_SUPPORT
  16055             if (!SOC_WARM_BOOT(unit)) {
  16056                 rv = _bcm_fp_oam_bhh_scache_alloc(unit);
  16057                 if ((BCM_E_NOT_FOUND != rv) && (BCM_FAILURE(rv))) {
  16058                     BCM_IF_ERROR_RETURN(bcm_fp_oam_detach(unit));
  16059                     return (rv);
  16060                 }
  16061 #endif
  16062                 /* Set control message data */
  16063                 sal_memset(&msg_init, 0, sizeof(msg_init));
  16064                 msg_init.num_sessions       = oc->bhh_endpoint_count;
  16065                 msg_init.rx_channel         = oc->rx_channel;
  16066                 msg_init.node_id            = node_id;
  16067                 sal_memcpy(msg_init.carrier_code, carrier_code,
  16068                            SHR_BHH_CARRIER_CODE_LEN);
  16069                 if (soc_feature(unit, soc_feature_oam_pm)) {
  16070                     msg_init.data_collection_mode = 
  16071                                   oc->pm_bhh_lmdm_data_collection_mode;
  16072                 }
  16073 
  16074                 msg_init.max_encap_length = oc->bhh_max_encap_length;
  16075                 if (bhh_consolidate_final_event) {
  16076                     msg_init.flags |= BHH_SDK_MSG_CTRL_INIT_ONLY_FINAL_EVENT;
  16077                 }
  16078                 /* Pack control message data into DMA buffer */
  16079                 buffer     = oc->bhh_dma_buffer;
  16080                 buffer_ptr = bhh_sdk_msg_ctrl_init_pack(unit, buffer, &msg_init);
  16081                 buffer_len = buffer_ptr - buffer;
  16082 
  16083                 /* Send BHH Init message to uC */
  16084                 rv = _bcm_fp_oam_msg_send_receive(unit,
  16085                                                  MOS_MSG_CLASS_BHH, 
  16086                                                  MOS_MSG_SUBCLASS_BHH_INIT,
  16087                                                  buffer_len, 0,
  16088                                                  MOS_MSG_SUBCLASS_BHH_INIT_REPLY,
  16089                                                  &reply_len);
  16090 
  16091                 if (BCM_FAILURE(rv) || (reply_len != 0)) {
  16092                     BCM_IF_ERROR_RETURN(bcm_fp_oam_detach(unit));
  16093                     LOG_ERROR(BSL_LS_BCM_OAM,
  16094                             (BSL_META_U(unit,
  16095                                         "OAM(unit %d) Error: BHH init " 
  16096                                         "failed \n"),
  16097                              unit));
  16098                     return (BCM_E_INTERNAL);
  16099                 }
  16100 
  16101 #ifdef BCM_WARM_BOOT_SUPPORT
  16102             } else if (SOC_WARM_BOOT(unit)) {
  16103                 rv = _bcm_fp_oam_bhh_reinit(unit);
  16104                 if (BCM_FAILURE(rv)) {
  16105                     BCM_IF_ERROR_RETURN(bcm_fp_oam_detach(unit));
  16106                     return (rv);
  16107                 }
  16108             }
  16109 #endif
  16110 
  16111             /*
  16112              * Start event message callback thread
  16113              */
  16114             priority = soc_property_get(unit, spn_BHH_THREAD_PRI,
  16115                                         BHH_THREAD_PRI_DFLT);
  16116 
  16117             if (oc->bhh_event_thread_id == NULL) {
  16118                 if ((oc->bhh_event_thread_id =
  16119                     sal_thread_create("bcmBHH", SAL_THREAD_STKSZ,
  16120                                       priority,
  16121                                       _bcm_fp_oam_bhh_callback_thread,
  16122                                       (void*)oc)) == SAL_THREAD_ERROR) {
  16123                     oc->bhh_event_thread_id = NULL;
  16124                     BCM_IF_ERROR_RETURN(bcm_fp_oam_detach(unit));
  16125                     return (BCM_E_MEMORY);
  16126                 }
  16127             }
  16128         }
  16129     }
  16130 #endif /* INCLUDE_BHH */
  16131 
  16132 #if defined(INCLUDE_MPLS_LM_DM)
  16133     if (soc_feature(unit, soc_feature_mpls_lm_dm)) {
  16134         rv = _bcm_fp_oam_mpls_lm_dm_init(unit, oc);
  16135         if (rv != BCM_E_NONE) {
  16136             BCM_IF_ERROR_RETURN(bcm_fp_oam_detach(unit));
  16137             return rv;
  16138         }
  16139     }
  16140 #endif /* INCLUDE_MPLS_LM_DM */
  16141 
  16142 #if defined(BCM_WARM_BOOT_SUPPORT)
  16143     if (!SOC_WARM_BOOT(unit))
  16144 #endif
  16145     {
  16146         /* Set default olp header type mapping */
  16147         rv = _bcm_td2p_oam_olp_header_type_mapping_set(unit);
  16148         if (BCM_FAILURE(rv)) {
  16149             return (rv);
  16150         }
  16151 
  16152         /* Enable OLP on HG ports */
  16153         BCM_IF_ERROR_RETURN(_bcm_td2p_oam_hg_olp_enable(unit));
  16154 
  16155         /* Set Magic port used for remote OLP over HG communication */
  16156         BCM_IF_ERROR_RETURN(_bcm_td2p_oam_olp_magic_port_set(unit));
  16157 
  16158 #if defined (BCM_APACHE_SUPPORT)
  16159         if(SOC_IS_APACHE(unit)) {
  16160             BCM_IF_ERROR_RETURN(_bcm_apache_oam_default_hw_config_set(unit));
  16161         }
  16162 #endif /* BCM_APACHE_SUPPORT */
  16163     }
  16164     return (BCM_E_NONE);
  16165 }
  16166 
  16167 #if defined(INCLUDE_CCM)
  16168 void
  16169 _bcm_fp_oam_ccm_hash_data_dump(int unit, _bcm_fp_oam_mep_data_t *ep_p)
  16170 {
  16171     LOG_CLI((BSL_META_U(unit,"Flags = 0x%x\r\n"),ep_p->mep_data.flags));
  16172     LOG_CLI((BSL_META_U(unit,"EP ID = %d\r\n"),ep_p->mep_data.ep_id));
  16173     LOG_CLI((BSL_META_U(unit,"Grp id = %d\r\n"),ep_p->mep_data.group_id));
  16174     LOG_CLI((BSL_META_U(unit,"Src Mac = %02X:%02X:%02X:%02X:%02X:%02X\r\n"),
  16175              ep_p->mep_data.sa[0], ep_p->mep_data.sa[1],
  16176              ep_p->mep_data.sa[2], ep_p->mep_data.sa[3],
  16177              ep_p->mep_data.sa[4], ep_p->mep_data.sa[5]));
  16178     LOG_CLI((BSL_META_U(unit,"Dst Mac = %02X:%02X:%02X:%02X:%02X:%02X\r\n"),
  16179              ep_p->mep_data.da[0], ep_p->mep_data.da[1],
  16180              ep_p->mep_data.da[2], ep_p->mep_data.da[3],
  16181              ep_p->mep_data.da[4], ep_p->mep_data.da[5]));
  16182     LOG_CLI((BSL_META_U(unit,"Type = %d\r\n"),ep_p->mep_data.type));
  16183     LOG_CLI((BSL_META_U(unit,"Level = %d\r\n"),ep_p->mep_data.level));
  16184     LOG_CLI((BSL_META_U(unit,"Name = %d\r\n"),ep_p->mep_data.name));
  16185     LOG_CLI((BSL_META_U(unit,"Period = %d\r\n"),ep_p->mep_data.period));
  16186     LOG_CLI((BSL_META_U(unit,"Outer Vlan = %d\r\n"),ep_p->mep_data.vlan));
  16187     LOG_CLI((BSL_META_U(unit,"Inner Vlan = %d\r\n"),ep_p->mep_data.inner_vlan));
  16188     LOG_CLI((BSL_META_U(unit,"pkt pri = 0x%x\r\n"),ep_p->mep_data.pkt_pri));
  16189     LOG_CLI((BSL_META_U(unit,"Inner Vlan Pri = %d\r\n"),ep_p->mep_data.inner_vlan_pri));
  16190     LOG_CLI((BSL_META_U(unit,"Outer TPID = 0x%04X\r\n"),ep_p->mep_data.tpid));
  16191     LOG_CLI((BSL_META_U(unit,"Inner TPID = 0x%04X\r\n"),ep_p->mep_data.inner_tpid));
  16192     LOG_CLI((BSL_META_U(unit,"Gport = %d\r\n"),ep_p->mep_data.gport));
  16193     LOG_CLI((BSL_META_U(unit,"SGLP = %d\r\n"),ep_p->mep_data.sglp));
  16194     LOG_CLI((BSL_META_U(unit,"DGLP = %d\r\n"),ep_p->mep_data.dglp));
  16195     LOG_CLI((BSL_META_U(unit,"Trunk Index = %d\r\n"),ep_p->mep_data.trunk_index));
  16196     LOG_CLI((BSL_META_U(unit,"Faults = %d\r\n"),ep_p->mep_data.faults));
  16197     LOG_CLI((BSL_META_U(unit,"persistent_faults = %d\r\n"),
  16198                         ep_p->mep_data.persistent_faults));
  16199     LOG_CLI((BSL_META_U(unit,"port_state = %d\r\n"),
  16200                         ep_p->mep_data.port_state));
  16201     LOG_CLI((BSL_META_U(unit,"intf_state = %d\r\n"),
  16202                         ep_p->mep_data.intf_state));
  16203     LOG_CLI((BSL_META_U(unit,"num_ctrs = %d\r\n\n"),
  16204                         ep_p->mep_data.num_ctrs));
  16205 }
  16206 #endif /* INCLUDE_CCM */
  16207 
  16208 #if defined(INCLUDE_MPLS_LM_DM)
  16209 void
  16210 _bcm_fp_oam_mpls_lm_dm_hash_data_dump(int unit, _bcm_fp_oam_mpls_lm_dm_ep_data_t *ep_p)
  16211 {
  16212     LOG_CLI((BSL_META_U(unit,"EP ID = %d\r\n"),ep_p->id));
  16213     LOG_CLI((BSL_META_U(unit,"Flags = 0x%x\r\n"),ep_p->flags));
  16214     LOG_CLI((BSL_META_U(unit,"Type = %d\r\n"),ep_p->type));
  16215     LOG_CLI((BSL_META_U(unit,"VCCV_TYPE = %d\r\n"),ep_p->vccv_type));
  16216     LOG_CLI((BSL_META_U(unit,"Gport = %d\r\n"),ep_p->gport));
  16217     LOG_CLI((BSL_META_U(unit,"Tx_Gport = %d\r\n"),ep_p->tx_gport));
  16218     LOG_CLI((BSL_META_U(unit,"Trunk Index = %d\r\n"),ep_p->trunk_index));
  16219     LOG_CLI((BSL_META_U(unit,"Src Mac = %02X:%02X:%02X:%02X:%02X:%02X\r\n"),
  16220              ep_p->src_mac[0], ep_p->src_mac[1],
  16221              ep_p->src_mac[2], ep_p->src_mac[3],
  16222              ep_p->src_mac[4], ep_p->src_mac[5]));
  16223     LOG_CLI((BSL_META_U(unit,"Dst Mac = %02X:%02X:%02X:%02X:%02X:%02X\r\n"),
  16224              ep_p->dst_mac[0], ep_p->dst_mac[1],
  16225              ep_p->dst_mac[2], ep_p->dst_mac[3],
  16226              ep_p->dst_mac[4], ep_p->dst_mac[5]));
  16227     LOG_CLI((BSL_META_U(unit,"Outer Vlan = %d\r\n"),ep_p->outer_vlan));
  16228     LOG_CLI((BSL_META_U(unit,"Outer TPID = 0x%04X\r\n"),ep_p->outer_tpid));
  16229     LOG_CLI((BSL_META_U(unit,"Outer pri = 0x%x\r\n"),ep_p->outer_pri));
  16230     LOG_CLI((BSL_META_U(unit,"Inner Vlan = %d\r\n"),ep_p->inner_vlan));
  16231     LOG_CLI((BSL_META_U(unit,"Inner TPID = 0x%04X\r\n"),ep_p->inner_tpid));
  16232     LOG_CLI((BSL_META_U(unit,"Inner Vlan Pri = %d\r\n"),ep_p->inner_pri));
  16233 
  16234     LOG_CLI((BSL_META_U(unit,"Session Id = %d\r\n"),ep_p->session_id));
  16235     LOG_CLI((BSL_META_U(unit,"Session num entries = %d\r\n"),
  16236                 ep_p->session_num_entries));
  16237     LOG_CLI((BSL_META_U(unit,"HW Base Session Id = %d\r\n\n"),
  16238                 ep_p->hw_base_session_id));
  16239 }
  16240 #endif /* INCLUDE_MPLS_LM_DM */
  16241 
  16242 #if defined(INCLUDE_CCM) || defined(INCLUDE_BHH) || defined(INCLUDE_MPLS_LM_DM)
  16243 /*
  16244  * Function:
  16245  *     _bcm_fp_oam_sw_dump
  16246  * Purpose:
  16247  *     Displays oam information maintained by software.
  16248  * Parameters:
  16249  *     unit - Device unit number
  16250  * Returns:
  16251  *     None
  16252  */
  16253 void
  16254 _bcm_fp_oam_sw_dump(int unit)
  16255 {
  16256     int ep_id;
  16257     int rv;
  16258     _bcm_fp_oam_control_t *oc;
  16259 
  16260     LOG_CLI((BSL_META_U(unit,"OAM\n")));
  16261     /* Get OAM control structure. */
  16262     rv = _bcm_fp_oam_control_get(unit, &oc);
  16263     if(BCM_FAILURE(rv)) {
  16264         LOG_ERROR(BSL_LS_BCM_OAM,
  16265                 (BSL_META_U(unit,
  16266                 "OAM(unit %d) Error: Get oam control variable\n"),
  16267                  unit));
  16268 
  16269         return;
  16270     }
  16271 
  16272 #if defined(INCLUDE_CCM)
  16273     if ((soc_feature(unit, soc_feature_uc_ccm)) &&
  16274         (oc->ccm_ukernel_ready)) {
  16275         LOG_CLI((BSL_META_U(unit,"CCM EPs data :\n")));
  16276         for(ep_id=0; ep_id < oc->mep_count; ep_id++) {
  16277             if (oc->mep_data[ep_id].in_use) {
  16278                 _bcm_fp_oam_ccm_hash_data_dump(unit, &(oc->mep_data[ep_id]));
  16279             }
  16280         }
  16281     }
  16282 #endif /* INCLUDE_CCM */
  16283 
  16284 #if defined(INCLUDE_MPLS_LM_DM)
  16285     if ((soc_feature(unit, soc_feature_mpls_lm_dm)) &&
  16286         (oc->mpls_lm_dm_ukernel_ready)) {
  16287         _bcm_fp_oam_mpls_lm_dm_ep_data_t  *ep_p;
  16288         LOG_CLI((BSL_META_U(unit,"MPLS LM/DM EPs data :\n")));
  16289         _MPLS_LM_DM_EP_ITER(ep_p, ep_id) {
  16290             if (!ep_p->in_use) {
  16291                 continue;
  16292             }
  16293             _bcm_fp_oam_mpls_lm_dm_hash_data_dump(unit, ep_p);
  16294         }
  16295     }
  16296 #endif /* INCLUDE_MPLS_LM_DM */
  16297 
  16298 #if defined (INCLUDE_BHH)
  16299     if ((soc_feature(unit, soc_feature_bhh)) &&
  16300         (oc->ukernel_not_ready == 0)) {
  16301         LOG_CLI((BSL_META_U(unit,"BHH EPs data :\n")));
  16302         for(ep_id=0; ep_id < oc->bhh_endpoint_count; ep_id++) {
  16303             if (oc->bhh_ep_data[ep_id].in_use) {
  16304                 _bcm_fp_oam_bhh_hash_data_dump(unit,  &oc->bhh_ep_data[ep_id]);
  16305             }
  16306         }
  16307     }
  16308 #endif
  16309 }
  16310 
  16311 /*
  16312  * Function:
  16313  *     _bcm_fp_oam_port_trunk_update_msg_send
  16314  * Purpose:
  16315  *     Send port to trunk mapping update msg to UKERNEL
  16316  * Parameters:
  16317  *     unit          - (IN) BCM device number
  16318  *     num_ports     - number of ports.
  16319  *     trunk_id      - ports map to which trunk_id
  16320  *     list_of_ports - list of ports
  16321  *
  16322  * Returns:
  16323  *      BCM_E_XXX
  16324  */
  16325 static int
  16326 _bcm_fp_oam_port_trunk_update_msg_send(int unit, uint16 num_ports,
  16327                             uint16 trunk_id, uint16 *list_of_ports)
  16328 {
  16329     shr_ccm_msg_ctrl_port_trunk_upd_t upd_msg;
  16330     _bcm_fp_oam_control_t *oc = NULL;
  16331     uint8 *dma_buffer = NULL;  /* DMA buffer */
  16332     uint8 *dma_buffer_ptr = NULL;  /* DMA buffer ptr after pack */
  16333     uint16 s_msg_len = 0;       /* Send Message length */
  16334     uint16  r_msg_len = 0; /* Msg response length */
  16335     int rv = BCM_E_NONE, index;
  16336 
  16337     /* Get OAM Control Structure. */
  16338     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
  16339 
  16340     /* Clear upd_msg structure */
  16341     sal_memset(&upd_msg, 0, sizeof(upd_msg));
  16342 
  16343 
  16344     /* Fill upd_msg structure */
  16345     if (num_ports < MAX_PORTS) {
  16346         upd_msg.num_ports = num_ports; 
  16347     } else {
  16348         return BCM_E_PARAM;
  16349     }
  16350    
  16351     upd_msg.trunk_id = trunk_id;
  16352 
  16353     for (index = 0; index < num_ports; index++) {
  16354         upd_msg.list_of_ports[index] = list_of_ports[index];
  16355     }
  16356 
  16357 
  16358     /* Pack Update data to buffer */
  16359     dma_buffer = oc->dma_buffer;
  16360     dma_buffer_ptr = shr_ccm_msg_ctrl_port_trunk_upd_pack(dma_buffer, &upd_msg);
  16361     s_msg_len = dma_buffer_ptr - dma_buffer;
  16362     rv = _bcm_fp_oam_msg_send_receive(unit, MOS_MSG_CLASS_CCM,
  16363             MOS_MSG_SUBCLASS_CCM_PORT_TRUNK_UPDATE, s_msg_len, 0,
  16364             MOS_MSG_SUBCLASS_CCM_PORT_TRUNK_UPDATE_REPLY, &r_msg_len);
  16365 
  16366     if (BCM_FAILURE(rv)) {
  16367         LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: "
  16368             "Port trunk update Msg returned error %s.\n"), bcm_errmsg(rv)));
  16369         rv = BCM_E_INTERNAL;
  16370     }
  16371     return (rv);
  16372 }
  16373 
  16374 /*
  16375  * Function:
  16376  *     _bcm_fp_oam_port_trunk_map_get
  16377  * Purpose:
  16378  *     Get port to trunk mapping from UKERNEL
  16379  * Parameters:
  16380  *     unit          - (IN) BCM device number
  16381  *     num_ports     - number of ports.
  16382  *     trunk_id      - ports map to which trunk_id
  16383  *     list_of_ports - list of ports
  16384  *
  16385  * Returns:
  16386  *      BCM_E_XXX
  16387  */
  16388 static int
  16389 _bcm_fp_oam_port_trunk_map_get(int unit, uint16 *num_ports,
  16390                             uint16 trunk_id, uint16 *list_of_ports)
  16391 {
  16392     shr_ccm_msg_ctrl_port_trunk_upd_t get_msg;
  16393     _bcm_fp_oam_control_t *oc = NULL;
  16394     uint8 *dma_buffer = NULL;  /* DMA buffer */
  16395     uint8 *dma_buffer_ptr = NULL;  /* DMA buffer ptr after pack */
  16396     uint16  r_msg_len = 0; /* Msg response length */
  16397     int rv = BCM_E_NONE, index;
  16398 
  16399     /* Get OAM Control Structure. */
  16400     BCM_IF_ERROR_RETURN(_bcm_fp_oam_control_get(unit, &oc));
  16401 
  16402     /* Send trunk_id in the send length variable */
  16403     rv = _bcm_fp_oam_msg_send_receive(unit, MOS_MSG_CLASS_CCM,
  16404             MOS_MSG_SUBCLASS_CCM_PORT_TRUNK_GET, trunk_id, 0, 
  16405             MOS_MSG_SUBCLASS_CCM_PORT_TRUNK_GET_REPLY, &r_msg_len);
  16406 
  16407     if (BCM_FAILURE(rv)) {
  16408         LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: "
  16409             "Port trunk map get Msg returned error %s.\n"), bcm_errmsg(rv)));
  16410         return(BCM_E_INTERNAL);
  16411     }
  16412 
  16413     /* Clear get_msg structure */
  16414     sal_memset(&get_msg, 0, sizeof(get_msg));
  16415 
  16416     /* UnPack control message data in the DMA buffer */
  16417     dma_buffer = oc->dma_buffer;
  16418     dma_buffer_ptr = shr_ccm_msg_ctrl_port_trunk_upd_unpack(dma_buffer, &get_msg);
  16419 
  16420     if (r_msg_len != dma_buffer_ptr - dma_buffer) {
  16421         rv = BCM_E_INTERNAL;
  16422         LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: "
  16423             "Trunk map get Msg length check failed, trunk:%d.\n"), trunk_id));
  16424         return (rv);
  16425     }
  16426 
  16427     *num_ports = get_msg.num_ports;
  16428 
  16429     for (index = 0; index < *num_ports; index++) {
  16430         list_of_ports[index] = get_msg.list_of_ports[index];
  16431     }
  16432 
  16433     return (rv);
  16434 }
  16435 
  16436 int
  16437 _bcm_fp_oam_trunk_ports_update(int unit, bcm_gport_t trunk_gport,
  16438                                int max_ports, bcm_gport_t *port_arr,
  16439                                uint8 delete)
  16440 {
  16441     bcm_trunk_t trunk_id = BCM_TRUNK_INVALID;
  16442     uint16 *list_of_ports = NULL;
  16443     int rv = BCM_E_NONE;
  16444     bcm_module_t module_id;
  16445     bcm_port_t   port_id;
  16446     bcm_trunk_t port_trunk_id;
  16447     int local_id, result, i;
  16448 
  16449     if (!BCM_GPORT_IS_TRUNK(trunk_gport)) {
  16450         return BCM_E_PARAM;
  16451     }
  16452 
  16453     if (max_ports >= MAX_PORTS) {
  16454         return BCM_E_PARAM;
  16455     }
  16456 
  16457     if (!port_arr) {
  16458         return BCM_E_PARAM;
  16459     }
  16460 
  16461     /* Get trunk_id from gport */
  16462     trunk_id = BCM_GPORT_TRUNK_GET(trunk_gport);
  16463 
  16464     if (trunk_id == BCM_TRUNK_INVALID) {
  16465         return BCM_E_PARAM;
  16466     }
  16467 
  16468     _BCM_OAM_ALLOC(list_of_ports, uint16, sizeof(uint16) * max_ports , "list of ports");
  16469 
  16470     for (i = 0; i < max_ports; i++) {
  16471         module_id = -1;
  16472         port_id = -1;
  16473         port_trunk_id = BCM_TRUNK_INVALID;
  16474         local_id = -1;
  16475         result = FALSE;
  16476 
  16477         /* Get (Modid + Port) value from Gport */
  16478         rv = _bcm_esw_gport_resolve(unit, port_arr[i],
  16479                     &module_id, &port_id, &port_trunk_id,
  16480                     &local_id);
  16481         if ((BCM_FAILURE(rv)) || 
  16482             (port_trunk_id != BCM_TRUNK_INVALID)) {
  16483             goto cleanup;
  16484         }
  16485         rv = _bcm_esw_modid_is_local(unit, module_id, &result);
  16486 
  16487         if (BCM_FAILURE(rv)) {
  16488             goto cleanup;
  16489         } else if (!result) {
  16490             /* We will handle only local ports */
  16491             rv = BCM_E_PARAM;
  16492             goto cleanup;
  16493         }
  16494         
  16495         list_of_ports[i] = port_id; 
  16496     }
  16497 
  16498     if (delete) {
  16499         rv = _bcm_fp_oam_port_trunk_update_msg_send(
  16500                 unit, max_ports, CCM_INVALID_TRUNK_NUM, list_of_ports);
  16501     } else {
  16502         rv = _bcm_fp_oam_port_trunk_update_msg_send(
  16503                 unit, max_ports, trunk_id, list_of_ports);
  16504     }
  16505 
  16506     if (BCM_FAILURE(rv)) {
  16507         LOG_DEBUG(BSL_LS_BCM_OAM,
  16508                 (BSL_META_U(unit,
  16509                             "OAM(unit %d) Error: Trunk map update " 
  16510                             "failed \n"),
  16511                  unit));
  16512     }
  16513 
  16514 cleanup:
  16515     sal_free(list_of_ports);
  16516 
  16517     return rv;
  16518 }
  16519 
  16520 int _bcm_fp_oam_trunk_ports_update_trunk_id(int unit, bcm_trunk_t trunk_id)
  16521 {
  16522     bcm_port_t port_id_list[MAX_PORTS];
  16523     uint16 *list_of_ports = NULL;
  16524     int local_member_count = 0, i;
  16525     int rv = BCM_E_NONE;
  16526 
  16527     BCM_IF_ERROR_RETURN(_bcm_esw_trunk_local_members_get(unit, trunk_id, MAX_PORTS,
  16528                 port_id_list,
  16529                 &local_member_count));
  16530     _BCM_OAM_ALLOC(list_of_ports, uint16, sizeof(uint16) * local_member_count, "list of ports");
  16531 
  16532     for(i = 0; i < local_member_count; i++) {
  16533         list_of_ports[i] = port_id_list[i];
  16534     }
  16535 
  16536     rv = _bcm_fp_oam_port_trunk_update_msg_send(unit, local_member_count,
  16537                 trunk_id, list_of_ports);
  16538 
  16539 
  16540     sal_free(list_of_ports);
  16541     return rv;
  16542 
  16543 }
  16544 
  16545 /*Add ports (specified by port_arr) to trunk (specified by trunk_gport) mapping 
  16546   to port-trunk database in OAM  */
  16547 int 
  16548 bcm_fp_oam_trunk_ports_add (int unit, bcm_gport_t trunk_gport,
  16549                             int max_ports, bcm_gport_t *port_arr)
  16550 {
  16551     return _bcm_fp_oam_trunk_ports_update(unit, trunk_gport, max_ports, port_arr, 0);
  16552 }
  16553 
  16554 /*Delete ports (specified by port_arr) to trunk (specified by trunk_gport) 
  16555   mapping from port-trunk database in OAM  */
  16556 int
  16557 bcm_fp_oam_trunk_ports_delete (int unit, bcm_gport_t trunk_gport,
  16558                                int max_ports, bcm_gport_t *port_arr)
  16559 {
  16560     return _bcm_fp_oam_trunk_ports_update(unit, trunk_gport, max_ports, port_arr, 1);
  16561 }
  16562 
  16563 /*Get ports (in port_arr) that are mapped to trunk (specified by trunk_gport)
  16564   from port-trunk database in OAM  */
  16565 int
  16566 bcm_fp_oam_trunk_ports_get (int unit, bcm_gport_t trunk_gport,
  16567                             int max_ports, bcm_gport_t *port_arr,
  16568                             int *port_count)
  16569 {
  16570     bcm_trunk_t trunk_id = 0;
  16571     uint16 *list_of_ports = NULL;
  16572     int rv = BCM_E_NONE, i;
  16573     bcm_port_t port;
  16574     bcm_gport_t gport;
  16575     uint16 num_ports = 0;
  16576 
  16577     if (!BCM_GPORT_IS_TRUNK(trunk_gport)) {
  16578         return BCM_E_PARAM;
  16579     }
  16580 
  16581     if (max_ports >= MAX_PORTS) {
  16582         return BCM_E_PARAM;
  16583     }
  16584 
  16585     if (!port_arr) {
  16586         return BCM_E_PARAM;
  16587     }
  16588 
  16589     /* Get trunk_id from gport */
  16590     trunk_id = BCM_GPORT_TRUNK_GET(trunk_gport);
  16591 
  16592     if (trunk_id == BCM_TRUNK_INVALID) {
  16593         return BCM_E_PARAM;
  16594     }
  16595 
  16596     _BCM_OAM_ALLOC(list_of_ports, uint16, sizeof(uint16) * max_ports , "list of ports");
  16597 
  16598 
  16599     rv = _bcm_fp_oam_port_trunk_map_get(
  16600             unit, &num_ports, trunk_id, list_of_ports);
  16601 
  16602 
  16603     if (BCM_FAILURE(rv)) {
  16604         LOG_DEBUG(BSL_LS_BCM_OAM,
  16605                 (BSL_META_U(unit,
  16606                             "OAM(unit %d) Error: Trunk map get" 
  16607                             "failed \n"),
  16608                  unit));
  16609         goto cleanup;
  16610     }
  16611 
  16612     *port_count = num_ports;
  16613 
  16614     /* If the size of array sent by user is smaller than
  16615      * actual number of ports, then reduce the count to
  16616      * array size.
  16617      */
  16618     if (*port_count > max_ports) {
  16619         *port_count = max_ports;
  16620     }
  16621 
  16622     for (i = 0; i < *port_count; i++) {
  16623         gport = BCM_GPORT_INVALID;
  16624         port = list_of_ports[i];
  16625         rv = bcm_esw_port_gport_get(unit, port, &gport);
  16626         if (BCM_FAILURE(rv) || gport == BCM_GPORT_INVALID) {
  16627             rv = BCM_E_INTERNAL;
  16628             goto cleanup;
  16629         }
  16630         port_arr[i] = gport;
  16631     }
  16632 
  16633 
  16634 cleanup:
  16635     sal_free(list_of_ports);
  16636 
  16637     return rv;
  16638 }
  16639 
  16640 #endif