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

subport.c (132539B)


      1 /*
      2  * 
      3  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      4  * 
      5  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      6  *
      7  * File:        subport.c
      8  * Purpose:     XGS5 Subport CoE common driver.
      9  */
     10 
     11 #include <soc/defs.h>
     12 
     13 #include <shared/bsl.h>
     14 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
     15 
     16 #include <soc/drv.h>
     17 #include <soc/scache_dictionary.h>
     18 #include <soc/debug.h>
     19 #include <soc/trident2.h>
     20 #include <soc/td2_td2p.h>
     21 #include <soc/bondoptions.h>
     22 #include <bcm_int/esw/subport.h>
     23 #include <bcm_int/esw/xgs5.h>
     24 #include <bcm_int/esw/xgs3.h>
     25 #include <bcm_int/esw/port.h>
     26 #include <bcm_int/esw/stack.h>
     27 #include <bcm_int/esw/trident2plus.h>
     28 #include <bcm_int/esw_dispatch.h>
     29 #include <bcm_int/esw/xgs5.h>
     30 #include <bcm/error.h>
     31 #include <bcm/debug.h>
     32 #include <bcm_int/esw/firebolt.h>
     33 #include <bcm_int/esw/vlan.h>
     34 #include <bcm_int/esw/trx.h>
     35 #include <bcm_int/esw/triumph.h>
     36 #include <bcm_int/esw/triumph2.h>
     37 #define BCMI_MAX_SHORT_VALUE                 65535
     38 
     39 /*
     40  * SUBPORT HW Definition Table
     41  */
     42 static bcmi_xgs5_subport_coe_hw_defs_t  *bcmi_xgs5_subport_coe_hw_defs[BCM_MAX_NUM_UNITS] = {0};
     43 
     44 #define SUBPORT_COE_HW(u_)    (bcmi_xgs5_subport_coe_hw_defs[(u_)])
     45 
     46 #define SUBPORT_COE_HW_ING_PORT(u_)  \
     47     (bcmi_xgs5_subport_coe_hw_defs[(u_)]->igr_port)
     48 #define SUBPORT_COE_HW_EGR_PORT(u_)  \
     49     (bcmi_xgs5_subport_coe_hw_defs[(u_)]->egr_port)
     50 #define SUBPORT_COE_HW_MODPORT_MAP_SUBPORT(u_)  \
     51     (bcmi_xgs5_subport_coe_hw_defs[(u_)]->modport_map_subport)
     52 #define SUBPORT_COE_HW_SUBPORT_SUBTAG_SGPP(u_)  \
     53     (bcmi_xgs5_subport_coe_hw_defs[(u_)]->subport_tag_sgpp)
     54 #define SUBPORT_COE_HW_EGR_SUBPORT_TAG_DOT1P(u_)  \
     55     (bcmi_xgs5_subport_coe_hw_defs[(u_)]->egr_subport_tag_dot1p)
     56 
     57 #define SUBPORT_COE_HW_ING_PORT_MEM(u_)  \
     58     (SUBPORT_COE_HW_ING_PORT(u_)->mem)
     59 #define SUBPORT_COE_HW_EGR_PORT_MEM(u_)  \
     60     (SUBPORT_COE_HW_EGR_PORT(u_)->mem)
     61 #define SUBPORT_COE_HW_MODPORT_MAP_SUBPORT_MEM(u_)  \
     62     (SUBPORT_COE_HW_MODPORT_MAP_SUBPORT(u_)->mem)
     63 #define SUBPORT_COE_HW_SUBPORT_SUBTAG_SGPP_MEM(u_)  \
     64     (SUBPORT_COE_HW_SUBPORT_SUBTAG_SGPP(u_)->mem)
     65 #define SUBPORT_COE_HW_EGR_SUBPORT_TAG_DOT1P_MEM(u_) \
     66     (SUBPORT_COE_HW_EGR_SUBPORT_TAG_DOT1P(u_)->mem)
     67 
     68 #define BCM_FAILURE_CLEANUP(rv, label) \
     69     do { if (SOC_FAILURE(rv)) { goto label; } } while(0)
     70 
     71 
     72 STATIC int _bcm_subport_coe_port_count[BCM_MAX_NUM_UNITS] = { 0 };
     73 
     74 STATIC int
     75 bcmi_xgs5_subtag_subport_init(int unit)
     76 {
     77     bcm_port_t port;
     78     int num_vlan = 0, index = 0;
     79     soc_info_t *si = &SOC_INFO(unit);
     80     BCM_IF_ERROR_RETURN
     81         (soc_mem_clear(unit, SUBPORT_COE_HW_SUBPORT_SUBTAG_SGPP_MEM(unit),
     82                COPYNO_ALL, TRUE));
     83     num_vlan = soc_mem_index_count(unit, VLAN_TABm);
     84 
     85     BCM_PBMP_ITER(si->subtag_allowed_pbm, port) {
     86 
     87         if (port < SOC_MAX_NUM_PORTS) {
     88 
     89             /* SubTag VLAN ID bitmap to keep track of the VLAN ID used per
     90              * SubTag enabled port.
     91              */
     92             if (_bcm_subtag_vlan_id_bitmap[unit][port] == NULL) {
     93 
     94                 _bcm_subtag_vlan_id_bitmap[unit][port] =
     95                     sal_alloc(SHR_BITALLOCSIZE(num_vlan),
     96                             "_bcm_subtag_vlan_id_bitmap");
     97 
     98                 if (_bcm_subtag_vlan_id_bitmap[unit][port] == NULL) {
     99                     LOG_ERROR(BSL_LS_BCM_SUBPORT,
    100                       (BSL_META_U(unit,"ERROR:_bcm_subtag_vlan_id_bitmap "
    101                                 " alloc failed\n")));
    102 
    103                     return BCM_E_MEMORY;
    104                 }
    105             }
    106             sal_memset(_bcm_subtag_vlan_id_bitmap[unit][port], 0,
    107                     SHR_BITALLOCSIZE(num_vlan));
    108         }
    109     }
    110 
    111     /* SubTag subport group bitmap to keep track of used SubTag groups */
    112     if (_bcm_subtag_group_bitmap[unit] == NULL) {
    113 
    114         _bcm_subtag_group_bitmap[unit] = 
    115              sal_alloc(SHR_BITALLOCSIZE(si->max_subport_coe_groups),
    116              "subtag_subport_group_bitmap");
    117 
    118         if (_bcm_subtag_group_bitmap[unit] == NULL) {
    119              LOG_ERROR(BSL_LS_BCM_SUBPORT,
    120                       (BSL_META_U(unit,"ERROR:subtag group bitmap "
    121                                        "alloc failed\n")));
    122 
    123              return BCM_E_MEMORY;
    124         }
    125     }
    126 
    127     sal_memset(_bcm_subtag_group_bitmap[unit], 0,
    128         SHR_BITALLOCSIZE(si->max_subport_coe_groups));
    129 
    130     /* SubTag subport port info per subport group per subport port */
    131     if (_bcm_subtag_subport_port_info[unit] == NULL) {
    132         _bcm_subtag_subport_port_info[unit] =
    133             sal_alloc((si->max_subport_coe_ports *
    134                        sizeof(_bcm_subtag_subport_port_info_t)),
    135                        "subtag_subport_port_info");
    136         if (_bcm_subtag_subport_port_info[unit] == NULL) {
    137             LOG_ERROR(BSL_LS_BCM_SUBPORT,
    138                       (BSL_META_U(unit,"ERROR: "
    139                     " subtag_subport_port_info alloc failed\n")));
    140 
    141             return BCM_E_MEMORY;
    142         }
    143     }
    144 
    145     for (index = 0; index < si->max_subport_coe_ports; index++) {
    146         _bcm_subtag_subport_port_info[unit][index].group = BCM_GPORT_INVALID;
    147         _bcm_subtag_subport_port_info[unit][index].vlan = BCM_VLAN_INVALID;
    148         _bcm_subtag_subport_port_info[unit][index].subtag_tcam_hw_idx = -1;
    149         _bcm_subtag_subport_port_info[unit][index].subport_modport = -1; 
    150         _bcm_subtag_subport_port_info[unit][index].subport_port = -1;
    151         _bcm_subtag_subport_port_info[unit][index].nh_index = -1;
    152         _bcm_subtag_subport_port_info[unit][index].valid = 0;
    153         _bcm_subtag_subport_port_info[unit][index].modport_subport_idx = 0;
    154         _bcm_subtag_subport_port_info[unit][index].phb_valid = 0;
    155         _bcm_subtag_subport_port_info[unit][index].priority = 0;
    156         _bcm_subtag_subport_port_info[unit][index].color = 0;
    157     }
    158     /* Set the Ingress/Egress EtherTypes to a specific default */
    159     BCM_IF_ERROR_RETURN(bcmi_xgs5_subport_coe_ether_type_size_set(
    160                                 unit, bcmSwitchSubportCoEEtherType,
    161                                 BCM_SUBPORT_COE_DEFAULT_ETHERTYPE));
    162     BCM_IF_ERROR_RETURN(bcmi_xgs5_subport_coe_ether_type_size_set(
    163                                 unit, bcmSwitchSubportEgressTpid,
    164                                 BCM_SUBPORT_COE_DEFAULT_ETHERTYPE)); 
    165     BCM_IF_ERROR_RETURN(bcmi_xgs5_subport_coe_ether_type_size_set(
    166                                 unit, bcmSwitchSubportEgressWideTpid,
    167                                 BCM_SUBPORT_COE_DEFAULT_ETHERTYPE)); 
    168     return BCM_E_NONE;
    169 }
    170 
    171 STATIC void
    172 bcmi_xgs5_subport_free_resource(int unit)
    173 {
    174     bcm_port_t port;
    175 
    176     if(_bcm_subport_group_bitmap[unit] != NULL) {
    177         sal_free(_bcm_subport_group_bitmap[unit]);
    178         _bcm_subport_group_bitmap[unit] = NULL;
    179     }
    180 
    181     if (soc_feature(unit, soc_feature_hgproxy_subtag_coe)) {
    182 
    183         if(_bcm_subtag_group_bitmap[unit] != NULL) {
    184             sal_free(_bcm_subtag_group_bitmap[unit]);
    185             _bcm_subtag_group_bitmap[unit] = NULL;
    186         }
    187 
    188         if (_bcm_subtag_subport_port_info[unit] != NULL) {
    189             sal_free(_bcm_subtag_subport_port_info[unit]);
    190             _bcm_subtag_subport_port_info[unit] = NULL;
    191         }
    192 
    193         if (BCM_PBMP_NOT_NULL(SOC_INFO(unit).subtag_allowed_pbm)) {
    194             BCM_PBMP_ITER(SOC_INFO(unit).subtag_allowed_pbm, port) {
    195                 /* check to fix coverity static overrun error */
    196                 if (port < SOC_MAX_NUM_PORTS) {
    197                     if (_bcm_subtag_vlan_id_bitmap[unit][port] != NULL) {
    198                         sal_free(_bcm_subtag_vlan_id_bitmap[unit][port]);
    199                         _bcm_subtag_vlan_id_bitmap[unit][port] = NULL;
    200                     }
    201                 }
    202             }
    203         }
    204 
    205     } /* end of  soc_feature_hgproxy_subtag_coe */
    206 
    207     if (_bcm_subport_group_subport_port_count[unit] != NULL) {
    208         sal_free(_bcm_subport_group_subport_port_count[unit]);
    209         _bcm_subport_group_subport_port_count[unit] = NULL;
    210     }
    211 
    212     if (_bcm_subport_mutex[unit] != NULL) {
    213         sal_mutex_destroy(_bcm_subport_mutex[unit]);
    214         _bcm_subport_mutex[unit] = NULL;
    215     }
    216 
    217 }
    218 
    219 /*
    220  * Function:
    221  *      bcmi_xgs5_subport_init
    222  * Purpose:
    223  *      Initialize the Subport subsystem
    224  * Parameters:
    225  *      unit - (IN) Unit number.
    226  * Returns:
    227  *         int  - Result of init
    228  */
    229 int
    230 bcmi_xgs5_subport_init(int unit,
    231                        bcm_esw_subport_drv_t *drv,
    232                        bcmi_xgs5_subport_coe_hw_defs_t *hw_defs)
    233 {
    234     int rv = BCM_E_NONE;
    235 
    236 #ifdef BCM_HGPROXY_COE_SUPPORT 
    237     soc_info_t *si = &SOC_INFO(unit);
    238 #endif
    239 
    240 /* Do this only for the Newer CoE implementations */
    241 #ifdef BCM_HGPROXY_COE_SUPPORT 
    242 
    243     if (soc_feature(unit, soc_feature_hgproxy_subtag_coe)) {
    244 
    245         /* Subport group bitmap to keep track of used subport groups */
    246         if (_bcm_subport_group_bitmap[unit] == NULL) {
    247 
    248             _bcm_subport_group_bitmap[unit] = 
    249                 sal_alloc(SHR_BITALLOCSIZE(si->max_subport_coe_groups),
    250                 "subport_group_bitmap");
    251 
    252             if (_bcm_subport_group_bitmap[unit] == NULL) {
    253                 LOG_ERROR(BSL_LS_BCM_SUBPORT,
    254                           (BSL_META_U(unit,"ERROR:subport_init: group bitmap "
    255                                            "alloc failed\n")));
    256 
    257                 bcmi_xgs5_subport_free_resource(unit);
    258 
    259                 return BCM_E_MEMORY;
    260             }
    261 
    262         }
    263 
    264         sal_memset(_bcm_subport_group_bitmap[unit], 0,
    265             SHR_BITALLOCSIZE(si->max_subport_coe_groups));
    266 
    267         _bcm_subport_group_count[unit] = 0;
    268 
    269         /* Keep Count of subport port created per subport group */
    270         if (_bcm_subport_group_subport_port_count[unit] == NULL) {
    271             _bcm_subport_group_subport_port_count[unit] =
    272                 sal_alloc((si->max_subport_coe_groups * sizeof(int)),
    273                             "subport_group_subport_port_count");
    274             if (_bcm_subport_group_subport_port_count[unit] == NULL) {
    275                 LOG_ERROR(BSL_LS_BCM_SUBPORT,
    276                           (BSL_META_U(unit,"ERROR: "
    277                     "subport_group_subport_port_count alloc failed\n")));
    278 
    279                 return BCM_E_MEMORY;
    280             }
    281         }
    282 
    283         sal_memset(_bcm_subport_group_subport_port_count[unit], 0,
    284             (si->max_subport_coe_groups * sizeof(int)));
    285 
    286         /* Subtag CoE subport initialization */
    287 
    288         if(hw_defs) {
    289            SUBPORT_COE_HW(unit) = hw_defs;
    290         }
    291         if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) &&
    292             BCM_PBMP_NOT_NULL(si->subtag_allowed_pbm)) {
    293             rv = bcmi_xgs5_subtag_subport_init(unit);
    294             if (SOC_FAILURE(rv)) {
    295                 LOG_ERROR(BSL_LS_BCM_SUBPORT,
    296                           (BSL_META_U(unit,"ERROR: SubTag init failed.\n")));
    297 
    298                 bcmi_xgs5_subport_free_resource(unit);
    299                 return rv;
    300             }
    301         }
    302 
    303         _bcm_subport_coe_port_count[unit] = 0;
    304 
    305         /* Create subport mutex */
    306         if (NULL == _bcm_subport_mutex[unit]) {
    307             _bcm_subport_mutex[unit] =
    308                 sal_mutex_create("subtag subport mutex");
    309 
    310             if (_bcm_subport_mutex[unit] == NULL) {
    311                 LOG_ERROR(BSL_LS_BCM_SUBPORT,
    312                           (BSL_META_U(unit,"ERROR:subtag subport mutex "
    313                                            "create failed\n")));
    314 
    315                 return BCM_E_MEMORY;
    316             }
    317         }
    318     }
    319 
    320 #ifdef BCM_WARM_BOOT_SUPPORT
    321     if(SOC_WARM_BOOT(unit)) {
    322         rv = _bcmi_xgs5_subport_reinit(unit);
    323         if (rv != BCM_E_NONE) {
    324         }
    325     }
    326 #endif /* BCM_WARM_BOOT_SUPPORT */
    327 
    328 
    329 #endif
    330 
    331     /* Install Tables */
    332     /* If a driver is not assigned already, assign the driver */
    333     if(BCM_ESW_SUBPORT_DRV(unit) == NULL) {
    334         BCM_ESW_SUBPORT_DRV(unit) = drv;
    335     }
    336 
    337     return BCM_E_NONE;
    338 }
    339 
    340 int _bcmi_xgs5_subport_reinit(int unit)
    341 {
    342      
    343     return 0;
    344 }
    345 
    346 int _bcm_coe_subtag_subport_port_get(int unit, 
    347                                      bcm_gport_t subport_port_gport,
    348                                      bcm_subport_config_t *config)
    349 {
    350     bcm_gport_t subport_group;
    351     int i = 0;
    352     soc_info_t *si = &SOC_INFO(unit);
    353 
    354     if (config == NULL) {
    355         return BCM_E_PARAM;
    356     }
    357 
    358     if(_bcm_subtag_subport_port_info[unit] == NULL) {
    359         return BCM_E_NOT_FOUND;
    360     }
    361 
    362     /* Check if the passed in port is of 'subtag' type */
    363     if (_BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, subport_port_gport)) {
    364 
    365         /* Find the entry corresponding to the subport */
    366         for (i=0; i < si->max_subport_coe_ports; i++) {
    367             if((_bcm_subtag_subport_port_info[unit][i].valid) && 
    368                 (_bcm_subtag_subport_port_info[unit][i].subport_port == 
    369                  subport_port_gport)) {
    370                     /* Entry found, break */
    371                     break;
    372                 }
    373         }
    374 
    375         /* Flag error if subport not found */
    376         if(i == si->max_subport_coe_ports) {
    377             LOG_VERBOSE(BSL_LS_BCM_SUBPORT,
    378                         (BSL_META_U(unit, "ERROR:Invalid SubTag subport"
    379                                           " port gport 0x%x\n"),
    380                                     subport_port_gport));
    381             return BCM_E_NOT_FOUND;
    382         }
    383 
    384         /* Get the group id and ensure it is valid */
    385         subport_group = _bcm_subtag_subport_port_info[unit][i].group;
    386 
    387         if (!BCM_GPORT_IS_SUBPORT_GROUP(subport_group)) {
    388             LOG_VERBOSE(BSL_LS_BCM_SUBPORT,
    389                         (BSL_META_U(unit, "ERROR:Invalid SubTag subport"
    390                                           " group gport 0x%x\n"),
    391                 subport_port_gport));
    392             return BCM_E_PARAM;
    393         }
    394 
    395         /* Fill in needed data */
    396         config->group = subport_group;
    397         config->pkt_vlan =
    398             _bcm_subtag_subport_port_info[unit][i].vlan;  
    399         /* Put togethe the CoE (mod,port) associated with this subtag */
    400         config->subport_modport = 
    401             _bcm_subtag_subport_port_info[unit][i].subport_modport;
    402 
    403         /* Fill in the PHB data */
    404         if(_bcm_subtag_subport_port_info[unit][i].phb_valid) {
    405             config->prop_flags |= BCM_SUBPORT_PROPERTY_PHB;
    406             config->int_pri = 
    407                 _bcm_subtag_subport_port_info[unit][i].priority;
    408             config->color = 
    409                 _bcm_subtag_subport_port_info[unit][i].color;
    410         } else {
    411             config->prop_flags &= ~BCM_SUBPORT_PROPERTY_PHB;
    412             config->int_pri = 0;
    413             config->color = 0;
    414         }
    415     } else {
    416         return BCM_E_PARAM;
    417     }
    418 
    419     return BCM_E_NONE;
    420 }
    421 
    422 
    423 int bcmi_xgs5_subport_coe_port_get(int unit, 
    424                                    bcm_gport_t subport_port_gport,
    425                                    bcm_subport_config_t *config)
    426 {
    427     int rv = BCM_E_NONE;
    428 
    429     if (config == NULL) {
    430         return BCM_E_PARAM;
    431     }
    432 
    433     _BCM_SUBPORT_COE_CHECK_INIT(unit);
    434 
    435     if (!BCM_GPORT_IS_SUBPORT_PORT(subport_port_gport)) {
    436         LOG_ERROR(BSL_LS_BCM_SUBPORT,
    437                       (BSL_META_U(unit,"ERROR: gport 0x%x is not "
    438                                        "subport port gport\n"),
    439                                   subport_port_gport));                                
    440             return BCM_E_PARAM;
    441     }
    442 
    443     _BCM_SUBPORT_COE_LOCK(unit);
    444 
    445     if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) && 
    446         _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, subport_port_gport)) {
    447             rv = _bcm_coe_subtag_subport_port_get(unit, 
    448                          subport_port_gport, config);
    449     }
    450 
    451     if (SOC_FAILURE(rv)) {
    452         LOG_VERBOSE(BSL_LS_BCM_SUBPORT,
    453                         (BSL_META_U(unit, "ERROR: Subport port 0x%x "
    454                                           "get failed. rv=%d(%s)\n"),
    455                                     subport_port_gport, rv, soc_errmsg(rv)));
    456         _BCM_SUBPORT_COE_UNLOCK(unit);
    457         return rv;
    458     }
    459 
    460     _BCM_SUBPORT_COE_UNLOCK(unit);
    461 
    462     return BCM_E_NONE;
    463 }
    464 
    465 /*
    466  * Function:
    467  *      _bcm_coe_subtag_subport_default_lport_entry_set
    468  * Purpose:
    469  *      Add a deafult lport entry for this Source Trunk Map entry
    470  * Parameters:
    471  *      unit   - (IN) Device Number
    472  *      port   - (IN) Physical port which this coe port belong to
    473  *      stm_index - (IN) Source Trunk Map Index to update the LPORT at
    474  * Returns:
    475  *      BCM_E_XXX
    476  */
    477 
    478 STATIC int
    479 _bcm_coe_subtag_subport_default_lport_entry_set(int unit, bcm_port_t port,
    480                                                 int stm_index)
    481 {
    482     source_trunk_map_table_entry_t  stm_entry;
    483     lport_tab_entry_t               lport_entry;
    484     void                           *entries[1];
    485     uint32                          lport_index;
    486     int                             key_type_value = 0;
    487     int                             value;
    488     int                             rv = BCM_E_NONE;
    489 
    490     sal_memcpy(&lport_entry, soc_mem_entry_null(unit, LPORT_TABm),
    491                soc_mem_entry_words(unit, LPORT_TABm) * sizeof(uint32));
    492 
    493     /* Inherrit the default properties from its cascaded port*/
    494 
    495     /* Enable outer_tpid_enable */
    496     if (SOC_MEM_FIELD_VALID(unit, LPORT_TABm, OUTER_TPID_ENABLEf)) {
    497         soc_LPORT_TABm_field32_set(unit, &lport_entry, OUTER_TPID_ENABLEf, 1);
    498     }
    499 
    500     /* Switching VLAN. */
    501     if (SOC_MEM_FIELD_VALID(unit, LPORT_TABm, OUTER_TPIDf)) {
    502         soc_LPORT_TABm_field32_set(unit, &lport_entry, OUTER_TPIDf, 0x8100);
    503     }
    504 
    505     /* Set default  vlan id(pvid) for port. */
    506     soc_LPORT_TABm_field32_set(unit, &lport_entry, PORT_VIDf, BCM_VLAN_DEFAULT);
    507 
    508     /* Enable mac based vlan classification. */
    509     soc_LPORT_TABm_field32_set(unit, &lport_entry, MAC_BASED_VID_ENABLEf, 1);
    510 
    511     /* Enable subnet based vlan classification. */
    512     soc_LPORT_TABm_field32_set(unit, &lport_entry, SUBNET_BASED_VID_ENABLEf, 1);
    513 
    514     if (SOC_MEM_FIELD_VALID(unit, LPORT_TABm, TRUST_INCOMING_VIDf)) {
    515         soc_LPORT_TABm_field32_set(unit, &lport_entry, TRUST_INCOMING_VIDf, 1);
    516 
    517         /* Set identify mapping for pri/cfi re-mapping */
    518         if (SOC_MEM_FIELD_VALID(unit, LPORT_TABm, PRI_MAPPINGf)) {
    519             soc_LPORT_TABm_field32_set(unit, &lport_entry, PRI_MAPPINGf, 0xfac688);
    520             soc_LPORT_TABm_field32_set(unit, &lport_entry, CFI_0_MAPPINGf, 0);
    521             soc_LPORT_TABm_field32_set(unit, &lport_entry, CFI_1_MAPPINGf, 1);
    522         }
    523 
    524         /* Set identify mapping for ipri/icfi re-mapping */
    525         if (SOC_MEM_FIELD_VALID(unit, LPORT_TABm, IPRI_MAPPINGf)) {
    526             soc_LPORT_TABm_field32_set(unit, &lport_entry, IPRI_MAPPINGf, 0xfac688);
    527             soc_LPORT_TABm_field32_set(unit, &lport_entry, ICFI_0_MAPPINGf, 0);
    528             soc_LPORT_TABm_field32_set(unit, &lport_entry, ICFI_1_MAPPINGf, 1);
    529         }
    530 
    531         /* Set the CML to PVP_CML_SWITCH by default (hw learn and forward) */
    532         if (SOC_MEM_FIELD_VALID(unit, LPORT_TABm, CML_FLAGS_NEWf)) {
    533             soc_LPORT_TABm_field32_set(unit, &lport_entry, CML_FLAGS_NEWf, 0x8);
    534             soc_LPORT_TABm_field32_set(unit, &lport_entry, CML_FLAGS_MOVEf, 0x8);
    535         }
    536         /* Set first VLAN_XLATE key-type to {outer,port}.
    537          * Set second VLAN_XLATE key-type to {inner,port}.
    538          */
    539         if (SOC_MEM_FIELD_VALID(unit, LPORT_TABm, VT_KEY_TYPEf)) {
    540             BCM_IF_ERROR_RETURN
    541                 (_bcm_esw_pt_vtkey_type_value_get(unit,
    542                          VLXLT_HASH_KEY_TYPE_OVID, &key_type_value));
    543             soc_LPORT_TABm_field32_set(unit, &lport_entry, VT_KEY_TYPEf,
    544                                       key_type_value);
    545         }
    546 
    547         if (SOC_MEM_FIELD_VALID(unit, LPORT_TABm, VT_KEY_TYPE_USE_GLPf)) {
    548             soc_LPORT_TABm_field32_set(unit, &lport_entry, VT_KEY_TYPE_USE_GLPf, 1);
    549         }
    550         if (SOC_MEM_FIELD_VALID(unit, LPORT_TABm, VT_PORT_TYPE_SELECTf)) {
    551             soc_LPORT_TABm_field32_set(unit, &lport_entry, VT_PORT_TYPE_SELECTf, 1);
    552         }
    553         if (SOC_MEM_FIELD_VALID(unit, LPORT_TABm, VT_KEY_TYPE_2f)) {
    554             BCM_IF_ERROR_RETURN
    555                 (_bcm_esw_pt_vtkey_type_value_get(unit,
    556                          VLXLT_HASH_KEY_TYPE_IVID, &key_type_value));
    557             soc_LPORT_TABm_field32_set(unit, &lport_entry, VT_KEY_TYPE_2f,
    558                                       key_type_value);
    559         }
    560         if (SOC_MEM_FIELD_VALID(unit, LPORT_TABm, VT_KEY_TYPE_2_USE_GLPf)) {
    561             soc_LPORT_TABm_field32_set(unit, &lport_entry, VT_KEY_TYPE_2_USE_GLPf, 1);
    562         }
    563         if (SOC_MEM_FIELD_VALID(unit, LPORT_TABm, VT_PORT_TYPE_SELECT_2f)) {
    564             soc_LPORT_TABm_field32_set(unit, &lport_entry, VT_PORT_TYPE_SELECT_2f, 1);
    565         }
    566 
    567         /* Trust the outer tag pri/cfi (to be backwards compatible) */
    568         if (SOC_MEM_FIELD_VALID(unit, LPORT_TABm, TRUST_OUTER_DOT1Pf)) {
    569             soc_LPORT_TABm_field32_set(unit, &lport_entry, TRUST_OUTER_DOT1Pf, 1);
    570         }
    571     }
    572 
    573     /* Enable IFP. */
    574     soc_LPORT_TABm_field32_set(unit, &lport_entry, FILTER_ENABLEf, 1);
    575 
    576     /* Enable VFP. */
    577     soc_LPORT_TABm_field32_set(unit, &lport_entry, VFP_ENABLEf, 1);
    578 
    579     /* Set port field select index to PFS index max - 1. */
    580     if(SOC_MEM_FIELD_VALID(unit, LPORT_TABm, FP_PORT_FIELD_SEL_INDEXf)) {
    581         soc_LPORT_TABm_field32_set(unit, &lport_entry, FP_PORT_FIELD_SEL_INDEXf,
    582                                    (soc_mem_index_max(unit, FP_PORT_FIELD_SELm)
    583                                     - 1));
    584     }
    585 
    586     /* Enable V4 L3 termination */
    587     if (SOC_MEM_FIELD_VALID(unit, LPORT_TABm, V4L3_ENABLEf)) {
    588         BCM_IF_ERROR_RETURN(
    589          _bcm_esw_port_tab_get(unit, port, V4L3_ENABLEf, &value));
    590 
    591         soc_LPORT_TABm_field32_set(unit, &lport_entry, V4L3_ENABLEf, value);
    592     }
    593 
    594     /* Enable V6 L3 termination */
    595     if (SOC_MEM_FIELD_VALID(unit, LPORT_TABm, V6L3_ENABLEf)) {
    596         BCM_IF_ERROR_RETURN(
    597          _bcm_esw_port_tab_get(unit, port, V6L3_ENABLEf, &value));
    598         soc_LPORT_TABm_field32_set(unit, &lport_entry, V6L3_ENABLEf, value);
    599     }
    600 
    601     /* Enable V4 IPMC */
    602     if (SOC_MEM_FIELD_VALID(unit, LPORT_TABm, V4IPMC_ENABLEf)) {
    603         BCM_IF_ERROR_RETURN(
    604          _bcm_esw_port_tab_get(unit, port, V4IPMC_ENABLEf, &value));
    605         soc_LPORT_TABm_field32_set(unit, &lport_entry, V4IPMC_ENABLEf, value);
    606     }
    607 
    608     /* Enable V6 IPMC */
    609     if (SOC_MEM_FIELD_VALID(unit, LPORT_TABm, V6IPMC_ENABLEf)) {
    610         BCM_IF_ERROR_RETURN(
    611          _bcm_esw_port_tab_get(unit, port, V6IPMC_ENABLEf, &value));
    612         soc_LPORT_TABm_field32_set(unit, &lport_entry, V6IPMC_ENABLEf, value);
    613     }
    614 
    615     /* IPMC DO VLAN enable */
    616     if (SOC_MEM_FIELD_VALID(unit, LPORT_TABm, IPMC_DO_VLANf)) {
    617         BCM_IF_ERROR_RETURN(
    618         _bcm_esw_port_tab_get(unit, port, IPMC_DO_VLANf, &value));
    619         soc_LPORT_TABm_field32_set(unit, &lport_entry, IPMC_DO_VLANf, value);
    620     }
    621 
    622     /* Enable MPLS */
    623     if (SOC_MEM_FIELD_VALID(unit, LPORT_TABm, MPLS_ENABLEf)) {
    624         BCM_IF_ERROR_RETURN(
    625         _bcm_esw_port_tab_get(unit, port, MPLS_ENABLEf, &value));
    626         soc_LPORT_TABm_field32_set(unit, &lport_entry, MPLS_ENABLEf, value);
    627     }
    628 
    629     if (SOC_IS_TRIDENT3X(unit)) {
    630         soc_LPORT_TABm_field32_set(unit, &lport_entry, PRI_MAPPINGf, 0xfac688);
    631         soc_LPORT_TABm_field32_set(unit, &lport_entry, CFI_0_MAPPINGf, 0);
    632         soc_LPORT_TABm_field32_set(unit, &lport_entry, CFI_1_MAPPINGf, 1);
    633         soc_LPORT_TABm_field32_set(unit, &lport_entry, IPRI_MAPPINGf, 0xfac688);
    634         soc_LPORT_TABm_field32_set(unit, &lport_entry, ICFI_0_MAPPINGf, 0);
    635         soc_LPORT_TABm_field32_set(unit, &lport_entry, ICFI_1_MAPPINGf, 1);
    636         soc_LPORT_TABm_field32_set(unit, &lport_entry, CML_FLAGS_NEWf, 0x8);
    637         soc_LPORT_TABm_field32_set(unit, &lport_entry, CML_FLAGS_MOVEf, 0x8);
    638         soc_LPORT_TABm_field32_set(unit, &lport_entry, TAG_ACTION_PROFILE_PTRf, 0x1);
    639 
    640         BCM_IF_ERROR_RETURN
    641             (_bcm_esw_pt_vtkey_type_value_get(unit,
    642                       VLXLT_HASH_KEY_TYPE_OVID, &key_type_value));
    643         soc_LPORT_TABm_field32_set(unit, &lport_entry, VT_KEY_TYPEf,
    644                                   key_type_value);
    645 
    646         soc_LPORT_TABm_field32_set(unit, &lport_entry, VT_PORT_TYPE_SELECT_1f, 1);
    647 
    648         BCM_IF_ERROR_RETURN
    649             (_bcm_esw_pt_vtkey_type_value_get(unit,
    650                    VLXLT_HASH_KEY_TYPE_IVID, &key_type_value));
    651         soc_LPORT_TABm_field32_set(unit, &lport_entry, VT_KEY_TYPE_2f,
    652                                 key_type_value);
    653 
    654         soc_LPORT_TABm_field32_set(unit, &lport_entry, VT_PORT_TYPE_SELECT_2f, 1);
    655     }
    656 
    657     /* Add LPORT default entry */
    658     entries[0] = &lport_entry;
    659     BCM_IF_ERROR_RETURN(
    660         _bcm_lport_ind_profile_entry_add(unit, entries, 1, &lport_index));
    661 
    662     soc_mem_lock(unit, SOURCE_TRUNK_MAP_TABLEm);
    663 
    664     /* Get the current entry programmed at the specified index */
    665     rv = READ_SOURCE_TRUNK_MAP_TABLEm(unit, MEM_BLOCK_ANY,
    666                                       stm_index, &stm_entry);
    667 
    668     if(BCM_FAILURE(rv)) {
    669         soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm);
    670         return rv;
    671     }
    672 
    673     /* Update STM LPORT profile index  */
    674     soc_SOURCE_TRUNK_MAP_TABLEm_field32_set(unit, &stm_entry,
    675                                             LPORT_PROFILE_IDXf,
    676                                             lport_index);
    677 
    678     if (SOC_MEM_FIELD_VALID(unit, SOURCE_TRUNK_MAP_TABLEm, OUTER_TPID_ENABLEf)) {
    679         soc_SOURCE_TRUNK_MAP_TABLEm_field32_set(unit, &stm_entry,
    680                                                  OUTER_TPID_ENABLEf, 1);
    681     }
    682     /* Write the data back */
    683     rv = WRITE_SOURCE_TRUNK_MAP_TABLEm(unit, MEM_BLOCK_ANY,
    684                                        stm_index, &stm_entry);
    685 
    686     soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm);
    687 
    688     return rv;
    689 }
    690 
    691 STATIC int
    692 _bcm_coe_subtag_subport_default_egr_lport_entry_set(int unit, int port)
    693 {
    694     uint32 values[] = {0, 1, 1, 0};
    695     soc_field_t fields[] = {
    696         EN_EFILTERf,
    697         EM_SRCMOD_CHANGEf,
    698         EFP_FILTER_ENABLEf,
    699         EGR_QOS_PROFILE_INDEXf
    700     };
    701 
    702     BCM_IF_ERROR_RETURN(
    703         bcm_esw_port_egr_lport_fields_set(
    704             unit, port, EGR_LPORT_PROFILEm, 4, fields, values));
    705 
    706     if (SOC_MEM_FIELD_VALID(unit, EGR_PORT_1m, OUTER_TPID_ENABLEf)) {
    707         BCM_IF_ERROR_RETURN(
    708             bcm_esw_port_egr_lport_field_set(
    709                 unit, port, EGR_PORT_1m, OUTER_TPID_ENABLEf, 1));
    710 
    711     }
    712     if (SOC_MEM_FIELD_VALID(unit, EGR_LPORT_PROFILEm, VXLT_CTRL_IDf)) {
    713         BCM_IF_ERROR_RETURN(
    714             bcm_esw_port_egr_lport_field_set(
    715                 unit, port, EGR_LPORT_PROFILEm, VXLT_CTRL_IDf, 1));
    716 
    717     }
    718     return BCM_E_NONE;
    719 }
    720 
    721 /*
    722  * Function:
    723  *      _bcm_coe_subtag_subport_lport_entry_delete
    724  * Purpose:
    725  *      Delete the lport profile for this Source Trunk Map entry
    726  * Parameters:
    727  *      unit   - (IN) Device Number
    728  *      stm_index - (IN) Source Trunk Map Index to update the LPORT at
    729  * Returns:
    730  *      BCM_E_XXX
    731  */
    732 
    733 STATIC int
    734 _bcm_coe_subtag_subport_lport_entry_delete(int unit, int stm_index)
    735 {
    736     source_trunk_map_table_entry_t  stm_entry;
    737     uint32                          lport_index;
    738 
    739     /* Read the entry in question */
    740     SOC_IF_ERROR_RETURN
    741         (READ_SOURCE_TRUNK_MAP_TABLEm(unit, MEM_BLOCK_ANY,
    742                                       stm_index, &stm_entry)); 
    743 
    744     /* Extract the lport index from the entry */
    745     lport_index =
    746         soc_SOURCE_TRUNK_MAP_TABLEm_field32_get(unit, &stm_entry,
    747                                                 LPORT_PROFILE_IDXf);
    748 
    749     /* Delete the profile entry for this index*/
    750     BCM_IF_ERROR_RETURN(
    751         _bcm_lport_ind_profile_entry_delete(unit, lport_index));
    752 
    753     return BCM_E_NONE;
    754 }
    755 
    756 /*
    757  * Function:
    758  *      _bcm_coe_subtag_subport_port_delete
    759  * Purpose:
    760  *      Add a subport to a subport group
    761  * Parameters:
    762  *      unit   - (IN) Device Number
    763  *      subport_port_gport - (IN) Subport to delete
    764  * Returns:
    765  *      BCM_E_XXX
    766  */
    767 
    768 STATIC int
    769 _bcm_coe_subtag_subport_port_delete(int unit, bcm_gport_t subport)
    770 {
    771     int rv = BCM_E_NONE, group_id = 0, idx = 0;
    772     int port = 0, subport_group = -1;
    773     int subtag_to_subport_port_tab_idx = -1;
    774     bcm_vlan_t vlan_id;
    775     soc_mem_t mem;
    776     subport_tag_sgpp_map_entry_t subport_tag_to_sgpp_port_map_entry;
    777     soc_info_t *si = &SOC_INFO(unit);
    778 
    779     if (!_BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, subport)) {
    780         LOG_ERROR(BSL_LS_BCM_SUBPORT,
    781                       (BSL_META_U(unit,"ERROR: gport 0x%x is not SubTag "
    782                                        "subport port type.\n"),
    783                                   subport));
    784         return BCM_E_PARAM;
    785     }
    786 
    787     for (idx=0; idx < si->max_subport_coe_ports; idx++) {
    788         if(_bcm_subtag_subport_port_info[unit][idx].subport_port ==
    789             subport) {
    790             break;
    791         }
    792     }
    793 
    794     if(idx >= si->max_subport_coe_ports) {
    795         LOG_ERROR(BSL_LS_BCM_SUBPORT,
    796                       (BSL_META_U(unit,"ERROR: subport_gport 0x%x "
    797                                        "not configured.\n"),
    798                                   subport));
    799         return BCM_E_NOT_FOUND;
    800     }
    801 
    802     if (!_BCM_SUBPORT_COE_SUBTAG_PORT_INFO_VALID_GET(unit, idx)) {
    803         LOG_ERROR(BSL_LS_BCM_SUBPORT,
    804                       (BSL_META_U(unit,"ERROR: SubTag subport port "
    805                                        "gport 0x%x is invalid\n"),
    806                                   subport));
    807         return BCM_E_NOT_FOUND;
    808     }
    809 
    810     /* Extract the associated group */
    811     subport_group =
    812         _BCM_SUBPORT_COE_SUBTAG_PORT_INFO_GROUP_GET(unit, idx);
    813 
    814     /* Extract the associated front panel port */
    815     port = _BCM_SUBPORT_COE_GROUP_PORT_GET(subport_group);
    816 
    817     /* Get the idx associated with 'SUBPORT_TAG_SGPP_MAPm' entry */
    818     subtag_to_subport_port_tab_idx =
    819         _BCM_SUBPORT_COE_SUBTAG_PORT_INFO_TCAM_HW_ID_GET(unit, idx);
    820 
    821     mem = SUBPORT_COE_HW_SUBPORT_SUBTAG_SGPP_MEM(unit);
    822     if (subtag_to_subport_port_tab_idx < 0 ||
    823         subtag_to_subport_port_tab_idx > soc_mem_index_max(unit,mem)) {
    824         LOG_ERROR(BSL_LS_BCM_SUBPORT,
    825                       (BSL_META_U(unit,"ERROR: SubTag subport port gport "
    826                                        "0x%x is not found.\n"
    827                                        "subtag_to_pp_port  tcam idx = %d\n")
    828                                        ,subport, 
    829                                         subtag_to_subport_port_tab_idx));
    830         return BCM_E_NOT_FOUND;
    831     }
    832 
    833     /* Get the associated VLAN */
    834     vlan_id = _BCM_SUBPORT_COE_SUBTAG_PORT_INFO_VLAN_GET(unit, idx) &
    835               0xFFF;
    836 
    837     /* Make sure the VLAN is indeed configured */
    838     if (!_BCM_COE_SUBTAG_VLAN_ID_USED_GET(unit, port, vlan_id)) {
    839         LOG_ERROR(BSL_LS_BCM_SUBPORT,
    840                       (BSL_META_U(unit,"ERROR: SubTag subport port gport "
    841                                        "0x%x is not found.\n"
    842                                         "VLAN id = %d is not set for "
    843                                         "port %d\n"),
    844                                         subport, vlan_id, port));
    845         return BCM_E_NOT_FOUND;
    846     }
    847 
    848     /*
    849     * Clean port, VLAN ID to subport mapping
    850     */
    851     rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, subtag_to_subport_port_tab_idx,
    852              &subport_tag_to_sgpp_port_map_entry);
    853     soc_mem_field32_set(unit, mem,
    854                         (uint32 *)&subport_tag_to_sgpp_port_map_entry,
    855                         SUBPORT_COE_HW_SUBPORT_SUBTAG_SGPP(unit)->subport_tag,
    856                         0);
    857     soc_mem_field32_set(unit, mem,
    858                         (uint32 *)&subport_tag_to_sgpp_port_map_entry,
    859                         SUBPORT_COE_HW_SUBPORT_SUBTAG_SGPP(unit)->valid, 0);
    860 
    861     /* Clean PHB for the subport */
    862     soc_mem_field32_set(unit, mem,
    863                         (uint32 *)&subport_tag_to_sgpp_port_map_entry,
    864                        SUBPORT_COE_HW_SUBPORT_SUBTAG_SGPP(unit)->phb_enable, 0);
    865     soc_mem_field32_set(unit, mem,
    866                         (uint32 *)&subport_tag_to_sgpp_port_map_entry,
    867                         SUBPORT_COE_HW_SUBPORT_SUBTAG_SGPP(unit)->int_pri, 0);
    868     soc_mem_field32_set(unit, mem, 
    869                         (uint32 *)&subport_tag_to_sgpp_port_map_entry,
    870                         SUBPORT_COE_HW_SUBPORT_SUBTAG_SGPP(unit)->cng, 0);
    871     rv = soc_mem_write(unit, mem, MEM_BLOCK_ANY, 
    872                          subtag_to_subport_port_tab_idx,
    873                          &subport_tag_to_sgpp_port_map_entry);
    874     if (SOC_FAILURE(rv)) {
    875         LOG_ERROR(BSL_LS_BCM_SUBPORT,
    876                       (BSL_META_U(unit,"ERROR: subport_tag %d to sgpp %d "
    877                                   "map failed.\n"), vlan_id,
    878                                              subtag_to_subport_port_tab_idx));
    879         return rv;
    880     }
    881 
    882     /*
    883      * Clean SGPP to Physical port mapping
    884      */
    885 
    886     mem = SUBPORT_COE_HW_MODPORT_MAP_SUBPORT_MEM(unit);
    887     rv = soc_mem_field32_modify(unit, mem, 
    888              _BCM_SUBPORT_COE_SUBTAG_PORT_INFO_MODPORT_IDX_GET(unit, idx),
    889              SUBPORT_COE_HW_MODPORT_MAP_SUBPORT(unit)->dest, 0);
    890 
    891     rv = soc_mem_field32_modify(unit, mem, 
    892              _BCM_SUBPORT_COE_SUBTAG_PORT_INFO_MODPORT_IDX_GET(unit, idx),
    893              SUBPORT_COE_HW_MODPORT_MAP_SUBPORT(unit)->enable, 0);
    894 
    895     if (SOC_FAILURE(rv)) {
    896         LOG_ERROR(BSL_LS_BCM_SUBPORT,
    897                     (BSL_META_U(unit,"ERROR: Cleaning mod_port to subport id "
    898                                        "%d to physical port "
    899                                        "map failed.\n"), subport));
    900         return rv;
    901     }
    902 
    903 #if defined(INCLUDE_L3)
    904     /* Adjust the encoded offset and delete the allocated next-hop */
    905     if(_bcm_subtag_subport_port_info[unit][idx].nh_index != -1) {
    906         BCM_IF_ERROR_RETURN(bcm_xgs3_nh_del(unit, 0,
    907             _bcm_subtag_subport_port_info[unit][idx].nh_index - 
    908             BCM_XGS3_DVP_EGRESS_IDX_MIN(unit)));
    909     }
    910 #endif
    911 
    912     BCM_IF_ERROR_RETURN(_bcm_coe_subtag_subport_lport_entry_delete(unit,
    913                _bcm_subtag_subport_port_info[unit][idx].modport_subport_idx));
    914 
    915     _BCM_COE_SUBTAG_VLAN_ID_USED_CLR(unit, port, vlan_id);
    916 
    917     group_id = _BCM_SUBPORT_COE_GROUP_ID_GET(subport_group);
    918     *(_bcm_subport_group_subport_port_count[unit] + group_id) -= 1;
    919 
    920     _BCM_SUBPORT_COE_SUBTAG_PORT_INFO_SET(unit, idx,
    921                               subtag_to_subport_port_tab_idx,
    922                               BCM_GPORT_INVALID,
    923                               BCM_VLAN_INVALID,
    924                               -1, -1, -1, -1, -1, FALSE, -1);
    925 
    926 #ifdef BCM_WARM_BOOT_SUPPORT
    927     SOC_CONTROL_LOCK(unit);
    928     SOC_CONTROL(unit)->scache_dirty = 1;
    929     SOC_CONTROL_UNLOCK(unit);
    930 #endif
    931 
    932     return rv;
    933 }
    934 
    935 
    936 int bcmi_xgs5_subport_coe_port_delete(int unit, bcm_gport_t subport)
    937 {
    938     int rv = BCM_E_NONE;
    939 
    940     _BCM_SUBPORT_COE_CHECK_INIT(unit);
    941 
    942     if (!BCM_GPORT_IS_SUBPORT_PORT(subport)) {
    943         LOG_ERROR(BSL_LS_BCM_SUBPORT,
    944                       (BSL_META_U(unit,"ERROR: gport 0x%x is not "
    945                                        "subport port gport\n"),
    946                                        subport));
    947         return BCM_E_PARAM;
    948     }
    949 
    950     _BCM_SUBPORT_COE_LOCK(unit);
    951 
    952     if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) &&
    953         _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, subport)) {
    954         rv = _bcm_coe_subtag_subport_port_delete(unit, subport);
    955     }
    956 
    957     if (SOC_FAILURE(rv)) {
    958         LOG_ERROR(BSL_LS_BCM_SUBPORT,
    959                       (BSL_META_U(unit,"ERROR: Subport port 0x%x "
    960                                        "delete failed. rv = %d(%s)\n"),
    961                                         subport, rv, soc_errmsg(rv)));
    962         _BCM_SUBPORT_COE_UNLOCK(unit);
    963         return rv;
    964     }
    965 
    966     _BCM_SUBPORT_COE_UNLOCK(unit);
    967 
    968 #ifdef BCM_WARM_BOOT_SUPPORT
    969     SOC_CONTROL_LOCK(unit);
    970     SOC_CONTROL(unit)->scache_dirty = 1;
    971     SOC_CONTROL_UNLOCK(unit);
    972 #endif
    973 
    974     return rv;
    975 
    976 }
    977 
    978 /*
    979  * Function:
    980  *      _bcm_coe_subtag_subport_group_create
    981  * Purpose:
    982  *      Create a SubTag subport group
    983  * Parameters:
    984  *      unit        - (IN) Device Number
    985  *      port        - (IN) Front panel port
    986  *      group_id    - (IN) Group Id being configured
    987  *      group  - (OUT) GPORT (generic port) identifier
    988  * Returns:
    989  *      BCM_E_XXX
    990  */
    991 STATIC int
    992 _bcm_coe_subtag_subport_group_create(int unit, bcm_port_t port,
    993                                      int group_id, bcm_gport_t *group)
    994 {
    995 
    996     int rv = BCM_E_NONE;
    997 
    998     _BCM_SUBPORT_COE_CHECK_INIT(unit);
    999 
   1000     _BCM_SUBPORT_COE_SUBTAG_GROUP_SET(*group, port, group_id);
   1001     _BCM_SUBPORT_COE_GROUP_TYPE_CASCADED_SET(*group);
   1002 
   1003     _BCM_SUBPORT_COE_SUBTAG_GROUP_USED_SET(unit, group_id);
   1004     _bcm_subtag_subport_group_count[unit]++;
   1005 
   1006     /* Also, set the SUBPORT_TAG_NAMESPACE to be same as the port number */
   1007 
   1008     BCM_IF_ERROR_RETURN(_bcm_esw_port_tab_set(unit, port,
   1009            _BCM_CPU_TABS_NONE, SUBPORT_TAG_NAMESPACEf, port));
   1010 
   1011     return rv;
   1012 }
   1013 
   1014 /*
   1015  * Function:
   1016  *      bcmi_xgs5_subport_coe_group_create
   1017  * Purpose:
   1018  *      Create a subport group
   1019  * Parameters:
   1020  *      unit   - (IN) Device Number
   1021  *      config - (IN) Subport group config information
   1022  *      group  - (OUT) GPORT (generic port) identifier
   1023  * Returns:
   1024  *      BCM_E_XXX
   1025  */
   1026 int bcmi_xgs5_subport_coe_group_create(int unit,
   1027                                      bcm_subport_group_config_t *config,
   1028                                      bcm_gport_t *group)
   1029 {
   1030     int rv = BCM_E_NONE, group_id = 0, i = 0;
   1031     bcm_port_t port;
   1032     soc_info_t *si = &SOC_INFO(unit);
   1033 
   1034     /* Ensure the subport module is initialized */
   1035     _BCM_SUBPORT_COE_CHECK_INIT(unit);
   1036 
   1037     if (!(config->flags & BCM_SUBPORT_GROUP_TYPE_SUBPORT_TAG)) {
   1038         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   1039                       (BSL_META_U(unit,"ERROR: The group type has to "
   1040                                        "be SUBPORT_TAG\n")));
   1041         return BCM_E_PARAM;
   1042     }
   1043 
   1044     /* Validate the passed in front panel port */
   1045     rv = _bcm_esw_port_gport_validate(unit, config->port, &port);
   1046     if (SOC_FAILURE(rv)) {
   1047         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   1048                       (BSL_META_U(unit,"ERROR: Invalid gport 0x%x for "
   1049                                        "subport group create.\n"),
   1050                                   config->port));
   1051         return BCM_E_PORT;
   1052     }
   1053 
   1054     /* Ensure that the physical port can be a cascaded port */
   1055     if ((config->flags & BCM_SUBPORT_GROUP_TYPE_SUBPORT_TAG) &&
   1056         !BCM_PBMP_MEMBER(si->subtag_pbm, port)) {
   1057             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   1058                       (BSL_META_U(unit,"ERROR: SubportTag/CoE "
   1059                                        "should be enabled"
   1060                                        " for port %d\n"), port));
   1061             return BCM_E_PORT;
   1062     }
   1063 
   1064     /* If max groups aready taken up, error out */
   1065     if (_bcm_subport_group_count[unit] == si->max_subport_coe_groups) {
   1066         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   1067                       (BSL_META_U(unit,"ERROR: All %d subport "
   1068                                        "groups already used.\n"),
   1069                                        si->max_subport_coe_groups));
   1070         return BCM_E_FULL;
   1071     }
   1072 
   1073     if (config->flags & BCM_SUBPORT_GROUP_WITH_ID) {
   1074         group_id = BCM_GPORT_SUBPORT_GROUP_GET(*group);
   1075         /* Group id should be within 0 to 512.
   1076         * BCM_GPORT_SUBPORT_GROUP_MASK is 0xffffff (for all chips)
   1077         * but subtag group id is only first 9 bits (8-0). 
   1078         * Check that only subtag group id bits (8-0) are configured*/
   1079         if ((group_id >> _BCM_SUBPORT_COE_GROUP_PORT_SHIFT)
   1080                 & _SHR_GPORT_SUBPORT_GROUP_MASK) {
   1081             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   1082                       (BSL_META_U(unit,"ERROR: subport group id = %d "
   1083                                        "should be within 0 to"
   1084                                        " %d\n"), 
   1085                                        group_id, 
   1086                                        si->max_subport_coe_groups-1));
   1087             return BCM_E_PARAM;
   1088         }
   1089         if (_BCM_SUBPORT_COE_GROUP_USED_GET(unit, group_id)) {
   1090             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   1091                       (BSL_META_U(unit,"ERROR: subport group id = %d "
   1092                                        "is already used\n"), group_id));
   1093             return BCM_E_EXISTS;
   1094         }
   1095     } else {
   1096         /* If without Id, grab a free group */
   1097         for (i =0; i < si->max_subport_coe_groups; i++) {
   1098             if (!_BCM_SUBPORT_COE_GROUP_USED_GET(unit, i)) {
   1099                 group_id = i;
   1100                 break;
   1101             }
   1102         }
   1103 
   1104         if (i == si->max_subport_coe_groups) {
   1105             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   1106                       (BSL_META_U(unit,"ERROR: All %d subport groups "
   1107                                        "already used.\n"), i));
   1108             return BCM_E_FULL;
   1109         }
   1110     }
   1111 
   1112     _BCM_SUBPORT_COE_LOCK(unit);
   1113 
   1114     if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) && 
   1115         (config->flags & BCM_SUBPORT_GROUP_TYPE_SUBPORT_TAG)) {
   1116             rv  =_bcm_coe_subtag_subport_group_create(unit, port, 
   1117                                                       group_id, group);
   1118             if (SOC_FAILURE(rv)) {
   1119                 LOG_ERROR(BSL_LS_BCM_SUBPORT,
   1120                       (BSL_META_U(unit,"ERROR: SubTag subport group "
   1121                                        "create failed"
   1122                                        " for port %d. rv = %d(%s)\n"),
   1123                                   config->port, rv, soc_errmsg(rv)));
   1124                 _BCM_SUBPORT_COE_UNLOCK(unit);
   1125                 return rv;
   1126             }
   1127     }
   1128 
   1129     _BCM_SUBPORT_COE_GROUP_USED_SET(unit, group_id);
   1130     _bcm_subport_group_count[unit]++;
   1131 
   1132     _BCM_SUBPORT_COE_UNLOCK(unit);
   1133 
   1134 
   1135 #ifdef BCM_WARM_BOOT_SUPPORT
   1136     SOC_CONTROL_LOCK(unit);
   1137     SOC_CONTROL(unit)->scache_dirty = 1;
   1138     SOC_CONTROL_UNLOCK(unit);
   1139 #endif
   1140 
   1141     return BCM_E_NONE;
   1142 }
   1143 
   1144 /*
   1145  * Function:
   1146  *      _bcm_coe_subtag_subport_group_destroy
   1147  * Purpose:
   1148  *      Create a SubTag subport group
   1149  * Parameters:
   1150  *      unit        - (IN) Device Number
   1151  *      port        - (IN) Front panel port
   1152  *      group_id    - (IN) Group Id being configured
   1153  *      group  - (OUT) GPORT (generic port) identifier
   1154  * Returns:
   1155  *      BCM_E_XXX
   1156  */
   1157 STATIC int
   1158 _bcm_coe_subtag_subport_group_destroy(int unit, bcm_gport_t group)
   1159 {
   1160     int group_id = -1, i = 0;
   1161     int pp_port = 0, rv = BCM_E_NONE;
   1162     int subtag_subport_count = 0;
   1163     soc_info_t *si = &SOC_INFO(unit);
   1164 
   1165     _BCM_SUBPORT_COE_CHECK_INIT(unit);
   1166 
   1167     if (_BCM_COE_GPORT_IS_SUBTAG_SUBPORT_GROUP(group)) {
   1168 
   1169         group_id = _BCM_SUBPORT_COE_GROUP_ID_GET(group);
   1170 
   1171         if (!_BCM_SUBPORT_COE_SUBTAG_GROUP_USED_GET(unit, group_id)) {
   1172             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   1173                       (BSL_META_U(unit,"ERROR: SubTag subport group "
   1174                                        "0x%x not found.\n"), group));
   1175             return BCM_E_NOT_FOUND;
   1176         }
   1177 
   1178         subtag_subport_count =
   1179             *(_bcm_subport_group_subport_port_count[unit] + group_id);
   1180 
   1181         for (i=0; i < si->max_subport_coe_ports; i++) {
   1182 
   1183             if (subtag_subport_count == 0) {
   1184                break;
   1185             }
   1186 
   1187             if (!_BCM_SUBPORT_COE_SUBTAG_PORT_INFO_VALID_GET(unit, i)) {
   1188                continue;
   1189             }
   1190 
   1191             if (group !=
   1192                _BCM_SUBPORT_COE_SUBTAG_PORT_INFO_GROUP_GET(unit, i)) {
   1193                continue;
   1194             }
   1195 
   1196             rv = _bcm_coe_subtag_subport_port_delete(unit, 
   1197                       _bcm_subtag_subport_port_info[unit][i].subport_port);
   1198             if (SOC_FAILURE(rv)) {
   1199                 LOG_ERROR(BSL_LS_BCM_SUBPORT,
   1200                       (BSL_META_U(unit,"ERROR: SubTag subport group "
   1201                                        "0x%x destroy failed \n"
   1202                                        " to delete subport port (subport group id %d, "
   1203                                         " subport id %d)\n"), group, group_id, pp_port));
   1204                 return rv;
   1205             }
   1206             subtag_subport_count--;
   1207         }
   1208 
   1209         *(_bcm_subport_group_subport_port_count[unit] + group_id) = 0;
   1210         /* delete the subport group */
   1211         _bcm_subport_group_count[unit]--;
   1212         _BCM_SUBPORT_COE_GROUP_USED_CLR(unit, group_id);
   1213         _bcm_subtag_subport_group_count[unit]--;
   1214         _BCM_SUBPORT_COE_SUBTAG_GROUP_USED_CLR(unit, group_id);
   1215 
   1216     }
   1217 
   1218     return BCM_E_NONE;
   1219 }
   1220 
   1221 /*
   1222  * Function:
   1223  *      bcmi_xgs5_subport_coe_group_destroy
   1224  * Purpose:
   1225  *      Destroy a subport group and all subport ports attached to it.
   1226  * Parameters:
   1227  *      unit   - (IN) Device Number
   1228  *      group  - (IN) GPORT (generic port) identifier for subport group
   1229  * Returns:
   1230  *      BCM_E_XXX
   1231  */
   1232 int bcmi_xgs5_subport_coe_group_destroy(int unit, bcm_gport_t group)
   1233 {
   1234     int rv = BCM_E_NONE;
   1235     soc_info_t *si = &SOC_INFO(unit);
   1236 
   1237     _BCM_SUBPORT_COE_CHECK_INIT(unit);
   1238 
   1239     if (!BCM_GPORT_IS_SUBPORT_GROUP(group)) {
   1240         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   1241                       (BSL_META_U(unit,"ERROR: group 0x%x is not subport "
   1242                                        "group gport\n"), group));
   1243         return BCM_E_PARAM;
   1244     }
   1245 
   1246     _BCM_SUBPORT_COE_LOCK(unit);
   1247 
   1248     if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) &&
   1249         _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_GROUP(group)) {
   1250         if (BCM_PBMP_IS_NULL(si->subtag_pbm)) {
   1251             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   1252                       (BSL_META_U(unit,"ERROR: SubTag ports not "
   1253                                        "configured\n")));
   1254             _BCM_SUBPORT_COE_UNLOCK(unit);
   1255             return BCM_E_PARAM;
   1256         }
   1257         rv = _bcm_coe_subtag_subport_group_destroy(unit, group);
   1258     }
   1259 
   1260     if (SOC_FAILURE(rv)) {
   1261         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   1262                       (BSL_META_U(unit,"ERROR: subport group 0x%x "
   1263                                        "destroy failed. rv= %d(%s)\n"),
   1264                                         group, rv, soc_errmsg(rv)));
   1265         _BCM_SUBPORT_COE_UNLOCK(unit);
   1266         return rv;
   1267     }
   1268 
   1269     _BCM_SUBPORT_COE_UNLOCK(unit);
   1270 
   1271 #ifdef BCM_WARM_BOOT_SUPPORT
   1272     SOC_CONTROL_LOCK(unit);
   1273     SOC_CONTROL(unit)->scache_dirty = 1;
   1274     SOC_CONTROL_UNLOCK(unit);
   1275 #endif
   1276 
   1277     return BCM_E_NONE;
   1278 }
   1279 
   1280 /*
   1281  * Function:
   1282  *      _bcm_coe_subtag_subport_group_get
   1283  * Purpose:
   1284  *      Create a SubTag subport group
   1285  * Parameters:
   1286  *      unit        - (IN) Device Number
   1287  *      group_id    - (IN) Group Id being configured
   1288  *      group  - (OUT) GPORT (generic port) identifier
   1289  * Returns:
   1290  *      BCM_E_XXX
   1291  */
   1292 STATIC int
   1293 _bcm_coe_subtag_subport_group_get(int unit, bcm_gport_t group,
   1294                                   bcm_subport_group_config_t *config)
   1295 {
   1296     int group_id = -1;
   1297 
   1298     _BCM_SUBPORT_COE_CHECK_INIT(unit);
   1299 
   1300     if (config == NULL) {
   1301         return BCM_E_PARAM;
   1302     }
   1303 
   1304     if (_BCM_COE_GPORT_IS_SUBTAG_SUBPORT_GROUP(group)) {
   1305         group_id = _BCM_SUBPORT_COE_GROUP_ID_GET(group);
   1306         if (!_BCM_SUBPORT_COE_SUBTAG_GROUP_USED_GET(unit, group_id)) {
   1307             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   1308                       (BSL_META_U(unit,"ERROR: SubTag subport "
   1309                                        "group 0x%x not found.\n"), group));
   1310             return BCM_E_NOT_FOUND;;
   1311         }
   1312         config->flags |= BCM_SUBPORT_GROUP_TYPE_SUBPORT_TAG;
   1313         config->port = _BCM_SUBPORT_COE_GROUP_PORT_GET(group);
   1314     } else {
   1315         return BCM_E_PARAM;
   1316     }
   1317 
   1318     return BCM_E_NONE;
   1319 }
   1320 
   1321 /*
   1322  * Function:
   1323  *      bcmi_xgs5_subport_coe_group_get
   1324  * Purpose:
   1325  *      Get a subport group
   1326  * Parameters:
   1327  *      unit   - (IN) Device Number
   1328  *      group  - (IN) GPORT (generic port) identifier
   1329  *      config - (OUT) Subport group config information
   1330  * Returns:
   1331  *      BCM_E_XXX
   1332  */
   1333 
   1334 int bcmi_xgs5_subport_coe_group_get(int unit, bcm_gport_t group,
   1335                                      bcm_subport_group_config_t *config)
   1336 {
   1337     int rv = BCM_E_NONE;
   1338     soc_info_t *si = &SOC_INFO(unit);
   1339 
   1340     _BCM_SUBPORT_COE_CHECK_INIT(unit);
   1341 
   1342     if (config == NULL) {
   1343         return BCM_E_PARAM;
   1344     }
   1345 
   1346     if (!BCM_GPORT_IS_SUBPORT_GROUP(group)) {
   1347         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   1348                       (BSL_META_U(unit,"ERROR: group 0x%x is not "
   1349                                        "subport group gport\n"),
   1350                                         group));
   1351         return BCM_E_PARAM;
   1352     }
   1353 
   1354     _BCM_SUBPORT_COE_LOCK(unit);
   1355 
   1356     if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) &&
   1357         _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_GROUP(group)) {
   1358         if (BCM_PBMP_IS_NULL(si->subtag_pbm)) {
   1359             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   1360                       (BSL_META_U(unit,"ERROR: SubTag ports not "
   1361                                        "configured\n")));
   1362             _BCM_SUBPORT_COE_UNLOCK(unit);
   1363             return BCM_E_PARAM;
   1364         }
   1365         rv = _bcm_coe_subtag_subport_group_get(unit, group, config);
   1366     }
   1367 
   1368     if (SOC_FAILURE(rv)) {
   1369         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   1370                       (BSL_META_U(unit,"ERROR: subport group get "
   1371                                        "failed for 0x%x, rv = %d(%s)\n"),
   1372                                         group, rv, soc_errmsg(rv)));
   1373         _BCM_SUBPORT_COE_UNLOCK(unit);
   1374         return rv;
   1375     }
   1376 
   1377     _BCM_SUBPORT_COE_UNLOCK(unit);
   1378 
   1379     return BCM_E_NONE;
   1380 }
   1381 
   1382 
   1383 /*
   1384  * Function:
   1385  *      _bcm_coe_subtag_subport_group_traverse
   1386  * Purpose:
   1387  *      Traverse all valid subports for given SubTag subport group
   1388  *      and call the user supplied callback routine.
   1389  * Parameters:
   1390  *      unit      - Device Number
   1391  *      group     - Subport group GPORT identifier
   1392  *      cb        - User callback function, called once per subport.
   1393  *      user_data - cookie
   1394  */
   1395 
   1396 STATIC int
   1397 _bcm_coe_subtag_subport_group_traverse(int unit,
   1398                                    bcm_gport_t group,
   1399                                    bcm_subport_port_traverse_cb cb,
   1400                                    void *user_data)
   1401 {
   1402 
   1403     int rv = BCM_E_NONE, group_id = 0, i = 0;
   1404     int subtag_subport_count = 0;
   1405     bcm_subport_config_t config;
   1406     soc_info_t *si = &SOC_INFO(unit);
   1407 
   1408     _BCM_SUBPORT_COE_CHECK_INIT(unit);
   1409 
   1410     bcm_subport_config_t_init(&config);
   1411 
   1412     if (_BCM_COE_GPORT_IS_SUBTAG_SUBPORT_GROUP(group)) {
   1413         group_id = _BCM_SUBPORT_COE_GROUP_ID_GET(group);
   1414 
   1415         if (!_BCM_SUBPORT_COE_SUBTAG_GROUP_USED_GET(unit, group_id)) {
   1416             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   1417                       (BSL_META_U(unit,"ERROR: SubTag subport group "
   1418                                        "0x%x not found.\n"), group));
   1419             return BCM_E_NOT_FOUND;
   1420         }
   1421 
   1422         subtag_subport_count =
   1423             *(_bcm_subport_group_subport_port_count[unit] + group_id);
   1424 
   1425 
   1426         for (i=0; i < si->max_subport_coe_ports; i++) {
   1427 
   1428             if (subtag_subport_count == 0) {
   1429                break;
   1430             }
   1431 
   1432             if (!_BCM_SUBPORT_COE_SUBTAG_PORT_INFO_VALID_GET(unit, i)) {
   1433                continue;
   1434             }
   1435 
   1436             if (group !=
   1437                _BCM_SUBPORT_COE_SUBTAG_PORT_INFO_GROUP_GET(unit, i)) {
   1438                continue;
   1439             }
   1440 
   1441             rv = _bcm_coe_subtag_subport_port_get(unit, 
   1442                      _bcm_subtag_subport_port_info[unit][i].subport_port, 
   1443                     &config);
   1444             if (SOC_FAILURE(rv)) {
   1445                 LOG_ERROR(BSL_LS_BCM_SUBPORT,
   1446                       (BSL_META_U(unit,"ERROR: SubTag subport group "
   1447                                        "0x%x traverse failed \n"
   1448                                        "to get subport port (group id %d, "
   1449                                        "subport id %d)\n"),
   1450                                         group, group_id,
   1451                        _bcm_subtag_subport_port_info[unit][i].subport_port));
   1452                 return rv;
   1453             }
   1454             /* coverity[returned_value] */
   1455             rv = cb(unit, 
   1456                     _bcm_subtag_subport_port_info[unit][i].subport_port, 
   1457                     &config, 
   1458                     user_data);
   1459 #ifdef BCM_CB_ABORT_ON_ERR
   1460             if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) {
   1461                 LOG_ERROR(BSL_LS_BCM_SUBPORT,
   1462                       (BSL_META_U(unit,"ERROR: subport group 0x%x "
   1463                                        "traverse failed \n"
   1464                                        "to callback for subport "
   1465                                        "port (group id %d, subport id %d)\n"), 
   1466                                        group, group_id, 
   1467                        _bcm_subtag_subport_port_info[unit][i].subport_port));
   1468                 return rv;
   1469             }
   1470 #endif
   1471             subtag_subport_count--;
   1472         }
   1473     } else {
   1474         return BCM_E_PARAM;
   1475     }
   1476     return BCM_E_NONE;
   1477 }
   1478 
   1479 /*
   1480  * Function:
   1481  *      bcmi_xgs5_subport_coe_group_traverse
   1482  * Purpose:
   1483  *      Traverse all valid subports for given subport group and call the user
   1484  *      supplied callback routine.
   1485  * Parameters:
   1486  *      unit      - Device Number
   1487  *      group     - Subport group GPORT identifier
   1488  *      cb        - User callback function, called once per subport.
   1489  *      user_data - cookie
   1490  */
   1491 
   1492 int bcmi_xgs5_subport_coe_group_traverse(int unit, bcm_gport_t group,
   1493                                      bcm_subport_port_traverse_cb cb,
   1494                                      void *user_data)
   1495 {
   1496     int rv = BCM_E_NONE;
   1497     soc_info_t *si = &SOC_INFO(unit);
   1498 
   1499     _BCM_SUBPORT_COE_CHECK_INIT(unit);
   1500 
   1501     if (!BCM_GPORT_IS_SUBPORT_GROUP(group)) {
   1502         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   1503                       (BSL_META_U(unit,"ERROR: group 0x%x is not subport "
   1504                                        "group gport\n"), group));
   1505         return BCM_E_PARAM;
   1506     }
   1507 
   1508     _BCM_SUBPORT_COE_LOCK(unit);
   1509 
   1510     if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) &&
   1511         _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_GROUP(group)) {
   1512         if (BCM_PBMP_IS_NULL(si->subtag_pbm)) {
   1513             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   1514                       (BSL_META_U(unit,"ERROR: SubTag ports not "
   1515                                        "configured\n")));
   1516             _BCM_SUBPORT_COE_UNLOCK(unit);
   1517             return BCM_E_PARAM;
   1518         }
   1519         rv =_bcm_coe_subtag_subport_group_traverse(unit, group, cb, user_data);
   1520     }
   1521 
   1522     if (SOC_FAILURE(rv)) {
   1523         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   1524                       (BSL_META_U(unit,"ERROR: subport group traverse failed for "
   1525                                        "0x%x, rv = %d(%s)\n"),
   1526                                         group, rv, soc_errmsg(rv)));
   1527         _BCM_SUBPORT_COE_UNLOCK(unit);
   1528         return rv;
   1529     }
   1530 
   1531     _BCM_SUBPORT_COE_UNLOCK(unit);
   1532 
   1533     return BCM_E_NONE;
   1534 }
   1535 
   1536 /*
   1537  * Function:
   1538  *      _bcm_coe_subport_free_entry_find
   1539  * Purpose:
   1540  *      Search for unused entry in the SUBPORT_TAG_SGPP_MAP table
   1541  * Parameters:
   1542  *      unit - Device unit number
   1543  *      index - (OUT) index where found
   1544  * Returns:
   1545  *      BOC_E_NONE      - free entry found
   1546  *      BOC_E_FULL      - no free entries found
   1547  */
   1548 STATIC int 
   1549 _bcm_coe_subport_free_entry_find(int unit, int *free_index)
   1550 {
   1551     int index;
   1552     soc_info_t *si=&SOC_INFO(unit);
   1553 
   1554     if(_bcm_subtag_subport_port_info[unit] == NULL) {
   1555         return BCM_E_INTERNAL;
   1556     }
   1557     for (index = 0; index < si->max_subport_coe_ports; index++) {
   1558         if (_bcm_subtag_subport_port_info[unit][index].valid == 0) {
   1559             /* Return the first unused entry*/
   1560             *free_index = index;
   1561             return BCM_E_NONE;
   1562         }
   1563     }
   1564 
   1565     /* If we fall through, the table is full */
   1566     return BCM_E_FULL;
   1567 }
   1568 
   1569 /*
   1570  * Function:
   1571  *      _bcm_coe_subport_allocate_modport
   1572  * Purpose:
   1573  *      Search for unused entry from CoE modules configured
   1574  * Parameters:
   1575  *      unit - Device unit number
   1576  *      mod  - (OUT) ModuleId of free module
   1577  *      port - (OUT) Port num of free free port on the module
   1578  * Returns:
   1579  *      BOC_E_NONE      - free entry found
   1580  *      BOC_E_FULL      - no free entries found
   1581  */
   1582 STATIC int 
   1583 _bcm_coe_subport_allocate_modport(int unit,int *mod, int *port)
   1584 {
   1585     int i, j, rv;
   1586     bcm_stk_modid_config_t modIdInfo[TD2P_MAX_COE_MODULES];
   1587     bcm_gport_t coe_system_gport;
   1588     soc_info_t *si=&SOC_INFO(unit);
   1589     SHR_BITDCL *mod_port_bitmap[TD2P_MAX_COE_MODULES] = { NULL };
   1590     int mod_port_used[TD2P_MAX_COE_MODULES] = { 0 };
   1591     int modid, portid;
   1592     unsigned int size;
   1593 
   1594     if(_bcm_subtag_subport_port_info[unit] == NULL) {
   1595         return BCM_E_INTERNAL;
   1596     }
   1597 
   1598     /* Initialize the (mod,port) info */
   1599     for(i = 0; i < si->num_coe_modules; i++) {
   1600         modIdInfo[i].modid = modIdInfo[i].num_ports = -1;
   1601         size = SHR_BITALLOCSIZE(TD2P_MAX_SUBPORT_COE_PORT_PER_MOD);
   1602         mod_port_bitmap[i] = 
   1603             sal_alloc(size, "mod_port_bitmap");
   1604         if (mod_port_bitmap[i] == NULL) {
   1605             rv = BCM_E_MEMORY;
   1606             goto cleanup;
   1607         }
   1608         sal_memset(mod_port_bitmap[i], 0, size);
   1609     }
   1610 
   1611     /* Get the configured CoE module-port info */
   1612     _bcm_stk_aux_modport_info_get(unit, BCM_MODID_TYPE_COE, modIdInfo);
   1613 
   1614     /* Create mod port bitmap */
   1615     for (i = 0; i < si->max_subport_coe_ports; i++){
   1616         if(_BCM_SUBPORT_COE_SUBTAG_PORT_INFO_VALID_GET(unit, i)) {
   1617             coe_system_gport = 
   1618                 _BCM_SUBPORT_COE_SUBTAG_PORT_INFO_SUBPORT_MODPORT_GET(unit, i);
   1619             modid = BCM_GPORT_MODPORT_MODID_GET(coe_system_gport);
   1620             portid = BCM_GPORT_MODPORT_PORT_GET(coe_system_gport);
   1621             for (j = 0; j < si->num_coe_modules; j++) {
   1622                 if (modid == modIdInfo[j].modid) {
   1623                     mod_port_used[j]++;
   1624                     /* coverity[negative_shift: FALSE] */
   1625                     SHR_BITSET(mod_port_bitmap[j], portid);
   1626                 }
   1627             }
   1628         }
   1629     }
   1630 
   1631     /* Get a unused (mod,port) from the CoE modules */
   1632     rv = BCM_E_FULL;
   1633     for (i = 0; i < si->num_coe_modules; i++) {
   1634         if((modIdInfo[i].modid != BCM_MODID_INVALID) &&
   1635            (modIdInfo[i].num_ports != -1) &&
   1636            (mod_port_used[i] < modIdInfo[i].num_ports)) {
   1637             for(j = 0; j < modIdInfo[i].num_ports; j++) {
   1638                 if (!SHR_BITGET(mod_port_bitmap[i],j)){
   1639                     *mod  = modIdInfo[i].modid;
   1640                     *port = j;
   1641                     rv = BCM_E_NONE;
   1642                     goto cleanup;
   1643                 }
   1644             }
   1645         }
   1646     }
   1647 
   1648 cleanup:
   1649     for(i = 0; i < si->num_coe_modules; i++) {
   1650         if (mod_port_bitmap[i] != NULL) {
   1651             sal_free(mod_port_bitmap[i]);
   1652         }
   1653     }
   1654     return rv;
   1655 }
   1656 
   1657 /*
   1658  * Function:
   1659  *      _bcm_xgs5_subport_coe_mod_port_local
   1660  * Purpose:
   1661  *      Check if a given (mod,port) is local
   1662  * Parameters:
   1663  *      unit   - (IN) Device Number
   1664  *      modid  - (IN) Mod Id value
   1665  *      portid - (IN) Port Id value
   1666  * Returns:
   1667  *      TRUE if local, FALSE otherwise
   1668  */
   1669 
   1670 int _bcm_xgs5_subport_coe_mod_port_local(int unit, int modid, bcm_port_t portid)
   1671 {
   1672     int rv;
   1673 
   1674     /* Check if the passed in (mod,port) is valid on the local device */
   1675     rv = _bcm_stk_aux_modport_valid(unit, BCM_MODID_TYPE_COE, modid, portid);
   1676 
   1677     return ((rv == BCM_E_NONE) ? TRUE : FALSE);
   1678 }
   1679 
   1680 
   1681 /*
   1682  * Function:
   1683  *      _bcm_xgs5_subport_coe_gport_local
   1684  * Purpose:
   1685  *      Check if a given coe-subport-gport is local
   1686  * Parameters:
   1687  *      unit   - (IN) Device Number
   1688  *      modid  - (IN) Mod Id value
   1689  *      portid - (IN) Port Id value
   1690  * Returns:
   1691  *      TRUE if local, FALSE otherwise
   1692  */
   1693 
   1694 int _bcm_xgs5_subport_coe_gport_local(int unit, bcm_gport_t gport)
   1695 {
   1696     int rv;
   1697 
   1698     /* Check if the passed in (mod,port) is valid on the local device */
   1699     rv = _bcm_stk_aux_modport_valid(unit, BCM_MODID_TYPE_COE,
   1700                                     _BCM_SUBPORT_COE_PORT_ID_MOD_GET(gport),
   1701                                     _BCM_SUBPORT_COE_PORT_ID_PORT_GET(gport));
   1702 
   1703     if(rv == BCM_E_NONE) {
   1704         return TRUE;
   1705     } else {
   1706         return FALSE;
   1707     }
   1708 }
   1709 
   1710 /*
   1711  * Function:
   1712  *      _bcm_xgs5_subport_coe_mod_local
   1713  * Purpose:
   1714  *      Check if a given mod is a local-coe-module
   1715  * Parameters:
   1716  *      unit   - (IN) Device Number
   1717  *      modid  - (IN) Mod Id value
   1718  * Returns:
   1719  *      TRUE if local, FALSE otherwise
   1720  */
   1721 
   1722 int _bcm_xgs5_subport_coe_mod_local(int unit, int modid)
   1723 {
   1724     int rv;
   1725 
   1726     /* Check if the passed in (mod,port) is valid on the local device */
   1727     rv = _bcm_stk_aux_mod_valid(unit, BCM_MODID_TYPE_COE, modid);
   1728 
   1729     if(rv == BCM_E_NONE) {
   1730         return TRUE;
   1731     } else {
   1732         return FALSE;
   1733     }
   1734 }
   1735 
   1736 /*
   1737  * Function:
   1738  *      _bcm_coe_subtag_subport_port_add
   1739  * Purpose:
   1740  *      Add a subport to a subport group
   1741  * Parameters:
   1742  *      unit   - (IN) Device Number
   1743  *      config - (IN) Subport config information
   1744  *      gport  - (OUT) Subport_port GPORT (generic port) identifier
   1745  * Returns:
   1746  *      BCM_E_XXX
   1747  */
   1748 
   1749 STATIC int
   1750 _bcm_coe_subtag_subport_port_add(int unit,
   1751                                  bcm_subport_config_t *config,
   1752                                  bcm_gport_t *gport)
   1753 {
   1754     int rv = BCM_E_NONE, subtag_index = -1, subtag_hw_index = -1;
   1755     int sp_group_idx = -1, mod_port_index = 0, modid = 0, portid = 0, port;
   1756     uint16 vlan_id = 0, phb_val = 0;
   1757     soc_mem_t mem;
   1758     uint32  subtag_to_sgpp_entry[SOC_MAX_MEM_FIELD_WORDS]; /* HW entry buffer.*/
   1759 #ifdef BCM_TRIDENT3_SUPPORT
   1760     uint32  subtag_to_sgpp_key[SOC_MAX_MEM_FIELD_WORDS]; /* HW entry buffer.*/
   1761 #endif
   1762     modport_map_subport_entry_t         sgpp_to_port_entry;
   1763 #if defined(INCLUDE_L3)
   1764     bcm_l3_egress_t nh_info;
   1765     egr_l3_next_hop_entry_t egr_nh;
   1766     int nh_index;
   1767 #endif
   1768     soc_info_t *si = &SOC_INFO(unit);
   1769 
   1770     sal_memset(subtag_to_sgpp_entry, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32));
   1771 
   1772     /* Ensure subport module is initialized */
   1773     _BCM_SUBPORT_COE_CHECK_INIT(unit);
   1774 
   1775     /* Ensyre group is of the proper type */
   1776     if (!BCM_GPORT_IS_SUBPORT_GROUP(config->group)) {
   1777         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   1778                       (BSL_META_U(unit,"ERROR: group 0x%x is not "
   1779                                        "subport group gport\n"),
   1780                                         config->group));
   1781         return BCM_E_PARAM;
   1782     }
   1783 
   1784     /* Make sure the group is of correct type */
   1785     if (!_BCM_COE_GPORT_IS_SUBTAG_SUBPORT_GROUP(config->group)) {
   1786         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   1787                       (BSL_META_U(unit,"ERROR: subport group 0x%x is not "
   1788                                        "SubTag group\n"),
   1789                                         config->group));
   1790         return BCM_E_PARAM;
   1791     }
   1792 
   1793     /* Get the group Idx */
   1794     sp_group_idx = _BCM_SUBPORT_COE_GROUP_ID_GET(config->group);
   1795 
   1796     /* Make sure the group exists */
   1797     if (!_BCM_SUBPORT_COE_SUBTAG_GROUP_USED_GET(unit, sp_group_idx)) {
   1798         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   1799                       (BSL_META_U(unit,"ERROR: group 0x%x does not exist. "
   1800                                        "group id =%d\n"),
   1801                                         config->group, sp_group_idx));
   1802         return BCM_E_NOT_FOUND;
   1803     }
   1804 
   1805     /* Get the physical port number from the group Id */
   1806     port = _BCM_SUBPORT_COE_GROUP_PORT_GET(config->group);
   1807 
   1808     /* Check if port is member of pbmp_subtag  */
   1809     if (!SOC_PBMP_MEMBER(si->subtag_pbm, port)) {
   1810         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   1811                       (BSL_META_U(unit,"ERROR: Port %d is not member "
   1812                                        "of pbmp_subport\n"), port));
   1813         return BCM_E_PORT;
   1814     }
   1815 
   1816     /* Ensure the port in question is configured to host 'subtended' port */
   1817     if (si->port_num_subport[port] <= 0) {
   1818         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   1819                       (BSL_META_U(unit,"ERROR: %d number of subports "
   1820                                        "available for port %d\n"),
   1821                                        si->port_num_subport[port], port));
   1822         return BCM_E_CONFIG;
   1823     }
   1824 
   1825     /* Check if the number of subports on this physical port
   1826        is already reached at the configured values */
   1827     if(*(_bcm_subport_group_subport_port_count[unit] + sp_group_idx) >= 
   1828         si->port_num_subport[port]) {
   1829         return BCM_E_FULL;
   1830     }
   1831 
   1832     /* Ensure that the passed in subport_tag is valid */
   1833     if ((config->pkt_vlan & 0xFFF) <= BCM_VLAN_NONE) {
   1834         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   1835                       (BSL_META_U(unit,"ERROR: (config->pkt_vlan & 0xFFF) "
   1836                                        "%d is invalid\n"),
   1837                                         (config->pkt_vlan & 0xFFF)));
   1838         return BCM_E_PARAM;
   1839     }
   1840 
   1841     /* If the PHB is set, check the PRI and Color for sanity */
   1842     if (config->prop_flags & BCM_SUBPORT_PROPERTY_PHB) {
   1843         if (config->int_pri < 0 || config->int_pri > 15) {
   1844             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   1845                       (BSL_META_U(unit,"ERROR: int_pri %d is invalid\n"), 
   1846                        config->int_pri));
   1847             return BCM_E_PARAM;
   1848         }
   1849         if ((config->color != bcmColorGreen) &&
   1850              (config->color != bcmColorYellow) &&
   1851              (config->color != bcmColorRed)) {
   1852              LOG_ERROR(BSL_LS_BCM_SUBPORT,
   1853                       (BSL_META_U(unit,"ERROR: color %d is invalid\n"), 
   1854                        config->color));
   1855             return BCM_E_PARAM;
   1856         }
   1857     }
   1858 
   1859     /* Check if the VLAN passed is valid */
   1860     VLAN_CHK_ID(unit, config->pkt_vlan);
   1861 
   1862     /* Check if VLAN id is alredy used for the port */
   1863     vlan_id = config->pkt_vlan & 0xFFF; 
   1864 
   1865     if (_BCM_COE_SUBTAG_VLAN_ID_USED_GET(unit, port, vlan_id)) {
   1866         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   1867                       (BSL_META_U(unit,"ERROR: VLAN id %d already "
   1868                                        "used for port %d\n"),
   1869                                         vlan_id, port));
   1870         return BCM_E_EXISTS;
   1871     }
   1872 
   1873     /* If the MODPORT is set in the passed in 'system_gport' we will use the
   1874        (mod,port) which is a part of it, if it is valid. Else allocate one
   1875        from the configured CoE modules */
   1876 
   1877     /* If a valid gport is supplied use it, else allocate one */
   1878     if(BCM_GPORT_IS_MODPORT(config->subport_modport)) {
   1879         modid = BCM_GPORT_MODPORT_MODID_GET(config->subport_modport);
   1880         portid = BCM_GPORT_MODPORT_PORT_GET(config->subport_modport);
   1881         /* Check if the supplied CoE-(mod,port) is valid */
   1882         if(_bcm_stk_aux_modport_valid(unit, BCM_MODID_TYPE_COE,
   1883                                       modid, portid) != BCM_E_NONE) {
   1884             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   1885                       (BSL_META_U(unit,"ERROR: Supplied (mod,port) (%d,%d) "
   1886                                        "not valid\n"),
   1887                                         modid, portid));
   1888             return BCM_E_PARAM;
   1889         }
   1890 
   1891     } else {
   1892         rv = _bcm_coe_subport_allocate_modport(unit, &modid, &portid);
   1893         if(rv != BCM_E_NONE) {
   1894             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   1895                       (BSL_META_U(unit,"ERROR: Free CoE (mod,port) "
   1896                                        "not found\n")));
   1897             return rv;
   1898         }
   1899         /* Put together a CoE-MODPORT for subsequent use */
   1900         BCM_GPORT_MODPORT_SET(config->subport_modport, modid, portid);
   1901 
   1902     }
   1903 
   1904     /* Find a free entry in SUBPORT_TAG_SGPP_MAPm table */
   1905     mem = SUBPORT_COE_HW_SUBPORT_SUBTAG_SGPP_MEM(unit);
   1906     rv = _bcm_coe_subport_free_entry_find(unit, &subtag_index);
   1907     if (SOC_FAILURE(rv)) {
   1908         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   1909                       (BSL_META_U(unit,"ERROR: Free entry not found in "
   1910                                   " subtag to sgpp map table\n")));
   1911         return rv;
   1912     }
   1913 
   1914     if (soc_mem_is_cam(unit, mem)) {
   1915         subtag_hw_index = subtag_index;
   1916          /* Read entry and map VLAN ID (Subtag) to (mod,port) */
   1917         rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, subtag_hw_index,
   1918             &subtag_to_sgpp_entry);
   1919         if (BCM_FAILURE(rv)) {
   1920             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   1921                       (BSL_META_U(unit,"SUBPORT_TAG_SGPP_MAPm read "
   1922                                        "failed at index %d\n"),
   1923                                        subtag_index));
   1924             return rv;
   1925         }
   1926     /* Make sure the entry allocated is unused*/
   1927         if (soc_mem_field32_get(unit, mem, (uint32 *)&subtag_to_sgpp_entry, 
   1928                 SUBPORT_COE_HW_SUBPORT_SUBTAG_SGPP(unit)->valid)) {
   1929             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   1930                       (BSL_META_U(unit,"SUBPORT_TAG_SGPP_MAPm entry "
   1931                                        "at index %d is been used\n"),
   1932                                        subtag_index));
   1933             return BCM_E_FAIL;
   1934         }
   1935     }
   1936 
   1937     /* Set the TAG, Namespace, (MOD,PORT), VALID and related fields */
   1938     soc_mem_field32_set(unit, mem, (uint32 *)&subtag_to_sgpp_entry, 
   1939                         SUBPORT_COE_HW_SUBPORT_SUBTAG_SGPP(unit)->subport_tag,
   1940                         config->pkt_vlan);
   1941 
   1942     /* Assign the physical port to the namespace */
   1943     soc_mem_field32_set(unit, mem, (uint32 *)&subtag_to_sgpp_entry, 
   1944         SUBPORT_COE_HW_SUBPORT_SUBTAG_SGPP(unit)->subport_tag_namespace,
   1945         _BCM_SUBPORT_COE_GROUP_PORT_GET(config->group));
   1946 
   1947     /* Assign the modId and port */
   1948 
   1949     if (SOC_IS_TRIDENT3X(unit)) {
   1950        /* In Trident3 chip,src port is SGPP(7,0), src modid is SGPP(15,8) */
   1951         soc_mem_field32_set(unit, mem, (uint32 *)&subtag_to_sgpp_entry,
   1952                         SUBPORT_COE_HW_SUBPORT_SUBTAG_SGPP(unit)->src_port, 
   1953                         ((modid << 0x8) | portid));
   1954     } else {
   1955         soc_mem_field32_set(unit, mem, (uint32 *)&subtag_to_sgpp_entry,
   1956                         SUBPORT_COE_HW_SUBPORT_SUBTAG_SGPP(unit)->src_modid, 
   1957                         modid);
   1958 
   1959         soc_mem_field32_set(unit, mem, (uint32 *)&subtag_to_sgpp_entry, 
   1960                         SUBPORT_COE_HW_SUBPORT_SUBTAG_SGPP(unit)->src_port, 
   1961                         portid);
   1962     }
   1963 
   1964     /* Set the 'valid' field */
   1965     soc_mem_field32_set(unit, mem, (uint32 *)&subtag_to_sgpp_entry,
   1966                         SUBPORT_COE_HW_SUBPORT_SUBTAG_SGPP(unit)->valid,
   1967                         1);
   1968 
   1969     /* Setup the masks */
   1970     if (SOC_MEM_FIELD_VALID(unit, mem,
   1971                   SUBPORT_COE_HW_SUBPORT_SUBTAG_SGPP(unit)->subport_tag_mask)) {
   1972         soc_mem_field32_set(unit, mem, (uint32 *)&subtag_to_sgpp_entry,
   1973                     SUBPORT_COE_HW_SUBPORT_SUBTAG_SGPP(unit)->subport_tag_mask,
   1974                     0xFFF);
   1975         soc_mem_field32_set(unit, mem, (uint32 *)&subtag_to_sgpp_entry,
   1976           SUBPORT_COE_HW_SUBPORT_SUBTAG_SGPP(unit)->subport_tag_namespace_mask,
   1977                       0x7F);
   1978     }
   1979 
   1980     /* Set PHB for the subport */
   1981     if (config->prop_flags & BCM_SUBPORT_PROPERTY_PHB) {
   1982         soc_mem_field32_set(unit, mem, (uint32 *)&subtag_to_sgpp_entry,
   1983             SUBPORT_COE_HW_SUBPORT_SUBTAG_SGPP(unit)->phb_enable, 1);
   1984         soc_mem_field32_set(unit, mem, (uint32 *)&subtag_to_sgpp_entry,
   1985             SUBPORT_COE_HW_SUBPORT_SUBTAG_SGPP(unit)->int_pri,
   1986                             config->int_pri);
   1987         soc_mem_field32_set(unit, mem, (uint32 *)&subtag_to_sgpp_entry,
   1988             SUBPORT_COE_HW_SUBPORT_SUBTAG_SGPP(unit)->cng,
   1989                            _BCM_COLOR_ENCODING(unit, config->color));
   1990         phb_val = 1;
   1991     }
   1992 
   1993     /* Write the entry to HW */
   1994     if (soc_mem_is_hashed(unit, mem)) {
   1995         rv = soc_mem_insert(unit, mem, MEM_BLOCK_ALL, &subtag_to_sgpp_entry);
   1996         if (SOC_FAILURE(rv) && rv != SOC_E_EXISTS) {
   1997             return rv;
   1998         }
   1999     } else {
   2000         if (subtag_hw_index >= 0) {
   2001             rv = soc_mem_write(unit, mem, MEM_BLOCK_ANY, subtag_hw_index,
   2002                            &subtag_to_sgpp_entry);
   2003     /* Bail on error */
   2004             if (SOC_FAILURE(rv)) {
   2005                 LOG_ERROR(BSL_LS_BCM_SUBPORT,
   2006                          (BSL_META_U(unit,"ERROR: (VLAN id %d, port %d) "
   2007                                        "to subtag_index %d "
   2008                                        "map failed.\n"),
   2009                                        vlan_id, port, subtag_index));
   2010                 return rv;
   2011             }
   2012         }
   2013     }
   2014 
   2015     /* Map Subtag to Physical port mapping using MODPORT_MAP_SUBPORTm.
   2016      * Note: subtag_index should be released below if failed.
   2017      */
   2018 
   2019     /* Compute the (mod,port) index */
   2020     rv = _bcm_esw_src_mod_port_table_index_get(unit, modid,
   2021                                                portid, &mod_port_index);
   2022     BCM_FAILURE_CLEANUP(rv, cleanup);
   2023 
   2024     /* Read the entry at the index and update needed fields */
   2025     mem = SUBPORT_COE_HW_MODPORT_MAP_SUBPORT_MEM(unit);
   2026     rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, mod_port_index,
   2027             &sgpp_to_port_entry);
   2028     BCM_FAILURE_CLEANUP(rv, cleanup);
   2029 
   2030     /* Set the physical port as the destination */
   2031     soc_mem_field32_set(unit, mem, (uint32 *)&sgpp_to_port_entry,
   2032         SUBPORT_COE_HW_MODPORT_MAP_SUBPORT(unit)->dest, port); 
   2033     /* Set the isTrunk as 0, we change if trunking is added */
   2034     soc_mem_field32_set(unit, mem, (uint32 *)&sgpp_to_port_entry,
   2035         SUBPORT_COE_HW_MODPORT_MAP_SUBPORT(unit)->is_trunk, 0);
   2036     /* Set 1 'enable' the entry  */
   2037     soc_mem_field32_set(unit, mem, (uint32 *)&sgpp_to_port_entry,
   2038         SUBPORT_COE_HW_MODPORT_MAP_SUBPORT(unit)->enable, 1);
   2039 
   2040     /* Write the entry to HW */
   2041     rv = soc_mem_write(unit, mem, MEM_BLOCK_ANY, mod_port_index,
   2042             &sgpp_to_port_entry);
   2043     BCM_FAILURE_CLEANUP(rv, cleanup);
   2044 
   2045     /* Update the ports SOURCE_TRUNK_MAP entry with a default
   2046        LPORT porperty  */
   2047     rv = _bcm_coe_subtag_subport_default_lport_entry_set(unit, port, 
   2048                                                          mod_port_index);
   2049     BCM_FAILURE_CLEANUP(rv, cleanup);
   2050 
   2051     /* With the index also update the EGR_GPP_ATTRIBUTES, with the subtag
   2052      * to be used on egress.
   2053      * Note: lport profile should be released below if failed.
   2054      */
   2055     rv = soc_mem_field32_modify(unit, EGR_GPP_ATTRIBUTESm,
   2056                                 mod_port_index,
   2057                                 SUBPORT_TAGf, vlan_id);
   2058 
   2059     /* Bail on error */
   2060     if (SOC_FAILURE(rv)) {
   2061         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   2062                       (BSL_META_U(unit,"ERROR: (mod,port) (%d,%d) "
   2063                                        "to physical port %d "
   2064                                        "map failed.\n"), 
   2065                                        modid, portid, port));
   2066         BCM_FAILURE_CLEANUP(rv, cleanup_lport);
   2067     }
   2068 
   2069     /* We need to reserve a egress-object for this subport */
   2070 
   2071     /* Allocate a next hop index */
   2072 #if defined(INCLUDE_L3)
   2073     bcm_l3_egress_t_init(&nh_info);
   2074 
   2075     rv = bcm_xgs3_nh_add(unit, _BCM_L3_SHR_MATCH_DISABLE |
   2076                          _BCM_L3_SHR_WRITE_DISABLE, &nh_info, &nh_index);
   2077 
   2078     if (SOC_FAILURE(rv)) {
   2079         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   2080                       (BSL_META_U(unit,"ERROR: Next hop allocation failed. "
   2081                                   "Coe (mod,port): (%d,%d), physical port %d"), 
   2082                                    modid, portid, port));
   2083         BCM_FAILURE_CLEANUP(rv, cleanup_lport);
   2084     }
   2085 
   2086     sal_memset(&egr_nh, 0, sizeof(egr_l3_next_hop_entry_t));
   2087 
   2088     /* SD-tag entry type */
   2089     if (SOC_IS_TRIDENT3X(unit)) {
   2090         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   2091             DATA_TYPEf, 2);
   2092     } else {
   2093         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   2094             ENTRY_TYPEf, 2);
   2095     }
   2096 
   2097     /* Setup the mod, port associated with the NH entry */
   2098     soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   2099             SD_TAG__HG_MC_DST_MODIDf, modid);
   2100     soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   2101             SD_TAG__HG_MC_DST_PORT_NUMf, portid);
   2102 
   2103     /* Write EGR_L3_NEXT_HOP entry */
   2104     rv = soc_mem_write(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ALL, 
   2105                        nh_index, &egr_nh);
   2106     if (SOC_FAILURE(rv)) {
   2107         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   2108                       (BSL_META_U(unit,"ERROR: Next hop update failed. "
   2109                                         "Coe (mod,port): (%d,%d), "
   2110                                         "physical port %d"), 
   2111                                         modid, portid, port));
   2112         BCM_FAILURE_CLEANUP(rv, cleanup_nh);
   2113     }
   2114 
   2115     /* Adjust the offset and assign the nh_index */
   2116     _bcm_subtag_subport_port_info[unit][subtag_index].nh_index = 
   2117         BCM_XGS3_DVP_EGRESS_IDX_MIN(unit) + nh_index;
   2118 #endif
   2119 
   2120     /* Update software book keeping.
   2121      * Note: subtag_index, nh_index and software book keeping
   2122      *       should be released below if failed.
   2123      */
   2124 
   2125 #ifdef BCM_TRIDENT3_SUPPORT
   2126     if (soc_mem_is_hashed(unit, SUBPORT_COE_HW_SUBPORT_SUBTAG_SGPP_MEM(unit))) {
   2127        /* Search the hash table for hw index */
   2128         sal_memset(subtag_to_sgpp_key, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32));
   2129         soc_SUBPORT_ID_TO_SGPP_MAPm_field32_set(unit, &subtag_to_sgpp_key,
   2130                                                 BASE_VALIDf, 1);
   2131         soc_SUBPORT_ID_TO_SGPP_MAPm_field32_set(unit, &subtag_to_sgpp_key,
   2132                            SUBPORT_ID_NAMESPACEf,
   2133                           _BCM_SUBPORT_COE_GROUP_PORT_GET(config->group));
   2134         soc_SUBPORT_ID_TO_SGPP_MAPm_field32_set(unit, &subtag_to_sgpp_key,
   2135                            SUBPORT_IDf,
   2136                           config->pkt_vlan);
   2137         rv = (soc_mem_search(unit, SUBPORT_COE_HW_SUBPORT_SUBTAG_SGPP_MEM(unit),
   2138                 MEM_BLOCK_ANY,
   2139                 &subtag_hw_index, &subtag_to_sgpp_key, &subtag_to_sgpp_entry, 0));
   2140         BCM_FAILURE_CLEANUP(rv, cleanup_nh);
   2141     }
   2142 #endif
   2143     /* Update bitmap to indicate the subtag/vlan_id is now in use,
   2144        for this port */
   2145     _BCM_COE_SUBTAG_VLAN_ID_USED_SET(unit, port, vlan_id);
   2146 
   2147     /* Encode our outgoing parameter as GPORT_SUBPORT type and
   2148        fill in the associated (mod,port) */
   2149     _BCM_SUBPORT_COE_PORT_ID_SET(*gport, modid, portid);
   2150     
   2151     /* Set the bit on the outgoing param indicating this is subtag type */
   2152     _BCM_SUBPORT_COE_PORT_TYPE_SET(*gport, _BCM_SUBPORT_COE_TYPE_SUBTAG);
   2153 
   2154     /* Save the related port info indexed by the subtag_index */
   2155     _BCM_SUBPORT_COE_SUBTAG_PORT_INFO_SET(unit, subtag_index, subtag_hw_index, 
   2156         config->group, config->pkt_vlan, *gport, config->subport_modport,
   2157         phb_val, config->int_pri, config->color, TRUE, mod_port_index);
   2158 
   2159     /* Increment number of subports on this group */
   2160     *(_bcm_subport_group_subport_port_count[unit] + sp_group_idx) += 1;
   2161 
   2162     rv = _bcm_coe_subtag_subport_default_egr_lport_entry_set(unit, *gport);
   2163     BCM_FAILURE_CLEANUP(rv, cleanup_nh);
   2164 
   2165 #ifdef BCM_WARM_BOOT_SUPPORT
   2166     SOC_CONTROL_LOCK(unit);
   2167     SOC_CONTROL(unit)->scache_dirty = 1;
   2168     SOC_CONTROL_UNLOCK(unit);
   2169 #endif
   2170     return rv;
   2171 
   2172     /* Free/invalidate the resources that have been allocated.*/
   2173 cleanup_nh:
   2174 #if defined(INCLUDE_L3)
   2175     bcm_xgs3_nh_del(unit, 0, nh_index);
   2176 #endif
   2177 
   2178     _BCM_COE_SUBTAG_VLAN_ID_USED_CLR(unit, port, vlan_id);
   2179 
   2180     _bcm_subtag_subport_port_info[unit][subtag_index].nh_index = -1;
   2181     *(_bcm_subport_group_subport_port_count[unit] + sp_group_idx) -= 1;
   2182 
   2183     _BCM_SUBPORT_COE_SUBTAG_PORT_INFO_SET(unit, subtag_index, subtag_hw_index,
   2184                                           BCM_GPORT_INVALID, 
   2185                                           BCM_VLAN_INVALID, 
   2186                                           -1, -1, -1, -1, -1, FALSE, -1);
   2187 
   2188 cleanup_lport:
   2189     _bcm_coe_subtag_subport_lport_entry_delete(unit, mod_port_index);
   2190 
   2191 cleanup:
   2192     /* Free/invalidate the SUBPORT_TAG_SGPP_MAP table entry */
   2193     /* coverity[check_return : FALSE] */
   2194     soc_mem_field32_modify(unit, SUBPORT_COE_HW_SUBPORT_SUBTAG_SGPP_MEM(unit),
   2195                            subtag_hw_index, VALIDf, 0);
   2196     return rv;
   2197 }
   2198 
   2199 
   2200 /*
   2201  * Function:
   2202  *      bcmi_xgs5_subport_coe_port_add
   2203  * Purpose:
   2204  *      Add a subport to a subport group
   2205  * Parameters:
   2206  *      unit   - (IN) Device Number
   2207  *      config - (IN) Subport config information
   2208  *      port   - (OUT) Subport_port GPORT (generic port) identifier
   2209  * Returns:
   2210  *      BCM_E_XXX
   2211  */
   2212 
   2213 int bcmi_xgs5_subport_coe_port_add(int unit, bcm_subport_config_t *config,
   2214                                    bcm_gport_t *port)
   2215 {
   2216     int rv = BCM_E_NONE;
   2217     uint16 group_id;
   2218     soc_info_t *si = &SOC_INFO(unit);
   2219 
   2220     _BCM_SUBPORT_COE_CHECK_INIT(unit);
   2221 
   2222     if (!BCM_GPORT_IS_SUBPORT_GROUP(config->group)) {
   2223         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   2224                       (BSL_META_U(unit,"ERROR: config->group 0x%x is not "
   2225                                        "subport group gport\n"),
   2226                                         config->group));
   2227         return BCM_E_PARAM;
   2228     }
   2229 
   2230     group_id = _BCM_SUBPORT_COE_GROUP_ID_GET(config->group);
   2231     if(!_BCM_SUBPORT_COE_GROUP_USED_GET(unit, group_id)) {
   2232         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   2233                       (BSL_META_U(unit,"ERROR:config->group 0x%x "
   2234                                        "is not found\n"), config->group));
   2235         return BCM_E_NOT_FOUND;
   2236     }
   2237 
   2238     if (_bcm_subport_coe_port_count[unit] == si->max_subport_coe_ports) {
   2239         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   2240                       (BSL_META_U(unit,"ERROR:All %d subport's in use\n"),
   2241                                   si->max_subport_coe_ports));
   2242         return BCM_E_FULL;
   2243     }
   2244 
   2245     _BCM_SUBPORT_COE_LOCK(unit);
   2246 
   2247     if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) &&
   2248         _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_GROUP(config->group)) {
   2249             if (BCM_PBMP_IS_NULL(si->subtag_pbm)) {
   2250                 LOG_ERROR(BSL_LS_BCM_SUBPORT,
   2251                       (BSL_META_U(unit,"ERROR: SubTag ports not "
   2252                                        "configured\n")));
   2253                 _BCM_SUBPORT_COE_UNLOCK(unit);
   2254                 return BCM_E_PARAM;
   2255             }
   2256             rv = _bcm_coe_subtag_subport_port_add(unit, config, port);
   2257     }
   2258 
   2259     if (SOC_FAILURE(rv)) {
   2260         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   2261                       (BSL_META_U(unit,"ERROR: Subport port add failed. "
   2262                                        "rv = %d(%s)\n"),
   2263                                         rv, soc_errmsg(rv)));
   2264         _BCM_SUBPORT_COE_UNLOCK(unit);
   2265         return rv;
   2266     }
   2267 
   2268     _BCM_SUBPORT_COE_UNLOCK(unit);
   2269 
   2270 #ifdef BCM_WARM_BOOT_SUPPORT
   2271     SOC_CONTROL_LOCK(unit);
   2272     SOC_CONTROL(unit)->scache_dirty = 1;
   2273     SOC_CONTROL_UNLOCK(unit);
   2274 #endif
   2275 
   2276     return rv;
   2277 }
   2278 
   2279 int bcmi_xgs5_subport_coe_port_traverse(int unit,
   2280                                         bcm_subport_port_traverse_cb cb,
   2281                                         void *user_data)
   2282 {
   2283     int i = 0, rv;
   2284     bcm_subport_config_t config;
   2285     soc_info_t *si = &SOC_INFO(unit);
   2286 
   2287     if(_bcm_subtag_subport_port_info[unit] == NULL) {
   2288         return BCM_E_NONE;
   2289     }
   2290 
   2291     for (i=0; i < si->max_subport_coe_ports; i++) {
   2292         if(_bcm_subtag_subport_port_info[unit][i].valid) {
   2293 
   2294             bcm_subport_config_t_init(&config);
   2295 
   2296             rv = _bcm_coe_subtag_subport_port_get(unit, 
   2297                      _bcm_subtag_subport_port_info[unit][i].subport_port, 
   2298                     &config);
   2299 
   2300             if (BCM_FAILURE(rv)) {
   2301                 LOG_ERROR(BSL_LS_BCM_SUBPORT,
   2302                       (BSL_META_U(unit,"ERROR: subport port traverse failed \n"
   2303                                   "to get SubTag subport id %d index: %d\n"), 
   2304                      _bcm_subtag_subport_port_info[unit][i].subport_port, i));
   2305                 return rv;
   2306             }
   2307 
   2308             rv = cb(unit, 
   2309                     _bcm_subtag_subport_port_info[unit][i].subport_port, 
   2310                     &config, 
   2311                     user_data);
   2312 
   2313             COMPILER_REFERENCE(rv);
   2314 
   2315 #ifdef BCM_CB_ABORT_ON_ERR
   2316             if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) {
   2317                 LOG_ERROR(BSL_LS_BCM_SUBPORT,
   2318                       (BSL_META_U(unit,"ERROR: subport port traverse failed \n"
   2319                                   "to callback for subport port "
   2320                                   "(subport_port id %d)\n"),
   2321                         _bcm_subtag_subport_port_info[unit][i].subport_port));
   2322                 return rv;
   2323             }
   2324 #endif
   2325         }
   2326     }
   2327 
   2328     return BCM_E_NONE;
   2329 }
   2330 
   2331 /*
   2332  * Function:
   2333  *      _bcm_coe_subtag_subport_cleanup
   2334  * Purpose:
   2335  *      Delate all valid subport ports and all valid subport groups.
   2336         Also clean up software resources.
   2337  * Parameters:
   2338  *      unit      - Device Number
   2339  * Returns:
   2340  *      BCM_E_XXX
   2341  */
   2342 int _bcm_coe_subtag_subport_cleanup(int unit)
   2343 {
   2344     int group_id = 0, rv = BCM_E_NONE, i = 0;
   2345     bcm_port_t port;
   2346     bcm_gport_t subport_group;
   2347     soc_mem_t mem;
   2348     soc_info_t *si = &SOC_INFO(unit);
   2349 
   2350     _BCM_SUBPORT_COE_CHECK_INIT(unit);
   2351 
   2352    /* Delete all SubTag subport ports */
   2353     for (i=0; i < si->max_subport_coe_ports; i++) {
   2354 
   2355         if (!_BCM_SUBPORT_COE_SUBTAG_PORT_INFO_VALID_GET(unit, i)) {
   2356             continue;
   2357         }
   2358 
   2359         rv = _bcm_coe_subtag_subport_port_delete(unit, 
   2360                   _bcm_subtag_subport_port_info[unit][i].subport_port);
   2361         if (SOC_FAILURE(rv)) {
   2362             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   2363                       (BSL_META_U(unit,"ERROR: SubTag subport port "
   2364                                        "delete failed (subport id %d)\n"),
   2365                          _bcm_subtag_subport_port_info[unit][i].subport_port));
   2366             return rv;
   2367         }
   2368 
   2369         subport_group =
   2370             _BCM_SUBPORT_COE_SUBTAG_PORT_INFO_GROUP_GET(unit, i);
   2371 
   2372         group_id = _BCM_SUBPORT_COE_GROUP_ID_GET(subport_group);
   2373 
   2374         if (*(_bcm_subport_group_subport_port_count[unit] + group_id) == 0) {
   2375              /* delete the subport group */
   2376             _bcm_subport_group_count[unit]--;
   2377             _BCM_SUBPORT_COE_GROUP_USED_CLR(unit, group_id);
   2378             _bcm_subtag_subport_group_count[unit]--;
   2379             _BCM_SUBPORT_COE_SUBTAG_GROUP_USED_CLR(unit, group_id);
   2380         }
   2381     }
   2382 
   2383     /* Unset the 'Cascaded' type on port */
   2384     BCM_PBMP_ITER(SOC_INFO(unit).subtag_pbm, port) {
   2385         mem = SUBPORT_COE_HW_ING_PORT_MEM(unit);
   2386         if (SOC_MEM_FIELD_VALID(unit, mem, 
   2387                                 SUBPORT_COE_HW_ING_PORT(unit)->port_type)) {
   2388             BCM_IF_ERROR_RETURN(soc_mem_field32_modify
   2389                 (unit, mem, 
   2390                  port, 
   2391                  SUBPORT_COE_HW_ING_PORT(unit)->port_type, 
   2392                             _BCM_COE_PORT_TYPE_ETHERNET));
   2393         }
   2394 
   2395         mem = SUBPORT_COE_HW_EGR_PORT_MEM(unit);
   2396         if (SOC_MEM_FIELD_VALID(unit, mem, 
   2397                                 SUBPORT_COE_HW_EGR_PORT(unit)->port_type)) {
   2398             BCM_IF_ERROR_RETURN(soc_mem_field32_modify(unit, mem, port, 
   2399                                     SUBPORT_COE_HW_EGR_PORT(unit)->port_type,
   2400                                     _BCM_COE_PORT_TYPE_ETHERNET));
   2401         }
   2402     }
   2403 
   2404     return BCM_E_NONE;
   2405 }
   2406 
   2407 /*
   2408  * Function:
   2409  *      bcmi_xgs5_subport_coe_cleanup
   2410  * Purpose:
   2411  *      Delate all valid subport ports and all valid subport groups.
   2412         Also clean up software resources.
   2413  * Parameters:
   2414  *      unit      - Device Number
   2415  * Returns:
   2416  *      BCM_E_XXX
   2417  */
   2418 int bcmi_xgs5_subport_coe_cleanup(int unit)
   2419 {
   2420 
   2421     int rv = BCM_E_NONE;
   2422     soc_info_t *si = &SOC_INFO(unit);
   2423 
   2424     _BCM_SUBPORT_COE_CHECK_INIT(unit);
   2425 
   2426     if (0 == SOC_HW_ACCESS_DISABLE(unit)) {
   2427         if (soc_feature(unit, soc_feature_hgproxy_subtag_coe)) {
   2428             if (BCM_PBMP_NOT_NULL(si->subtag_allowed_pbm)) {
   2429                 rv = _bcm_coe_subtag_subport_cleanup(unit);
   2430                 if (SOC_FAILURE(rv)) {
   2431                     LOG_ERROR(BSL_LS_BCM_SUBPORT,
   2432                           (BSL_META_U(unit,"ERROR: SubTag cleanup failed\n")));
   2433                     return rv;
   2434                 }
   2435             }
   2436         }
   2437     }
   2438 
   2439     bcmi_xgs5_subport_free_resource(unit);
   2440 
   2441     return BCM_E_NONE;
   2442 }
   2443 
   2444 /*
   2445  * Function:
   2446  *      bcmi_xgs5_subport_egr_subtag_dot1p_map_add
   2447  * Purpose:
   2448  *      Map the egress SubTag CoE packet's PHB (internal priority and color) 
   2449  *      to subport tag's 'Priority' and 'Color'.
   2450  * Parameters:
   2451  *      unit      - (IN) Device Number
   2452  *      map       - (IN) qos map
   2453  * Returns:
   2454  *      BCM_E_XXX
   2455  */
   2456 
   2457 int bcmi_xgs5_subport_egr_subtag_dot1p_map_add(int unit,
   2458                                                bcm_qos_map_t *map)
   2459 {
   2460     soc_mem_t mem;
   2461     int index;
   2462     uint32              tab_ent[SOC_MAX_MEM_FIELD_WORDS]; /* HW entry buffer. */
   2463 
   2464     mem = SUBPORT_COE_HW_EGR_SUBPORT_TAG_DOT1P_MEM(unit);
   2465 
   2466     if (!soc_feature(unit, soc_feature_hgproxy_subtag_coe)) {
   2467         return BCM_E_UNAVAIL;
   2468     }
   2469 
   2470     if (map->etag_pcp > 7 ||
   2471         map->etag_de > 1 ||
   2472         map->int_pri < 0 || map->int_pri > 15 ||
   2473         ((map->color != bcmColorGreen) && 
   2474         (map->color != bcmColorYellow) && 
   2475         (map->color != bcmColorRed))) {
   2476         return BCM_E_PARAM;
   2477     }
   2478 
   2479     /* EGR_SUBPORT_TAG_DOT1P_MAPm table is indexed with
   2480      * internal priority - 4 bits [5:2] and color - 2 bits[1:0]
   2481      */
   2482     index = ((map->int_pri << 2) | map->color) & soc_mem_index_max(unit, mem);
   2483 
   2484     sal_memset(tab_ent, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32));
   2485     soc_mem_field32_set(unit, mem, tab_ent,
   2486         SUBPORT_COE_HW_EGR_SUBPORT_TAG_DOT1P(unit)->subport_tag_priority,
   2487         map->etag_pcp);
   2488     if (SOC_IS_TRIDENT3X(unit)) {
   2489         /* TD3 only supports 4-byte SUBPORT-TAG */
   2490         soc_mem_field32_set(unit, mem, tab_ent,
   2491             SUBPORT_COE_HW_EGR_SUBPORT_TAG_DOT1P(unit)->subport_tag_cfi,
   2492             map->etag_de);
   2493     } else {
   2494         soc_mem_field32_set(unit, mem, tab_ent,
   2495            SUBPORT_COE_HW_EGR_SUBPORT_TAG_DOT1P(unit)->subport_tag_color,
   2496             map->color);
   2497         soc_mem_field32_set(unit, mem, tab_ent,
   2498             SUBPORT_COE_HW_EGR_SUBPORT_TAG_DOT1P(unit)->subport_tag_cfi,
   2499             map->etag_de);
   2500     }
   2501     SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, index,
   2502                        tab_ent));
   2503     return BCM_E_NONE;
   2504 }
   2505 
   2506 /*
   2507  * Function:
   2508  *      bcmi_xgs5_subport_egr_subtag_dot1p_map_delete
   2509  * Purpose:
   2510  *      Delete the map the egress SubTag CoE packet's
   2511  *      PHB (internal priority and color) 
   2512  *      to subport tag's 'Priority' and 'Color'.
   2513  * Parameters:
   2514  *      unit      - (IN) Device Number
   2515  *      map       - (IN) qos map
   2516  * Returns:
   2517  *      BCM_E_XXX
   2518  */
   2519 int
   2520 bcmi_xgs5_subport_egr_subtag_dot1p_map_delete(int unit,
   2521                                             bcm_qos_map_t *map)
   2522 {
   2523     soc_mem_t mem;
   2524     int index;
   2525     uint32              tab_ent[SOC_MAX_MEM_FIELD_WORDS]; /* HW entry buffer. */
   2526 
   2527     mem = SUBPORT_COE_HW_EGR_SUBPORT_TAG_DOT1P_MEM(unit);
   2528 
   2529     if (!soc_feature(unit, soc_feature_hgproxy_subtag_coe)) {
   2530         return BCM_E_UNAVAIL;
   2531     }
   2532 
   2533     if (map->etag_pcp > 7 ||
   2534         map->etag_de > 1 ||
   2535         map->int_pri < 0 || map->int_pri > 15 ||
   2536         ((map->color != bcmColorGreen) && 
   2537         (map->color != bcmColorYellow) && 
   2538         (map->color != bcmColorRed))) {
   2539         return BCM_E_PARAM;
   2540     }
   2541 
   2542     /* EGR_SUBPORT_TAG_DOT1P_MAPm table is indexed with
   2543      * internal priority - 4 bits [5:2] and color - 2 bits[1:0]
   2544      */
   2545     index = ((map->int_pri << 2) | map->color) & soc_mem_index_max(unit, mem);
   2546 
   2547     sal_memset(tab_ent, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32));
   2548     soc_mem_field32_set(unit, mem, tab_ent,
   2549         SUBPORT_COE_HW_EGR_SUBPORT_TAG_DOT1P(unit)->subport_tag_priority, 0);
   2550     soc_mem_field32_set(unit, mem, tab_ent,
   2551         SUBPORT_COE_HW_EGR_SUBPORT_TAG_DOT1P(unit)->subport_tag_cfi, 0);
   2552     /* Trident3 only support 4-byte SUBPORT-TAG */
   2553     if (!SOC_IS_TRIDENT3X(unit)) {
   2554         soc_mem_field32_set(unit, mem, tab_ent,
   2555         SUBPORT_COE_HW_EGR_SUBPORT_TAG_DOT1P(unit)->subport_tag_color, 0);
   2556     }
   2557     SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, index,
   2558                        tab_ent));
   2559     return BCM_E_NONE;
   2560 }
   2561 
   2562 /*
   2563  * Function:
   2564  *      bcmi_xgs5_subport_subtag_port_tpid_set
   2565  * Description:
   2566  *      Set the default Tag Protocol ID for a SubTag port.
   2567  * Parameters:
   2568  *      unit  - (IN) Device number
   2569  *      gport - (IN) SubTag group gport (Ignored)
   2570  *      tpid  - (IN) Tag Protocol ID
   2571  * Return Value:
   2572  *      BCM_E_XXX
   2573  */
   2574 
   2575 
   2576 
   2577 int 
   2578 bcmi_xgs5_subport_subtag_port_tpid_set(int unit,
   2579                                        bcm_gport_t gport,
   2580                                        uint16 tpid)
   2581 {
   2582     uint32      regval = 0;
   2583     soc_reg_t   reg;
   2584 
   2585     reg = SUBPORT_TAG_TPIDr;
   2586 
   2587     if (!(soc_reg_field_valid(unit, reg, TPIDf) || 
   2588           soc_reg_field_valid(unit, reg, ENABLEf))) {
   2589         return BCM_E_UNAVAIL;
   2590     }
   2591 
   2592     soc_reg_field_set(unit, reg, &regval, TPIDf, tpid);
   2593     soc_reg_field_set(unit, reg, &regval, ENABLEf, 1);
   2594 
   2595     SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, regval));
   2596 
   2597     reg = EGR_SUBPORT_TAG_TPIDr;
   2598     if (!(soc_reg_field_valid(unit, reg, TPID_8BYTE_TAGf) || 
   2599           soc_reg_field_valid(unit, reg, TPID_4BYTE_TAGf))) {
   2600         return BCM_E_UNAVAIL;
   2601     }
   2602 
   2603     soc_reg_field_set(unit, reg, &regval, TPID_8BYTE_TAGf, tpid);
   2604     soc_reg_field_set(unit, reg, &regval, TPID_4BYTE_TAGf, tpid);
   2605 
   2606     SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, regval));
   2607 
   2608     return BCM_E_NONE;
   2609 }
   2610 
   2611 /*
   2612  * Function:
   2613  *      bcmi_xgs5_subport_subtag_port_tpid_get
   2614  * Description:
   2615  *      Retrieve the default Tag Protocol ID for a SubTag port.
   2616  * Parameters:
   2617  *      unit  - (IN) Device number
   2618  *      gport - (IN)SubTag group gport (Ignored)
   2619  *      tpid  - (OUT) Tag Protocol ID
   2620  * Return Value:
   2621  *      BCM_E_XXX
   2622  */
   2623 
   2624 int
   2625 bcmi_xgs5_subport_subtag_port_tpid_get(int unit,
   2626                                        bcm_gport_t gport,
   2627                                        uint16 *tpid)
   2628 {
   2629     uint32      regval = 0;
   2630     soc_reg_t   reg;
   2631 
   2632     reg = SUBPORT_TAG_TPIDr;
   2633     SOC_IF_ERROR_RETURN(
   2634         soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &regval));
   2635 
   2636     if(soc_reg_field_get(unit, reg, regval, VALIDf)) {
   2637         *tpid = soc_reg_field_get(unit, reg, regval, TPIDf);
   2638         return BCM_E_NONE;
   2639     }
   2640 
   2641     return BCM_E_UNAVAIL;
   2642 }
   2643 
   2644 
   2645 /*
   2646  * Function:
   2647  *      bcmi_xgs5_subport_subtag_port_tpid_delete
   2648  * Description:
   2649  *      Delete allowed TPID for a SubTag port.
   2650  * Parameters:
   2651  *      unit  - (IN) Device number
   2652  *      gport - (IN) SubTag group gport (Ignored)
   2653  *      tpid  - (IN) Tag Protocol ID
   2654  * Return Value:
   2655  *      BCM_E_XXX
   2656  */
   2657 
   2658 int
   2659 bcmi_xgs5_subport_subtag_port_tpid_delete(int unit,
   2660                                           bcm_gport_t gport,
   2661                                           uint16 tpid)
   2662 {
   2663     uint32      regval = 0;
   2664     soc_reg_t   reg;
   2665 
   2666     reg = SUBPORT_TAG_TPIDr;
   2667     if (!(soc_reg_field_valid(unit, reg, TPIDf) || 
   2668           soc_reg_field_valid(unit, reg, ENABLEf))) {
   2669         return BCM_E_UNAVAIL;
   2670     }
   2671 
   2672     soc_reg_field_set(unit, reg, &regval, TPIDf, 0);
   2673     soc_reg_field_set(unit, reg, &regval, ENABLEf, 0);
   2674 
   2675     SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, regval));
   2676 
   2677     reg = EGR_SUBPORT_TAG_TPIDr;
   2678     if (!(soc_reg_field_valid(unit, reg, TPID_8BYTE_TAGf) || 
   2679           soc_reg_field_valid(unit, reg, TPID_4BYTE_TAGf))) {
   2680         return BCM_E_UNAVAIL;
   2681     }
   2682 
   2683     soc_reg_field_set(unit, reg, &regval, TPID_8BYTE_TAGf, 0);
   2684     soc_reg_field_set(unit, reg, &regval, TPID_4BYTE_TAGf, 0);
   2685 
   2686     SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, regval));
   2687 
   2688     return BCM_E_NONE;
   2689 }
   2690 
   2691 /*
   2692  * Function:
   2693  *      bcmi_xgs5_port_control_subtag_status_set
   2694  * Description:
   2695  *      Set the SubTag status for a given port.
   2696  * Parameters:
   2697  *      unit  - (IN) Device number
   2698  *      port  - (IN) port
   2699  *      value - (IN) Enable/Disable status
   2700  * Return Value:
   2701  *      BCM_E_XXX
   2702  * Note: The application need to delete all subport groups/ports, if any,
   2703  *       before disabling the SubTag CoE for given port.
   2704  */
   2705 
   2706 int bcmi_xgs5_port_control_subtag_status_set(int unit,
   2707                                              bcm_port_t port, int value)
   2708 {
   2709     int rv = BCM_E_NONE;
   2710     /* int  start = 0, end = 0; */
   2711     uint32 port_type;
   2712     soc_info_t *si = &SOC_INFO(unit);
   2713 
   2714     _BCM_SUBPORT_COE_CHECK_INIT(unit);
   2715 
   2716     if (!soc_feature(unit, soc_feature_hgproxy_subtag_coe)) {
   2717         return BCM_E_UNAVAIL;
   2718     }
   2719 
   2720     if (!BCM_PBMP_MEMBER(si->subtag_allowed_pbm, port)) {
   2721         return BCM_E_PORT;
   2722     }
   2723     _BCM_SUBPORT_COE_LOCK(unit);
   2724 
   2725     port_type = value ? _BCM_COE_PORT_TYPE_CASCADED :
   2726                         _BCM_COE_PORT_TYPE_ETHERNET;
   2727 
   2728     rv = _bcm_esw_port_tab_set(unit, port,
   2729            _BCM_CPU_TABS_NONE, PORT_TYPEf, port_type);
   2730 
   2731     if (BCM_FAILURE(rv)) {
   2732         _BCM_SUBPORT_COE_UNLOCK(unit);
   2733         return rv;
   2734     }
   2735     rv = _bcm_esw_egr_port_tab_set(unit, port,
   2736                   PORT_TYPEf, port_type);
   2737     if (BCM_FAILURE(rv)) {
   2738         _BCM_SUBPORT_COE_UNLOCK(unit);
   2739        return rv;
   2740     }
   2741 
   2742 
   2743     
   2744 
   2745     /* start = si->port_subport_base[port] - KT2_MIN_SUBPORT_INDEX;
   2746        end = start + si->port_num_subport[port] - 1;
   2747     */ 
   2748     if (value) {
   2749         BCM_PBMP_PORT_ADD(si->subtag_pbm, port);
   2750         BCM_PBMP_PORT_ADD(si->subtag.bitmap, port);
   2751 /****
   2752         SOC_IF_ERROR_RETURN
   2753             (soc_kt2_cosq_port_coe_linkphy_status_set(unit, port, 1));
   2754         SOC_IF_ERROR_RETURN
   2755             (soc_kt2_cosq_s1_range_set(unit, port, start, end, 0));
   2756         SOC_IF_ERROR_RETURN
   2757             (soc_kt2_cosq_repl_map_set(unit, port, start, end, 1));
   2758  */
   2759     } else {
   2760         if (BCM_PBMP_MEMBER(si->subtag_pbm, port)) {
   2761             BCM_PBMP_PORT_REMOVE(si->subtag_pbm, port);
   2762             BCM_PBMP_PORT_REMOVE(si->subtag.bitmap, port);
   2763 /****
   2764             SOC_IF_ERROR_RETURN
   2765                 (soc_kt2_cosq_port_coe_linkphy_status_set(unit, port, 0));
   2766             SOC_IF_ERROR_RETURN
   2767                 (soc_kt2_cosq_s1_range_set(unit, port, 0, 0, 0));
   2768             SOC_IF_ERROR_RETURN
   2769                 (soc_kt2_cosq_repl_map_set(unit, port, start, end, 0));
   2770  */ 
   2771         }
   2772     }
   2773     _BCM_SUBPORT_COE_UNLOCK(unit);
   2774     return rv;
   2775 }
   2776 /*
   2777  * Function:
   2778  *      bcmi_xgs5_port_control_subtag_status_get
   2779  * Description:
   2780  *      Get the SubTag status for a given port.
   2781  * Parameters:
   2782  *      unit  - (IN) Device number
   2783  *      port  - (IN) port
   2784  *      value - (OUT) Enable/Disable status
   2785  * Return Value:
   2786  *      BCM_E_XXX
   2787  */
   2788 
   2789 int bcmi_xgs5_port_control_subtag_status_get(int unit,
   2790                                              bcm_port_t port, 
   2791                                              int *value)
   2792 {
   2793     int rv = BCM_E_NONE;
   2794     soc_mem_t mem;
   2795     soc_info_t *si = &SOC_INFO(unit);
   2796     port_tab_entry_t port_tab_entry;
   2797 
   2798     _BCM_SUBPORT_COE_CHECK_INIT(unit);
   2799 
   2800     if (!soc_feature(unit, soc_feature_hgproxy_subtag_coe)) {
   2801         return BCM_E_UNAVAIL;
   2802     }
   2803     if (!BCM_PBMP_MEMBER(si->subtag_allowed_pbm, port)) {
   2804         return BCM_E_PORT;
   2805     }
   2806 
   2807     _BCM_SUBPORT_COE_LOCK(unit);
   2808 
   2809     *value = 0;
   2810     mem = SUBPORT_COE_HW_ING_PORT_MEM(unit);
   2811 
   2812     rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, port,
   2813             &port_tab_entry);
   2814     if (SOC_FAILURE(rv)) {
   2815         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   2816                       (BSL_META_U(unit,"ERROR:PORT_TABLEm read failed\n")));
   2817         _BCM_SUBPORT_COE_UNLOCK(unit);
   2818         return rv;
   2819     }
   2820     if ((soc_mem_field32_get(unit, mem, &port_tab_entry,
   2821             PORT_TYPEf) == _BCM_COE_PORT_TYPE_CASCADED)) {
   2822         *value = 1;
   2823     }
   2824 
   2825     _BCM_SUBPORT_COE_UNLOCK(unit);
   2826 
   2827     return rv;
   2828 }
   2829 
   2830 /*
   2831  * Function:
   2832  *      _bcmi_xgs5_subport_group_resolve
   2833  * Purpose:
   2834  *      Resolve physical port associated with the subtag subport group
   2835  */
   2836 
   2837 int
   2838 _bcmi_xgs5_subport_group_resolve(int unit,
   2839                                 bcm_gport_t subport_group_gport,
   2840                                 bcm_module_t *modid, bcm_port_t *port,
   2841                                 bcm_trunk_t *trunk_id, int *id)
   2842 
   2843 {
   2844     bcm_module_t my_modid;
   2845     uint16 group_id;
   2846 
   2847     _BCM_SUBPORT_COE_CHECK_INIT(unit);
   2848 
   2849     *modid = -1;
   2850     *port = -1;
   2851     *id = -1;
   2852     *trunk_id = BCM_TRUNK_INVALID;
   2853 
   2854     if (!BCM_GPORT_IS_SUBPORT_GROUP(subport_group_gport)) {
   2855         LOG_WARN(BSL_LS_BCM_SUBPORT,
   2856                  (BSL_META_U(unit,"gport 0x%x is not subport gport\n"),
   2857                              subport_group_gport));
   2858         return BCM_E_NONE;
   2859     }
   2860 
   2861     if ((soc_feature(unit, soc_feature_hgproxy_subtag_coe) &&
   2862         _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_GROUP(subport_group_gport))) {
   2863 
   2864         group_id = _BCM_SUBPORT_COE_GROUP_ID_GET(subport_group_gport);
   2865         if(!_BCM_SUBPORT_COE_GROUP_USED_GET(unit, group_id)) {
   2866             LOG_WARN(BSL_LS_BCM_SUBPORT,
   2867                      (BSL_META_U(unit,"subport gport 0x%x is not used\n"),
   2868                                  subport_group_gport));
   2869             return BCM_E_NONE;
   2870         }
   2871 
   2872         BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_modid));
   2873         *modid = my_modid;
   2874         *port = _BCM_SUBPORT_COE_GROUP_PORT_GET(subport_group_gport);
   2875     } else if (soc_feature(unit, soc_feature_subport_enhanced)) {
   2876 #if defined(BCM_TRIUMPH2_SUPPORT) && defined(INCLUDE_L3)
   2877         return _bcm_tr2_subport_group_resolve(unit, subport_group_gport,
   2878                                             modid, port, trunk_id,id);
   2879 #endif
   2880     } else if (soc_feature(unit, soc_feature_subport)) {
   2881 #if defined (BCM_TRX_SUPPORT) && defined(INCLUDE_L3)
   2882         return _bcm_tr_subport_group_resolve(unit, subport_group_gport,
   2883                                              modid, port, trunk_id, id);
   2884 #endif
   2885     }
   2886 
   2887     return BCM_E_NONE;
   2888 }
   2889 
   2890 
   2891 /*
   2892  * Function:
   2893  *      _bcmi_coe_subport_physical_port_get
   2894  * Purpose:
   2895  *      Given a subport-group/subport-port GPORT, return the physical port
   2896  */
   2897 int
   2898 _bcmi_coe_subport_physical_port_get(int unit, bcm_gport_t subport,
   2899                                     int *local_port)
   2900 {
   2901     int i = 0;
   2902     soc_info_t *si = &SOC_INFO(unit);
   2903 
   2904     if(_bcm_subtag_subport_port_info[unit] == NULL) {
   2905         return BCM_E_NOT_FOUND;
   2906     }
   2907 
   2908     if (BCM_GPORT_IS_SET(subport)) {
   2909         if (BCM_GPORT_IS_SUBPORT_PORT(subport)) {
   2910             if (_BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, subport)){
   2911 
   2912                 /* Find the entry corresponding to the subport */
   2913                 for (i = 0; i < si->max_subport_coe_ports; i++) {
   2914                     if((_bcm_subtag_subport_port_info[unit][i].valid) && 
   2915                        (_bcm_subtag_subport_port_info[unit][i].subport_port == 
   2916                          subport)) {
   2917                             /* Entry found, break */
   2918                             break;
   2919                         }
   2920                 }
   2921 
   2922                 /* If not found, return */
   2923                 if (i == si->max_subport_coe_ports) {
   2924                     return BCM_E_PORT;
   2925                 }
   2926 
   2927                 /* Get the physical port associated with the subport-group in
   2928                    question */
   2929 
   2930                 *local_port = _BCM_SUBPORT_COE_GROUP_PORT_GET(
   2931                               _bcm_subtag_subport_port_info[unit][i].group);
   2932             } else if (BCM_GPORT_IS_SUBPORT_GROUP(subport)) {
   2933                 *local_port = _BCM_SUBPORT_COE_GROUP_PORT_GET(subport);
   2934             }
   2935         }
   2936     }
   2937 
   2938     return BCM_E_NONE;
   2939 }
   2940 
   2941 /*
   2942  * Function:
   2943  *      _bcmi_coe_subport_mod_port_physical_port_get
   2944  * Purpose:
   2945  *      Given a coe-(mod,port), return the physical port
   2946  */
   2947 int
   2948 _bcmi_coe_subport_mod_port_physical_port_get(int unit, bcm_module_t modid, bcm_port_t portid,
   2949                                              int *local_port)
   2950 {
   2951     int subport_gport;
   2952 
   2953     /* Encode type and fill in the associated (mod,port) */
   2954     _BCM_SUBPORT_COE_PORT_ID_SET(subport_gport, modid, portid);
   2955     /* Set the bit on the outgoing param indicating this is subtag type */
   2956     _BCM_SUBPORT_COE_PORT_TYPE_SET(subport_gport, _BCM_SUBPORT_COE_TYPE_SUBTAG);
   2957 
   2958     return _bcmi_coe_subport_physical_port_get(unit, subport_gport, local_port);
   2959 }
   2960 
   2961 /*
   2962  * Function:
   2963  *      _bcm_xgs5_subport_port_resolve
   2964  * Purpose:
   2965  *      Resolve subport_port to related (mod,port) 
   2966  */
   2967 
   2968 int
   2969 _bcm_xgs5_subport_port_resolve(int unit,
   2970                                bcm_gport_t subport_port_gport,
   2971                                bcm_module_t *modid, bcm_port_t *port,
   2972                                bcm_trunk_t *trunk_id, int *id)
   2973 {
   2974 
   2975 #ifdef INCLUDE_L3
   2976     bcm_subport_config_t config;
   2977     int rv = BCM_E_NONE;
   2978 
   2979     _BCM_SUBPORT_COE_CHECK_INIT(unit);
   2980 
   2981     *modid = -1;
   2982     *port = -1;
   2983     *id = -1;
   2984     *trunk_id = BCM_TRUNK_INVALID;
   2985 
   2986     if (!BCM_GPORT_IS_SUBPORT_PORT(subport_port_gport)) {
   2987         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   2988                       (BSL_META_U(unit,"ERROR: gport 0x%x is not subport gport\n"),
   2989                                   subport_port_gport));
   2990         return BCM_E_PARAM;
   2991     }
   2992 
   2993     if ((soc_feature(unit, soc_feature_hgproxy_subtag_coe) &&
   2994         _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, subport_port_gport))) {
   2995 
   2996             bcm_subport_config_t_init(&config);
   2997             rv = _bcm_coe_subtag_subport_port_get(unit, subport_port_gport,
   2998                                                   &config);
   2999             if(rv == BCM_E_NONE) {
   3000                 *modid = _BCM_SUBPORT_COE_PORT_ID_MOD_GET(subport_port_gport);
   3001                 *port  = _BCM_SUBPORT_COE_PORT_ID_PORT_GET(subport_port_gport);
   3002             }
   3003     } else if (soc_feature(unit, soc_feature_subport_enhanced)) {
   3004 #if defined(BCM_TRIUMPH2_SUPPORT) && defined(INCLUDE_L3)
   3005         return _bcm_tr2_subport_port_resolve(unit,subport_port_gport,
   3006                                              modid, port, trunk_id, id);
   3007 #endif /* defined(BCM_TRIUMPH2_SUPPORT) && defined(INCLUDE_L3) */
   3008     } else if (soc_feature(unit, soc_feature_subport)) {
   3009 #if defined (BCM_TRX_SUPPORT) && defined(INCLUDE_L3)
   3010         return _bcm_tr_subport_port_resolve(unit, subport_port_gport,
   3011                                             modid, port, trunk_id, id);
   3012 #endif
   3013     }
   3014 
   3015     return rv;
   3016 
   3017 #else
   3018     return BCM_E_UNAVAIL;
   3019 #endif
   3020 }
   3021 
   3022 
   3023 /*
   3024  * Function:
   3025  *      bcmi_xgs5_subport_gport_modport_get
   3026  * Purpose:
   3027  *      Given a subport-gport, return teh corresponding mod-port 
   3028  * Parameters:
   3029  *      unit   - (IN) Device Number
   3030  *      subport_gport  - (IN) GPORT (generic port) identifier
   3031  *      module  - (OUT) Module associated with the subport
   3032  *      port  - (OUT) Port associated with the subport  
   3033  * Returns:
   3034  *      BCM_E_XXX
   3035  */
   3036 
   3037 int bcmi_xgs5_subport_gport_modport_get(int unit,
   3038             bcm_gport_t subport_gport, bcm_module_t *module, bcm_port_t *port)
   3039 {
   3040     bcm_trunk_t   trunk_id;
   3041     int           id = 0;
   3042 
   3043     BCM_IF_ERROR_RETURN(_bcm_xgs5_subport_port_resolve(unit, subport_gport,
   3044                             module, port, &trunk_id, &id));
   3045 
   3046     return BCM_E_NONE;
   3047 }
   3048 
   3049 /*
   3050  * Function:
   3051  *      _bcm_xgs5_subport_gport_validate
   3052  * Description:
   3053  *      Helper funtion to validate port/gport parameter 
   3054  * Parameters:
   3055  *      unit  - (IN) BCM device number
   3056  *      port_in  - (IN) Port / Gport to validate
   3057  *      port_out - (OUT) Port number if valid. 
   3058  * Return Value:
   3059  *      BCM_E_NONE - Port OK 
   3060  *      BCM_E_PORT - Port Invalid
   3061  */
   3062 int
   3063 _bcm_xgs5_subport_gport_validate(int unit, bcm_port_t port_in,
   3064                                        bcm_port_t *port_out)
   3065 {
   3066     if (BCM_GPORT_IS_SET(port_in)) {
   3067         if (BCM_GPORT_IS_SUBPORT_PORT(port_in) &&
   3068             _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port_in)) {
   3069                 return bcm_esw_port_local_get(unit, port_in, port_out);
   3070         } else {
   3071             return BCM_E_PORT; 
   3072         }
   3073     } else if (SOC_PORT_VALID(unit, port_in)) { 
   3074         *port_out = port_in;
   3075     } else {
   3076         return BCM_E_PORT; 
   3077     }
   3078 
   3079     return BCM_E_NONE;
   3080 
   3081 }
   3082 
   3083 /*
   3084 * Function:
   3085 *      _bcmi_coe_subport_tcam_idx_get
   3086 * Purpose:
   3087 *      Given a subport-port GPORT, return its TCAM h/w idx
   3088 */
   3089 int
   3090 _bcmi_coe_subport_tcam_idx_get(int unit, bcm_gport_t subport,
   3091                                     int *hw_idx)
   3092 {
   3093     int i = 0;
   3094     soc_info_t *si = &SOC_INFO(unit);
   3095 
   3096     if(hw_idx == NULL) {
   3097         return BCM_E_PARAM;
   3098     }
   3099 
   3100     if(_bcm_subtag_subport_port_info[unit] == NULL) {
   3101         return BCM_E_NOT_FOUND;
   3102     }
   3103 
   3104     if (BCM_GPORT_IS_SET(subport)) {
   3105         if (BCM_GPORT_IS_SUBPORT_PORT(subport)) {
   3106             if (_BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, subport)){
   3107 
   3108                 /* Find the entry corresponding to the subport */
   3109                 for (i = 0; i < si->max_subport_coe_ports; i++) {
   3110                     if((_bcm_subtag_subport_port_info[unit][i].valid) && 
   3111                        (_bcm_subtag_subport_port_info[unit][i].subport_port == 
   3112                          subport)) {
   3113                             /* Entry found, break */
   3114                             break;
   3115                         }
   3116                 }
   3117 
   3118                 /* If not found, return error */
   3119                 if (i == si->max_subport_coe_ports) {
   3120                     return BCM_E_PORT;
   3121                 }
   3122 
   3123                 /* Get the associated hw idx */
   3124                 *hw_idx = _BCM_SUBPORT_COE_SUBTAG_PORT_INFO_TCAM_HW_ID_GET(unit, i);
   3125                 return BCM_E_NONE;
   3126             }
   3127         }
   3128     }
   3129 
   3130     return BCM_E_PORT;
   3131 }
   3132 
   3133 /*
   3134  * Function:
   3135  *      _bcmi_coe_multicast_subport_encap_get
   3136  * Purpose:
   3137  *      Get the Encap ID for NIV virtual port.
   3138  * Parameters:
   3139  *      unit            - (IN) Unit number.
   3140  *      subport_port    - (IN) Multicast group ID.
   3141  *      encap_id        - (OUT) Encap ID.
   3142  * Returns:
   3143  *      BCM_E_XXX
   3144  * Notes:
   3145  */
   3146 int
   3147 _bcmi_coe_multicast_subport_encap_get(int unit, bcm_gport_t subport_port, 
   3148                                          bcm_if_t *encap_id)
   3149 {
   3150     int i = 0;
   3151     soc_info_t *si = &SOC_INFO(unit);
   3152 
   3153     if(_bcm_subtag_subport_port_info[unit] == NULL) {
   3154         return BCM_E_NOT_FOUND;
   3155     }
   3156 
   3157     if (BCM_GPORT_IS_SET(subport_port)) {
   3158         if (BCM_GPORT_IS_SUBPORT_PORT(subport_port)) {
   3159             if (_BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, subport_port)){
   3160 
   3161                 /* Find the entry corresponding to the subport */
   3162                 for (i=0; i < si->max_subport_coe_ports; i++) {
   3163                     if((_bcm_subtag_subport_port_info[unit][i].valid) && 
   3164                        (_bcm_subtag_subport_port_info[unit][i].subport_port == 
   3165                          subport_port)) {
   3166                             /* Entry found, break */
   3167                             break;
   3168                         }
   3169                 }
   3170 
   3171                 /* If not found, return */
   3172                 if (i == si->max_subport_coe_ports) {
   3173                     return BCM_E_NOT_FOUND;
   3174                 }
   3175 
   3176                 /* Get the encap id */
   3177                 *encap_id = _bcm_subtag_subport_port_info[unit][i].nh_index;
   3178                 return BCM_E_NONE;
   3179             }
   3180         }
   3181     }
   3182 
   3183     return BCM_E_NONE;
   3184 }
   3185 
   3186 int bcmi_xgs5_subport_coe_ether_type_size_set(int unit,
   3187                                               bcm_switch_control_t type,
   3188                                               int arg)
   3189 {
   3190     uint32 rval;
   3191 
   3192     if (arg > BCMI_MAX_SHORT_VALUE || arg < 0) {
   3193         return BCM_E_PARAM;
   3194     }
   3195 
   3196 #if defined(BCM_ESW_SUPPORT) && defined(BCM_IPROC_SUPPORT)
   3197     if (soc_feature(unit, soc_feature_untethered_otp)) {
   3198         if ((type == bcmSwitchSubportCoEEtherType) ||
   3199             (type == bcmSwitchSubportEgressTpid)) {
   3200             /* 0x8100 is not a valid subtag tpid  */
   3201             if (SOC_BOND_INFO_FEATURE_GET(unit,
   3202                     socBondInfoFeatureNoCoeSubtag8100) && (arg == 0x8100)) {
   3203                 return BCM_E_PARAM;
   3204             }
   3205         }
   3206     }
   3207 #endif /*  BCM_ESW_SUPPORT && BCM_IPROC_SUPPORT */
   3208 
   3209     switch (type) {
   3210         case bcmSwitchSubportCoEEtherType:
   3211             BCM_IF_ERROR_RETURN(READ_SUBPORT_TAG_TPIDr(unit, &rval));
   3212             soc_reg_field_set(unit, SUBPORT_TAG_TPIDr, &rval, TPIDf,
   3213                               arg);
   3214             /* If the TPID is being set to '0', clear the ENABLEf */
   3215             if(arg) {
   3216                 soc_reg_field_set(unit, SUBPORT_TAG_TPIDr, &rval, ENABLEf,
   3217                                   1);
   3218             } else {
   3219                 soc_reg_field_set(unit, SUBPORT_TAG_TPIDr, &rval, ENABLEf, 
   3220                                   0);
   3221             }
   3222             SOC_IF_ERROR_RETURN(WRITE_SUBPORT_TAG_TPIDr(unit, rval));
   3223             break;
   3224 
   3225         case bcmSwitchSubportEgressTpid:
   3226             BCM_IF_ERROR_RETURN(READ_EGR_SUBPORT_TAG_TPIDr(unit, &rval));
   3227             soc_reg_field_set(unit, EGR_SUBPORT_TAG_TPIDr, &rval, TPID_4BYTE_TAGf,
   3228                               arg);
   3229             SOC_IF_ERROR_RETURN(WRITE_EGR_SUBPORT_TAG_TPIDr(unit, rval));
   3230             break;
   3231 
   3232         case bcmSwitchSubportEgressWideTpid:
   3233             BCM_IF_ERROR_RETURN(READ_EGR_SUBPORT_TAG_TPIDr(unit, &rval));
   3234             soc_reg_field_set(unit, EGR_SUBPORT_TAG_TPIDr, &rval, TPID_8BYTE_TAGf, 
   3235                               arg);
   3236             SOC_IF_ERROR_RETURN(WRITE_EGR_SUBPORT_TAG_TPIDr(unit, rval));
   3237             break;
   3238 
   3239         default:
   3240             /* Return 'BCM_E_UNAVAIL' by default */
   3241             return BCM_E_UNAVAIL;
   3242     }
   3243 
   3244     return BCM_E_NONE;
   3245 }
   3246 
   3247 int bcmi_xgs5_subport_coe_ether_type_size_get(int unit, 
   3248                                               bcm_switch_control_t type, 
   3249                                               int *arg)
   3250 {
   3251     uint32 rval;
   3252 
   3253     switch (type) {
   3254         case bcmSwitchSubportCoEEtherType:
   3255             BCM_IF_ERROR_RETURN(READ_SUBPORT_TAG_TPIDr(unit, &rval));
   3256             *arg = soc_reg_field_get(unit, SUBPORT_TAG_TPIDr, rval, 
   3257                                      TPIDf);
   3258             break;
   3259 
   3260         case bcmSwitchSubportEgressTpid:
   3261 
   3262             BCM_IF_ERROR_RETURN(READ_EGR_SUBPORT_TAG_TPIDr(unit, &rval));
   3263             *arg = soc_reg_field_get(unit, EGR_SUBPORT_TAG_TPIDr, rval, 
   3264                                      TPID_4BYTE_TAGf);
   3265             break;
   3266 
   3267         case bcmSwitchSubportEgressWideTpid:
   3268 
   3269             BCM_IF_ERROR_RETURN(READ_EGR_SUBPORT_TAG_TPIDr(unit, &rval));
   3270             *arg = soc_reg_field_get(unit, EGR_SUBPORT_TAG_TPIDr, rval, 
   3271                                      TPID_8BYTE_TAGf);
   3272 
   3273             break;
   3274 
   3275         default:
   3276             /* Return 'BCM_E_UNAVAIL' by default */
   3277             return BCM_E_UNAVAIL;
   3278     }
   3279 
   3280     return BCM_E_NONE;
   3281 }
   3282 
   3283 int bcmi_xgs5_subport_subtag_port_override_set(int unit, int port, int arg)
   3284 {
   3285     bcm_module_t        modid;
   3286     bcm_port_t          portid;
   3287     bcm_trunk_t         trunk_id;
   3288     int                 id = 0, index = 0, rv = BCM_E_UNAVAIL;
   3289     egr_port_entry_t    egr_port_entry;
   3290 
   3291     if (arg > BCMI_MAX_SHORT_VALUE || arg < 0) {
   3292         return BCM_E_PARAM;
   3293     }
   3294 #if defined(BCM_HGPROXY_COE_SUPPORT)
   3295     if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) &&
   3296         BCM_GPORT_IS_SET(port) &&
   3297         _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port) &&
   3298         SOC_MEM_FIELD_VALID(unit, EGR_LPORT_PROFILEm, VT_SYS_PORT_OVERRIDEf)) {
   3299         return bcm_esw_port_egr_lport_field_set(
   3300                    unit, port, EGR_LPORT_PROFILEm,
   3301                    VT_SYS_PORT_OVERRIDEf, arg ? 1 : 0);
   3302     }
   3303 #endif
   3304 
   3305     if(BCM_GPORT_IS_SUBPORT_PORT(port)) {
   3306         /* Resolve the subport */
   3307         BCM_IF_ERROR_RETURN(
   3308             _bcm_xgs5_subport_port_resolve(unit, port, &modid, &portid, 
   3309                                            &trunk_id, &id));
   3310         /* Get the associated index */
   3311         BCM_IF_ERROR_RETURN(
   3312             _bcm_esw_src_mod_port_table_index_get(unit, modid, portid,
   3313                                               &index));
   3314     } else {
   3315         index = port;
   3316     }
   3317 
   3318     
   3319     BCM_IF_ERROR_RETURN(
   3320         soc_mem_read(unit, EGR_PORTm, MEM_BLOCK_ALL, 
   3321                                      index, &egr_port_entry));
   3322 
   3323     soc_mem_field32_set(unit, EGR_PORTm, &egr_port_entry,
   3324                         VT_SYS_PORT_OVERRIDEf, arg ? 1 : 0);
   3325 
   3326     rv = soc_mem_write(unit, EGR_PORTm, MEM_BLOCK_ALL, 
   3327                        index, &egr_port_entry);
   3328 
   3329     return rv;
   3330 }
   3331 
   3332 int bcmi_xgs5_subport_subtag_port_override_get(int unit, int port, int *arg)
   3333 {
   3334     bcm_module_t        modid;
   3335     bcm_port_t          portid;
   3336     bcm_trunk_t         trunk_id;
   3337     int                 id = 0, index = 0;
   3338     egr_port_entry_t    egr_port_entry;
   3339  #if defined(BCM_HGPROXY_COE_SUPPORT)
   3340     if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) &&
   3341         BCM_GPORT_IS_SET(port) &&
   3342         _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port) &&
   3343         SOC_MEM_FIELD_VALID(unit, EGR_LPORT_PROFILEm, VT_SYS_PORT_OVERRIDEf)) {
   3344         return bcm_esw_port_egr_lport_field_get(
   3345                    unit, port, EGR_LPORT_PROFILEm,
   3346                    VT_SYS_PORT_OVERRIDEf, (uint32 *)arg);
   3347     }
   3348  #endif
   3349 
   3350     if(BCM_GPORT_IS_SUBPORT_PORT(port)) {
   3351         /* Resolve the subport */
   3352         BCM_IF_ERROR_RETURN(
   3353             _bcm_xgs5_subport_port_resolve(unit, port, &modid, &portid, 
   3354                                            &trunk_id, &id));
   3355         /* Get the associated index */
   3356         BCM_IF_ERROR_RETURN(
   3357             _bcm_esw_src_mod_port_table_index_get(unit, modid, portid,
   3358                                               &index));
   3359     } else {
   3360         index = port;
   3361     }
   3362 
   3363     
   3364     BCM_IF_ERROR_RETURN(soc_mem_read(unit, EGR_PORTm, MEM_BLOCK_ALL, 
   3365                                      index, &egr_port_entry));
   3366 
   3367     *arg = soc_mem_field32_get(unit, EGR_PORTm, &egr_port_entry, 
   3368                                VT_SYS_PORT_OVERRIDEf);
   3369 
   3370     return BCM_E_NONE;
   3371 }
   3372 
   3373 /*
   3374  * Function:
   3375  *      bcmi_xgs5_subport_port_learn_set
   3376  * Purpose:
   3377  *      Set the CML bits for a CoE subport.
   3378  * Returns:
   3379  *      BCM_E_XXX
   3380  */
   3381 int
   3382 bcmi_xgs5_subport_port_learn_set(int unit, bcm_gport_t subport_port_id, 
   3383                                   uint32 flags)
   3384 {
   3385     int cml = 0, rv = BCM_E_NONE;
   3386     soc_field_t fields[2];
   3387     uint32 values[2];
   3388 
   3389     /* Ensure the subport module is initialized */
   3390     _BCM_SUBPORT_COE_CHECK_INIT(unit);
   3391 
   3392     cml = 0;
   3393     if (!(flags & BCM_PORT_LEARN_FWD)) {
   3394        cml |= (1 << 0);
   3395     }
   3396     if (flags & BCM_PORT_LEARN_CPU) {
   3397        cml |= (1 << 1);
   3398     }
   3399     if (flags & BCM_PORT_LEARN_PENDING) {
   3400        cml |= (1 << 2);
   3401     }
   3402     if (flags & BCM_PORT_LEARN_ARL) {
   3403        cml |= (1 << 3);
   3404     }
   3405 
   3406     /* Setup the fields */
   3407     fields[0] = CML_FLAGS_MOVEf;
   3408     fields[1] = CML_FLAGS_NEWf;
   3409     /* Set the values */
   3410     values[0] = values[1] = cml;
   3411 
   3412     BCM_IF_ERROR_RETURN(_bcm_esw_port_tab_set(unit, subport_port_id,
   3413            _BCM_CPU_TABS_NONE, fields[0], values[0]));
   3414 
   3415     BCM_IF_ERROR_RETURN(_bcm_esw_port_tab_set(unit, subport_port_id,
   3416            _BCM_CPU_TABS_NONE, fields[1], values[1]));
   3417 
   3418     return rv;
   3419 }
   3420 
   3421 /*
   3422  * Function:    
   3423  *      bcmi_xgs5_subport_port_learn_get
   3424  * Purpose:
   3425  *      Get the CML bits for a CoE subport.
   3426  * Returns: 
   3427  *      BCM_E_XXX
   3428  */     
   3429 int     
   3430 bcmi_xgs5_subport_port_learn_get(int unit, bcm_gport_t subport_port_id,
   3431                                   uint32 *flags)
   3432 {
   3433     int32 cml = 0;
   3434     
   3435     /* Ensure the subport module is initialized */
   3436     _BCM_SUBPORT_COE_CHECK_INIT(unit);
   3437 
   3438     BCM_IF_ERROR_RETURN(_bcm_esw_port_tab_get(unit, subport_port_id,
   3439            CML_FLAGS_NEWf, &cml));
   3440 
   3441     *flags = 0;
   3442     if (!(cml & (1 << 0))) {
   3443        *flags |= BCM_PORT_LEARN_FWD;
   3444     }
   3445     if (cml & (1 << 1)) {
   3446        *flags |= BCM_PORT_LEARN_CPU;
   3447     }
   3448     if (cml & (1 << 2)) {
   3449        *flags |= BCM_PORT_LEARN_PENDING;
   3450     }
   3451     if (cml & (1 << 3)) {
   3452        *flags |= BCM_PORT_LEARN_ARL;
   3453     }
   3454 
   3455     return BCM_E_NONE;
   3456 }
   3457 
   3458 
   3459 #ifdef BCM_WARM_BOOT_SUPPORT
   3460 
   3461 #define SCACHE_ALLOC_SIZE_INIT(_var_)                                          \
   3462     do {                                                                       \
   3463         (_var_) = 0; (_scache_ofst_) = 0;                                      \
   3464         LOG_VERBOSE(BSL_LS_BCM_SUBPORT,                                        \
   3465             (BSL_META_U(unit,                                                  \
   3466                         "WarmBoot: Scache offset initialized to 0\n")));       \
   3467     } while (0)
   3468 
   3469 #define SCACHE_ALLOC_SIZE_INCR(_var_, _count_)                                 \
   3470     do {                                                                       \
   3471         (_var_) += (_count_); (_scache_ofst_) += (_count_);                    \
   3472         LOG_VERBOSE(BSL_LS_BCM_SUBPORT,                                        \
   3473                     (BSL_META_U(unit,                                          \
   3474                                 "WarmBoot: Scache offset incr by %d to %d\n"), \
   3475                                 (int)(_count_),  (_scache_ofst_)              \
   3476                                ));                                            \
   3477     } while (0)
   3478 
   3479 #define SCACHE_BYTE_INIT(_scache_ptr_)                                         \
   3480     do {                                                                       \
   3481         _scache_ofst_ = 0;                                                     \
   3482         LOG_VERBOSE(BSL_LS_BCM_SUBPORT,                                        \
   3483                     (BSL_META_U(unit,                                          \
   3484                                 "WarmBoot: Scache offset initialized to 0\n")  \
   3485                                ));                                            \
   3486     } while (0)
   3487 
   3488 #define SCACHE_BYTE_COPY(_scache_ptr_, _local_var_, _size_)                   \
   3489     do {                                                                      \
   3490         sal_memcpy(_scache_ptr_, _local_var_, _size_);                        \
   3491         _scache_ptr_ += (_size_);                                             \
   3492         (_scache_ofst_) += (_size_);                                          \
   3493         LOG_VERBOSE(BSL_LS_BCM_SUBPORT,                                       \
   3494                     (BSL_META_U(unit,                                         \
   3495                                 "WarmBoot: Scache offset incr by %d to %d\n"),\
   3496                                 (int)(_size_),  (_scache_ofst_)              \
   3497                                ));                                           \
   3498     } while (0)
   3499 
   3500 #define SCACHE_BYTE_RESTORE(_scache_ptr_, _local_var_, _size_)                \
   3501     do {                                                                      \
   3502         sal_memcpy(_local_var_, _scache_ptr_, _size_);                        \
   3503         _scache_ptr_ += (_size_);                                             \
   3504         (_scache_ofst_) += (_size_);                                          \
   3505         LOG_VERBOSE(BSL_LS_BCM_SUBPORT,                                       \
   3506                     (BSL_META_U(unit,                                         \
   3507                                 "WarmBoot: Scache offset incr by %d to %d\n"),\
   3508                                 (int)(_size_),  (_scache_ofst_)              \
   3509                                ));                                           \
   3510     } while (0)
   3511 
   3512 #define SCACHE_BYTE_RESTORE2(_scache_ptr_, _local_var_, _scache_sz_, _local_sz_)\
   3513     do {                                                                      \
   3514         SOC_SCACHE_SIZE_MIN_RECOVER(_scache_ptr_, _local_var_, _scache_sz_, _local_sz_);\
   3515         (_scache_ofst_) += (_scache_sz_);                                     \
   3516         LOG_VERBOSE(BSL_LS_BCM_SUBPORT,                                       \
   3517                     (BSL_META_U(unit,                                         \
   3518                                 "WarmBoot: Scache offset incr by %d to %d\n"),\
   3519                                 (int)(_scache_sz_),  (_scache_ofst_)          \
   3520                                ));                                            \
   3521     } while (0)
   3522 
   3523 /*
   3524  * Function:
   3525  *      bcmi_xgs5_subport_wb_scache_alloc
   3526  * Purpose:
   3527  *      Allocate scache memory for individual entries to be saved for L2 warm-boot
   3528  * Parameters:
   3529  *      unit - (IN) StrataSwitch unit number.
   3530  *      version - (IN) version number
   3531  *      alloc_sz - (OUT) The allocated size
   3532  * Returns:
   3533  *      BCM_E_XXX
   3534  */
   3535 int
   3536 bcmi_xgs5_subport_wb_scache_alloc(int unit, uint16 version, int *alloc_sz)
   3537 {
   3538     int num_vlan = 0;
   3539     soc_info_t *si = &SOC_INFO(unit);
   3540     int incr_sz;
   3541     uint32 _scache_ofst_ = 0;
   3542 
   3543     SCACHE_ALLOC_SIZE_INIT(*alloc_sz);
   3544 
   3545     /* Num subport groups (_bcm_subport_group_count) */
   3546     SCACHE_ALLOC_SIZE_INCR(*alloc_sz, sizeof(int));
   3547 
   3548     /* Subport-group bitmap (_bcm_subport_group_bitmap) */
   3549     SCACHE_ALLOC_SIZE_INCR(*alloc_sz,
   3550         SHR_BITALLOCSIZE(si->max_subport_coe_groups));
   3551 
   3552     /* Subport-subtag-group bitmap (_bcm_subtag_group_bitmap) */
   3553     SCACHE_ALLOC_SIZE_INCR(*alloc_sz,
   3554         SHR_BITALLOCSIZE(si->max_subport_coe_groups));
   3555 
   3556     /* Number of Subport ports per group
   3557        (_bcm_subport_group_subport_port_count)*/
   3558     SCACHE_ALLOC_SIZE_INCR(*alloc_sz,
   3559         (si->max_subport_coe_groups * sizeof(int)));
   3560 
   3561     incr_sz = SOC_SCACHE_SIZE_MIN(sizeof(pbmp_t), 
   3562                                   SHR_BITALLOCSIZE(SOC_MAX_NUM_PORTS));
   3563     /* Bitmap of subtended ports */ 
   3564     SCACHE_ALLOC_SIZE_INCR(*alloc_sz, incr_sz);
   3565 
   3566     /* VLAN ID array bimap (_bcm_subtag_vlan_id_bitmap) */
   3567     num_vlan = soc_mem_index_count(unit, VLAN_TABm);
   3568     SCACHE_ALLOC_SIZE_INCR(*alloc_sz,
   3569                            SOC_MAX_NUM_PORTS * SHR_BITALLOCSIZE(num_vlan));
   3570 
   3571     /* Subport port info (_bcm_subtag_subport_port_info_t) */
   3572     SCACHE_ALLOC_SIZE_INCR(*alloc_sz,
   3573         (si->max_subport_coe_ports * sizeof(_bcm_subtag_subport_port_info_t)));
   3574 
   3575 
   3576     return BCM_E_NONE;
   3577 }
   3578 
   3579 /*
   3580  * Function:
   3581  *      bcmi_xgs5_subport_wb_sync
   3582  * Purpose:
   3583  *      Sync desired subport data to scache passed in
   3584  * Parameters:
   3585  *      unit - (IN) StrataSwitch unit number.
   3586  *      version - (IN) version number
   3587  *      scache_ptr - (IN) Pointer to scache where data will be synced
   3588  * Returns:
   3589  *      BCM_E_XXX
   3590  */
   3591 
   3592 int
   3593 bcmi_xgs5_subport_wb_sync(int unit, uint16 version, uint8 **scache_ptr)
   3594 {
   3595     int value = 0, num_vlan = 0, port = 0;
   3596     soc_info_t *si = &SOC_INFO(unit);
   3597     int copy_sz;
   3598     uint32 _scache_ofst_ = 0;
   3599 
   3600     SCACHE_BYTE_INIT(*scache_ptr);
   3601 
   3602     /* If the 'subtag_allowed_pbm' is non-null, it means subport
   3603        config is in effect and we need to sync it to scache */
   3604     if (BCM_PBMP_NOT_NULL(SOC_INFO(unit).subtag_allowed_pbm)) {
   3605 
   3606         /* Num subport groups (_bcm_subport_group_count) */
   3607         value = _bcm_subport_group_count[unit];
   3608         SCACHE_BYTE_COPY(*scache_ptr, &value, sizeof(int));
   3609 
   3610         /* Subport-group bitmap (_bcm_subport_group_bitmap) */
   3611         SCACHE_BYTE_COPY(*scache_ptr, _bcm_subport_group_bitmap[unit],
   3612                           SHR_BITALLOCSIZE(si->max_subport_coe_groups));
   3613 
   3614         /* Subport-group bitmap (_bcm_subtag_group_bitmap) */
   3615         SCACHE_BYTE_COPY(*scache_ptr, _bcm_subtag_group_bitmap[unit],
   3616                           SHR_BITALLOCSIZE(si->max_subport_coe_groups));
   3617 
   3618         /* Number of Subport ports per group
   3619            (_bcm_subport_group_subport_port_count)*/
   3620         SCACHE_BYTE_COPY(*scache_ptr,
   3621                          _bcm_subport_group_subport_port_count[unit],
   3622                          (si->max_subport_coe_groups * sizeof(int)));
   3623 
   3624         copy_sz = SOC_SCACHE_SIZE_MIN(sizeof(pbmp_t), 
   3625                                       SHR_BITALLOCSIZE(SOC_MAX_NUM_PORTS));
   3626         /* Bitmap of subtended ports */ 
   3627         /* coverity[overrun-buffer-arg] */
   3628         SCACHE_BYTE_COPY(*scache_ptr, &si->subtag_pbm, copy_sz);
   3629 
   3630         /* VLAN ID array bimap (_bcm_subtag_vlan_id_bitmap) */
   3631         num_vlan = soc_mem_index_count(unit, VLAN_TABm);
   3632 
   3633         /* Copy over each configured port's vlan bitmap */
   3634         BCM_PBMP_ITER(si->subtag_pbm, port) {
   3635 
   3636             SCACHE_BYTE_COPY(*scache_ptr, _bcm_subtag_vlan_id_bitmap[unit][port],
   3637                              SHR_BITALLOCSIZE(num_vlan));
   3638         }
   3639 
   3640         /* Copy over the subport port info */
   3641         SCACHE_BYTE_COPY(*scache_ptr, _bcm_subtag_subport_port_info[unit],
   3642                (si->max_subport_coe_ports * sizeof(_bcm_subtag_subport_port_info_t)));
   3643     }
   3644 
   3645     return BCM_E_NONE;
   3646 }
   3647 
   3648 /*
   3649  * Function:
   3650  *      bcmi_xgs5_subport_wb_recover
   3651  * Purpose:
   3652  *      Recover subport data that was sync'd before.
   3653  * Parameters:
   3654  *      unit - (IN) StrataSwitch unit number.
   3655  *      version - (IN) version number
   3656  *      scache_ptr - (IN) Pointer to scache where data will be recovered from
   3657  * Returns:
   3658  *      BCM_E_XXX
   3659  */
   3660 
   3661 int
   3662 bcmi_xgs5_subport_wb_recover(int unit, uint16 version, uint8 **scache_ptr)
   3663 {
   3664     int num_vlan = 0, port = 0;
   3665     soc_info_t *si = &SOC_INFO(unit);
   3666     int max_num_ports, pbmp_port_max, scache_sz;
   3667     uint32 _scache_ofst_ = 0;
   3668 
   3669     SCACHE_BYTE_INIT(*scache_ptr);
   3670 
   3671     /* If the 'subtag_allowed_pbm' is non-null, it means subport
   3672        config is in effect and we need to sync it to scache */
   3673     if (BCM_PBMP_NOT_NULL(SOC_INFO(unit).subtag_allowed_pbm)) {
   3674 
   3675         /* Recover SOC_MAX_NUM_PORTS from scache */
   3676         max_num_ports = soc_scache_dictionary_entry_get(unit, 
   3677                                      ssden_SOC_MAX_NUM_PORTS,
   3678                                      SOC_MAX_NUM_PORTS);
   3679         pbmp_port_max = soc_scache_dictionary_entry_get(unit, 
   3680                                      ssden_SOC_PBMP_PORT_MAX,
   3681                                      SOC_PBMP_PORT_MAX);
   3682         /* Num subport groups (_bcm_subport_group_count) */
   3683         SCACHE_BYTE_RESTORE(*scache_ptr, &_bcm_subport_group_count[unit],
   3684                             sizeof(int));
   3685 
   3686         /* Subport-group bitmap (_bcm_subport_group_bitmap) */
   3687         SCACHE_BYTE_RESTORE(*scache_ptr, _bcm_subport_group_bitmap[unit],
   3688                           SHR_BITALLOCSIZE(si->max_subport_coe_groups));
   3689 
   3690         /* Subport-group bitmap (_bcm_subtag_group_bitmap) */
   3691         SCACHE_BYTE_RESTORE(*scache_ptr, _bcm_subtag_group_bitmap[unit],
   3692                           SHR_BITALLOCSIZE(si->max_subport_coe_groups));
   3693 
   3694         /* Number of Subport ports per group
   3695            (_bcm_subport_group_subport_port_count)*/
   3696         /* coverity[overrun-buffer-arg] */
   3697         SCACHE_BYTE_RESTORE(*scache_ptr,
   3698                          _bcm_subport_group_subport_port_count[unit],
   3699                          (si->max_subport_coe_groups * sizeof(int)));
   3700 
   3701         scache_sz = SOC_SCACHE_SIZE_MIN(SHR_BITALLOCSIZE(pbmp_port_max), 
   3702                                         SHR_BITALLOCSIZE(max_num_ports));
   3703         /* Bitmap of subtended ports */ 
   3704         SCACHE_BYTE_RESTORE2(*scache_ptr, &si->subtag_pbm, 
   3705                              scache_sz, sizeof(pbmp_t));
   3706 
   3707         sal_memcpy(&si->subtag.bitmap, &si->subtag_pbm, sizeof(pbmp_t));
   3708 
   3709         /* VLAN ID array bimap (_bcm_subtag_vlan_id_bitmap) */
   3710         num_vlan = soc_mem_index_count(unit, VLAN_TABm);
   3711 
   3712         /* Copy over each configured port's vlan bitmap */
   3713         BCM_PBMP_ITER(si->subtag_pbm, port) {
   3714 
   3715             SCACHE_BYTE_RESTORE(*scache_ptr, 
   3716                                 _bcm_subtag_vlan_id_bitmap[unit][port],
   3717                                 SHR_BITALLOCSIZE(num_vlan));
   3718         }
   3719 
   3720         /* Copy over the subport port info */
   3721         SCACHE_BYTE_RESTORE(*scache_ptr, _bcm_subtag_subport_port_info[unit],
   3722                (si->max_subport_coe_ports * 
   3723                 sizeof(_bcm_subtag_subport_port_info_t)));
   3724     }
   3725 
   3726     return BCM_E_NONE;
   3727 }
   3728 
   3729 #endif /* BCM_WARM_BOOT_SUPPORT */
   3730 
   3731 
   3732 #ifdef BCM_WARM_BOOT_SUPPORT_SW_DUMP
   3733 
   3734 /*
   3735  * Function:
   3736  *      _bcm_coe_subport_sw_dump
   3737  * Purpose:
   3738  *      Print Subport module s/w state
   3739  * Parameters:
   3740  *      unit - (IN) StrataSwitch unit number.
   3741  * Returns:
   3742  *      Void
   3743  */
   3744 
   3745 void
   3746 _bcm_coe_subport_sw_dump(int unit)
   3747 {
   3748     int idx = 0, port = 0, num_vlan = 0;
   3749     soc_info_t *si = &SOC_INFO(unit);
   3750 
   3751     LOG_CLI((BSL_META_U(unit,
   3752                 "Total Subport Groups: %d\n"),
   3753                 _bcm_subport_group_count[unit]));
   3754 
   3755     LOG_CLI((BSL_META_U(unit,
   3756                         "Subport Groups and ports per group\n")));
   3757     for(idx = 0; idx < si->max_subport_coe_groups; idx++) {
   3758         if(_BCM_SUBPORT_COE_GROUP_USED_GET(unit, idx)) {
   3759            LOG_CLI((BSL_META_U(unit, "%d "), idx));
   3760            LOG_CLI((BSL_META_U(unit, ":%d "),
   3761                     _bcm_subport_group_subport_port_count[unit][idx]));
   3762         }
   3763     }
   3764 
   3765     LOG_CLI((BSL_META_U(unit,
   3766                 "VLAN Ids per port\n")));
   3767 
   3768     /* Run thru all ports and print their VLAN ID bimap */
   3769     num_vlan = soc_mem_index_count(unit, VLAN_TABm);
   3770 
   3771     BCM_PBMP_ITER(si->subtag_allowed_pbm, port) {
   3772 
   3773         LOG_CLI((BSL_META_U(unit, "VLAN List for Port: %d "), port));
   3774 
   3775         for(idx = 0; idx < num_vlan; idx++) {
   3776             if(_BCM_COE_SUBTAG_VLAN_ID_USED_GET(unit, port, idx)) {
   3777                 LOG_CLI((BSL_META_U(unit, "Vlan: %d "), idx));
   3778             }
   3779         }
   3780     }
   3781 
   3782     /* Run through the subports configured and dump their details */
   3783     LOG_CLI((BSL_META_U(unit,
   3784                         "Subport Ports:\n")));
   3785 
   3786     for (idx = 0; idx < si->max_subport_coe_ports; idx++) {
   3787         if(_bcm_subtag_subport_port_info[unit][idx].valid) {
   3788 
   3789             LOG_CLI((BSL_META_U(unit,
   3790                      "Group: 0x%x vlan: %d subtag_tcam_idx: %d "
   3791                      "subport_modport: 0x%x subport_port: 0x%x\n"
   3792                      "nh_index: %d valid: %d modport_subport_idx: 0x%x "
   3793                      "phb_valid: %d priority: %d color: %d\n"), 
   3794                     _bcm_subtag_subport_port_info[unit][idx].group,
   3795                     _bcm_subtag_subport_port_info[unit][idx].vlan,
   3796                     _bcm_subtag_subport_port_info[unit][idx].subtag_tcam_hw_idx,
   3797                     _bcm_subtag_subport_port_info[unit][idx].subport_modport,
   3798                     _bcm_subtag_subport_port_info[unit][idx].subport_port,
   3799                     _bcm_subtag_subport_port_info[unit][idx].nh_index,
   3800                     _bcm_subtag_subport_port_info[unit][idx].valid,
   3801                     _bcm_subtag_subport_port_info[unit][idx].modport_subport_idx,
   3802                     _bcm_subtag_subport_port_info[unit][idx].phb_valid,
   3803                     _bcm_subtag_subport_port_info[unit][idx].priority,
   3804                     _bcm_subtag_subport_port_info[unit][idx].color));
   3805         }
   3806     }
   3807 
   3808     LOG_CLI((BSL_META_U(unit,
   3809                         "\n----\n")));
   3810 
   3811 }
   3812 #endif /* BCM_WARM_BOOT_SUPPORT_SW_DUMP */
   3813 
   3814 #else  /* BCM_TRIDENT2PLUS_SUPPORT */
   3815 int bcm_esw_td2p_subport_not_empty;
   3816 #endif /* BCM_TRIDENT2PLUS_SUPPORT */
   3817