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

stack.c (362245B)


      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:        stack.c
      8  * Purpose:     BCM level APIs for stacking applications
      9  */
     10 
     11 #include <shared/bsl.h>
     12 #include <sal/core/sync.h>
     13 #include <soc/drv.h>
     14 #include <soc/scache.h>
     15 #include <soc/scache_dictionary.h>
     16 #include <soc/profile_mem.h>
     17 #include <soc/firebolt.h>
     18 #include <bcm/error.h>
     19 #include <bcm/stack.h>
     20 
     21 #include <bcm_int/control.h>
     22 #include <bcm_int/esw/mbcm.h>
     23 #include <bcm_int/esw/port.h>
     24 #include <bcm_int/esw/vlan.h>
     25 #include <bcm_int/esw/ipmc.h>
     26 #include <bcm_int/esw/mcast.h>
     27 #include <bcm_int/esw/rx.h>
     28 #include <bcm_int/esw/stack.h>
     29 #include <bcm_int/esw/trunk.h>
     30 #include <bcm_int/esw/trident.h>
     31 #include <bcm_int/esw/katana2.h>
     32 #include <bcm_int/esw/trx.h>
     33 #include <bcm_int/esw/trident2plus.h>
     34 
     35 #include <bcm_int/esw_dispatch.h>
     36 
     37 #include <bcm_int/esw/portctrl.h>
     38 
     39 #ifdef BCM_WARM_BOOT_SUPPORT
     40 #include <bcm_int/esw/switch.h>
     41 #endif /* BCM_WARM_BOOT_SUPPORT */
     42 #if defined(BROADCOM_DEBUG)
     43 #include <bcm_int/rpc/rlink.h>
     44 #include <appl/cputrans/atp.h>
     45 #endif /* BROADCOM_DEBUG */
     46 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
     47 #define BCM_STK_TD2P_NUM_LPORTS  (106)
     48 #endif /* BCM_TRIDENT2PLUS_SUPPORT */
     49 
     50 #if defined(BCM_MONTEREY_SUPPORT)
     51 #define BCM_STK_MONTEREY_NUM_LPORTS  (67)
     52 #endif /* BCM_MONTEREY_SUPPORT */
     53 
     54 #if defined(BCM_APACHE_SUPPORT)
     55 #define BCM_STK_APACHE_NUM_LPORTS  (75)
     56 #endif /* BCM_TRIDENT2PLUS_SUPPORT */
     57 
     58 #if defined(BCM_TRIDENT3_SUPPORT)
     59 #include <soc/flexport/trident3/trident3_flexport_defines.h>
     60 #endif /* BCM_TRIDENT3_SUPPORT */
     61 
     62 #if defined(BCM_MAVERICK2_SUPPORT)
     63 #include <soc/flexport/maverick2/maverick2_flexport_defines.h>
     64 #endif /* BCM_MAVERICK2_SUPPORT */
     65 
     66 #if defined(BCM_HELIX5_SUPPORT)
     67 #include <soc/flexport/helix5/helix5_flexport_defines.h>
     68 #endif /* BCM_HELIX5_SUPPORT */
     69 
     70 #if defined(BCM_HERCULES15_SUPPORT) || defined(BCM_BRADLEY_SUPPORT)
     71 #define LOCAL_MODMAP_SUPPORT
     72 STATIC int _bcm_esw_modmap_init(int unit);
     73 #endif /* BCM_HERCULES15_SUPPORT */
     74 
     75 static sal_mutex_t stack_mutex;
     76 
     77 #define ESW_STK_LOCK sal_mutex_take(stack_mutex, sal_mutex_FOREVER)
     78 #define ESW_STK_UNLOCK sal_mutex_give(stack_mutex)
     79 
     80 #ifdef _BCM_STK_FLAGS_GET
     81 STATIC int _esw_stk_flags_get(int unit, bcm_port_t port, uint32 *flags);
     82 #endif
     83 
     84 STATIC int _esw_stk_port_set(int unit, bcm_port_t port, uint32 flags);
     85 
     86 STATIC int _bcm_xgs_fabric_stk_init(int unit);
     87 STATIC int _bcm_xgs3_stk_init(int unit);
     88 STATIC int _bcm_xgs3_ignore_my_modid(int unit);
     89 
     90 #if defined(BCM_TRX_SUPPORT)
     91 STATIC int _bcm_stk_modport_profile_init(int unit);
     92 STATIC soc_profile_mem_t *modport_profile[BCM_MAX_NUM_UNITS];
     93 
     94 /* Software modport map entry data structure */
     95 typedef struct bcmi_trx_modport_map_entry_s {
     96     uint8 dest_istrunk[SOC_MAX_NUM_PORTS];
     97     uint8 dest[SOC_MAX_NUM_PORTS];
     98 } bcmi_trx_modport_map_entry_t;
     99 
    100 /* Software modport map profile data structure */
    101 typedef struct bcmi_trx_modport_map_profile_s {
    102     int ref_count;
    103     int num_entries;
    104     bcmi_trx_modport_map_entry_t *entry_array;
    105 } bcmi_trx_modport_map_profile_t;
    106 
    107 /* Software modport map info data structure */
    108 typedef struct bcmi_trx_modport_map_info_s {
    109     int num_profiles;
    110     bcmi_trx_modport_map_profile_t *profile_array;
    111 } bcmi_trx_modport_map_info_t;
    112 
    113 STATIC bcmi_trx_modport_map_info_t *
    114     bcmi_trx_modport_map_info[BCM_MAX_NUM_UNITS];
    115 
    116 /* Global initialized parameter for software modport map */
    117 STATIC uint8 trx_modport_map_initialized = 0;
    118 
    119 #define TRX_MODPORT_MAP_INFO(unit) bcmi_trx_modport_map_info[unit]
    120 #define TRX_MODPORT_MAP_PROFILE(unit, index) \
    121     bcmi_trx_modport_map_info[unit]->profile_array[index]
    122 
    123 STATIC int bcmi_trx_modport_map_detach(int unit);
    124 #endif /* BCM_TRX_SUPPORT */
    125 
    126 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_HURRICANE3_SUPPORT)
    127 src_modid_base_index_bookkeeping_t *src_modid_base_index_bk[BCM_MAX_NUM_UNITS];
    128 #define _BCM_SRC_MOD_PORT_TABLE_USED_GET(_u_, _idx_) \
    129     SHR_BITGET(src_modid_base_index_bk[_u_]->src_mod_port_table_bitmap, _idx_)
    130 #define _BCM_SRC_MOD_PORT_TABLE_USED_SET(_u_, _idx_) \
    131     SHR_BITSET(src_modid_base_index_bk[_u_]->src_mod_port_table_bitmap, _idx_)
    132 #define _BCM_SRC_MOD_PORT_TABLE_USED_CLR(_u_, _idx_) \
    133     SHR_BITCLR(src_modid_base_index_bk[_u_]->src_mod_port_table_bitmap, _idx_)
    134 #define _BCM_SRC_MOD_PORT_TABLE_USED_SET_RANGE(_u_, _idx_, _count_) \
    135     SHR_BITSET_RANGE(src_modid_base_index_bk[_u_]->src_mod_port_table_bitmap, _idx_, _count_)
    136 #define _BCM_SRC_MOD_PORT_TABLE_USED_CLR_RANGE(_u_, _idx_, _count_) \
    137     SHR_BITCLR_RANGE(src_modid_base_index_bk[_u_]->src_mod_port_table_bitmap, _idx_, _count_)
    138 #define _BCM_SRC_MOD_PORT_TABLE_TEST_RANGE(_u_, _idx_, _count_, _result_) \
    139     SHR_BITTEST_RANGE(src_modid_base_index_bk[_u_]->src_mod_port_table_bitmap, _idx_, _count_, _result_)
    140 
    141 STATIC soc_mem_t src_modbase_mems[] = {
    142     SOURCE_TRUNK_MAP_MODBASEm,
    143     EGR_GPP_ATTRIBUTES_MODBASEm,
    144 #ifdef BCM_TRIDENT2PLUS_SUPPORT
    145     EGR_DGPP_TO_NHI_MODBASEm,
    146     MODID_BASE_PTRm,
    147 #endif
    148 }; 
    149 
    150 STATIC soc_mem_t src_mod_port_mems[] = {
    151     SOURCE_TRUNK_MAP_TABLEm,
    152     EGR_GPP_ATTRIBUTESm,
    153 #ifdef BCM_TRIDENT2PLUS_SUPPORT
    154     EGR_DGPP_TO_NHIm,
    155     MODPORT_MAP_SUBPORTm,
    156 #endif
    157 };
    158 
    159 STATIC void _src_modid_base_index_bk_detach(int unit);
    160 STATIC int _src_modid_base_index_free(int unit, bcm_module_t modid, int nports);
    161 
    162 #endif /* BCM_TRIDENT_SUPPORT || BCM_HURRICANE3_SUPPORT */
    163 
    164 #if defined(BCM_TOMAHAWK3_SUPPORT)
    165 #define BCM_STK_API_TH3_SUPPORT_CHECK(_unit_)       \
    166         if (SOC_IS_TOMAHAWK3(_unit_)) {             \
    167             return BCM_E_UNAVAIL;                   \
    168         }
    169 #else
    170 #define BCM_STK_API_TH3_SUPPORT_CHECK(_unit_)
    171 #endif
    172 
    173 #if defined(LOCAL_MODMAP_SUPPORT)
    174 #define _NUM_SL_MOD         64
    175 #define _MAX_SPORT          31
    176 #define _XGS3_MODMAP_GROUPS_MAX  1
    177 #define _XGS3_MODMAP_FMOD_MAX   127
    178 #define _XGS4_FABRIC_MODMAP_FMOD_MAX   255
    179 #define FMOD_MAX(unit)  \
    180         ((SOC_IS_SC_CQ(unit) || SOC_IS_HURRICANE3(unit) || \
    181            SOC_IS_GREYHOUND2(unit)) ? \
    182             _XGS4_FABRIC_MODMAP_FMOD_MAX : _XGS3_MODMAP_FMOD_MAX)
    183 #define FMOD_RANGE_CHECK(a) \
    184         if (((a) < 0) || ((a) > FMOD_MAX(unit))) return(BCM_E_PARAM)
    185 #define LMOD_RANGE_CHECK(a) if (((a) < 0) || ((a) > 63))  return(BCM_E_PARAM)
    186 #define SMOD_RANGE_CHECK(a) if (((a) < 0) || ((a) > 63))  return(BCM_E_PARAM)
    187 #define FMOD_LMOD_CHECK(fm, lm) if (fm < lm) return(BCM_E_PARAM)
    188 #define SPORT_RANGE_CHECK(a) if ((a) > _MAX_SPORT)  return(BCM_E_PARAM)
    189 #define BCM_MODMAP_FEATURE_CHECK(unit, f) \
    190         do { \
    191             if (!soc_feature(unit, soc_feature_modmap)) { \
    192                 return BCM_E_UNAVAIL; \
    193             } \
    194         } while(0)
    195 #define MOD_MAP_DATA_CHECK(unit) \
    196         if (mod_map_data[unit] == NULL)  return(BCM_E_INIT)
    197 /*
    198  * One entry for each SOC device containing modmap information
    199  * for that device.
    200  */
    201 typedef struct mod_map_ctrl {
    202     int         l_modid[SOC_MAX_NUM_PORTS];
    203     int         thresh_d[_NUM_SL_MOD];
    204     int         fmod0[SOC_MAX_NUM_PORTS];
    205 } mod_map_ctrl_t;
    206 
    207 STATIC mod_map_ctrl_t *mod_map_data[BCM_MAX_NUM_UNITS];
    208 
    209 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
    210 
    211 typedef struct modid_mask_num_mods_s {
    212     int num_mods;    /* number of extra modules */
    213     uint32 mod_mask; /* module mask for extra modules */
    214 } modid_mask_num_mods_t;
    215 
    216 #define BCM_MAX_NUM_MODID_MASK 7
    217 STATIC modid_mask_num_mods_t modid_mask_data[BCM_MAX_NUM_MODID_MASK] = {
    218     {1,   0xFF}, 
    219     {2,   0xFE},
    220     {4,   0xFC}, 
    221     {8,   0xF8},
    222     {16,  0xF0}, 
    223     {32,  0xE0},
    224     {64,  0xC0}, 
    225 };
    226 
    227 #endif /* BCM_TRIDENT2PLUS_SUPPORT */
    228 
    229 #define STACK_INIT(unit) \
    230         if (stack_mutex == NULL) { return BCM_E_INIT; }
    231 
    232 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_HELIX4_SUPPORT)
    233 
    234 _bcm_stk_trident_linkflap_trunk_map_t _bcm_stk_trident_linkflap_trunk_map[BCM_MAX_NUM_UNITS];
    235 
    236 /*
    237  * Function:
    238  *      _bcm_stk_modport_map_linkscan_handler
    239  * Purpose:
    240  *      Called from linkscan handler when port toggles.
    241  *      Enables and Disables the port in MODPORT_MAP_SW.
    242  * Parameters:
    243  *      unit  - SOC unit #
    244  *      info  - port info
    245  * Returns:
    246  *      None
    247  */
    248 void 
    249 _bcm_stk_modport_map_linkscan_handler(int unit, 
    250                 bcm_port_t port, bcm_port_info_t *info)
    251 {
    252     int rv;
    253     SOC_LINKSCAN_MODPORT_MAP_LOCK(unit);
    254     rv = _bcm_td_stk_modport_map_linkscan_handler(unit, port, info);
    255     SOC_LINKSCAN_MODPORT_MAP_UNLOCK(unit);
    256     if (BCM_FAILURE(rv)) {
    257         LOG_WARN(BSL_LS_BCM_STK,
    258                  (BSL_META_U(unit,
    259                   "linkscan handler error: Unit %d, port %d, rv %d\n"),
    260                   unit, port, rv));
    261    }
    262 }
    263 #endif /*defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_HELIX4_SUPPORT)*/
    264 
    265 
    266 
    267 STATIC int
    268 _bcm_esw_modmap_init(int unit)
    269 {
    270     if (NULL == mod_map_data[unit]) {
    271         mod_map_data[unit] =
    272             sal_alloc (sizeof (mod_map_ctrl_t), "modmap_state");
    273     }
    274     if (NULL == mod_map_data[unit]) {
    275         return (BCM_E_MEMORY);
    276     }
    277 
    278     sal_memset(mod_map_data[unit], 0, sizeof (mod_map_ctrl_t));
    279 
    280     return BCM_E_NONE;
    281 }
    282 
    283 STATIC int
    284 _bcm_esw_modmap_detach(int unit)
    285 {
    286     if (NULL == mod_map_data[unit]) {
    287         return (BCM_E_NONE);
    288     }
    289     sal_free(mod_map_data[unit]);
    290 
    291     mod_map_data[unit] = NULL;
    292     return BCM_E_NONE;
    293 }
    294 #endif  /* MODMAP_SUPPORT */
    295 
    296 
    297 /*
    298  * Internal init (alloc the mutex).  Unit is ignored (for now)
    299  */
    300 
    301 STATIC int
    302 _bcm_esw_stk_init(void)
    303 {
    304     if (stack_mutex == NULL) {
    305         if ((stack_mutex = sal_mutex_create("bcm_esw_lock")) == NULL) {
    306             return BCM_E_MEMORY;
    307         }
    308     }
    309 
    310     return BCM_E_NONE;
    311 }
    312 
    313 
    314 /*
    315  * Function:
    316  *      _bcm_esw_stk_detach
    317  * Purpose:
    318  *      De-initialize device stacking
    319  * Parameters:
    320  *      unit  - (IN) BCM device number.
    321  * Returns:
    322  *      BCM_E_XXX
    323  */
    324 
    325 int
    326 _bcm_esw_stk_detach(int unit)
    327 {
    328     if (stack_mutex != NULL) {
    329         sal_mutex_destroy(stack_mutex);
    330         stack_mutex = NULL;
    331     }
    332 
    333     BCM_IF_ERROR_RETURN(bcm_esw_stk_modmap_unregister(unit));
    334 
    335 #if defined(LOCAL_MODMAP_SUPPORT)
    336     if (soc_feature(unit, soc_feature_modmap)) {
    337         SOC_IF_ERROR_RETURN(_bcm_esw_modmap_detach(unit));
    338     }
    339 #endif /* MODMAP_SUPPORT */
    340 
    341 #if defined(BCM_TRX_SUPPORT)
    342     if (modport_profile[unit]) {
    343         soc_profile_mem_destroy(unit, modport_profile[unit]);
    344         sal_free(modport_profile[unit]);
    345         modport_profile[unit] = NULL;
    346     }
    347 
    348     if (soc_feature(unit, soc_feature_modport_map_dest_is_hg_port_bitmap)) {
    349         BCM_IF_ERROR_RETURN(bcmi_trx_modport_map_detach(unit));
    350     }
    351 #endif /* BCM_TRX_SUPPORT */
    352 
    353 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_HURRICANE3_SUPPORT)
    354     if (soc_feature(unit, soc_feature_src_modid_base_index)) {
    355             _src_modid_base_index_bk_detach(unit);
    356     }
    357 #endif /* BCM_TRIDENT_SUPPORT || BCM_HURRICANE3_SUPPORT */
    358 #if defined(BCM_TRIDENT_SUPPORT) 
    359     if (soc_feature(unit, soc_feature_modport_map_dest_is_port_or_trunk)) {
    360         BCM_IF_ERROR_RETURN(bcm_td_modport_map_detach(unit));
    361     }
    362 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_HELIX4_SUPPORT)
    363     if (soc_feature(unit, soc_feature_epc_linkflap_recover)) {
    364         bcm_esw_linkscan_unregister(unit, _bcm_stk_modport_map_linkscan_handler);
    365     }
    366 #endif
    367 #endif /* BCM_TRIDENT_SUPPORT */
    368     return BCM_E_NONE;
    369 }
    370 
    371 #if defined(BCM_TRX_SUPPORT)
    372 /*
    373  * Function:
    374  *    bcmi_trx_modport_map_free_resources
    375  * Purpose:
    376  *    Free resources of software modport map profiles.
    377  * Parameters:
    378  *    unit - (IN) Unit number
    379  * Returns:
    380  *    None
    381  */
    382 STATIC void
    383 bcmi_trx_modport_map_free_resources(int unit)
    384 {
    385     int i;
    386 
    387     if (bcmi_trx_modport_map_info[unit]) {
    388         if (TRX_MODPORT_MAP_INFO(unit)->profile_array) {
    389             for (i = 0; i < TRX_MODPORT_MAP_INFO(unit)->num_profiles; i++) {
    390                 if (TRX_MODPORT_MAP_PROFILE(unit, i).entry_array) {
    391                     sal_free(TRX_MODPORT_MAP_PROFILE(unit, i).entry_array);
    392                     TRX_MODPORT_MAP_PROFILE(unit, i).entry_array = NULL;
    393                 }
    394             }
    395             sal_free(TRX_MODPORT_MAP_INFO(unit)->profile_array);
    396             TRX_MODPORT_MAP_INFO(unit)->profile_array = NULL;
    397         }
    398         sal_free(bcmi_trx_modport_map_info[unit]);
    399         bcmi_trx_modport_map_info[unit] = NULL;
    400     }
    401 }
    402 
    403 /*
    404  * Function:
    405  *    bcmi_trx_modport_map_detach
    406  * Purpose:
    407  *    Detach software modport map profiles.
    408  * Parameters:
    409  *    unit - (IN) Unit number
    410  * Returns:
    411  *    BCM_E_xxx
    412  */
    413 STATIC int
    414 bcmi_trx_modport_map_detach(int unit)
    415 {
    416     bcmi_trx_modport_map_free_resources(unit);
    417 
    418     return BCM_E_NONE;
    419 }
    420 
    421 /*
    422  * Function:
    423  *    bcmi_trx_modport_map_init
    424  * Purpose:
    425  *    Initialize software modport map profiles.
    426  * Parameters:
    427  *    unit - (IN) Unit number
    428  * Returns:
    429  *    BCM_E_xxx
    430  */
    431 STATIC int
    432 bcmi_trx_modport_map_init(int unit)
    433 {
    434     int rv = BCM_E_NONE;
    435     int i;
    436 
    437     LOG_VERBOSE(BSL_LS_BCM_STK,
    438                 (BSL_META_U(unit,
    439                             "bcmi_trx_modport_map_init\n")));
    440 
    441     /* Global initialization flag setup */
    442     if (trx_modport_map_initialized == 0) {
    443         for (i = 0; i < BCM_MAX_NUM_UNITS; i++) {
    444             bcmi_trx_modport_map_info[i] = NULL;
    445         }
    446         trx_modport_map_initialized = 1;
    447     }
    448 
    449     /* Clean up the modport map profiles related resources */
    450     if (bcmi_trx_modport_map_info[unit] != NULL) {
    451         bcmi_trx_modport_map_detach(unit);
    452     }
    453 
    454     /* Allocate modport map profiles resource for this unit. */
    455     bcmi_trx_modport_map_info[unit] =
    456         sal_alloc(sizeof(bcmi_trx_modport_map_info_t), "modport map info");
    457     if (NULL == bcmi_trx_modport_map_info[unit]) {
    458         return BCM_E_MEMORY;
    459     }
    460     sal_memset(TRX_MODPORT_MAP_INFO(unit), 0,
    461                sizeof(bcmi_trx_modport_map_info_t));
    462 
    463     TRX_MODPORT_MAP_INFO(unit)->num_profiles =
    464         (soc_mem_index_count(unit, MODPORT_MAP_SWm) /
    465         (SOC_MODID_MAX(unit) + 1));
    466 
    467     if (NULL == TRX_MODPORT_MAP_INFO(unit)->profile_array) {
    468         TRX_MODPORT_MAP_INFO(unit)->profile_array =
    469             sal_alloc(sizeof(bcmi_trx_modport_map_profile_t) *
    470                       TRX_MODPORT_MAP_INFO(unit)->num_profiles,
    471                       "trx modport map profiles");
    472         if (NULL == TRX_MODPORT_MAP_INFO(unit)->profile_array) {
    473             bcmi_trx_modport_map_free_resources(unit);
    474             return BCM_E_MEMORY;
    475         }
    476     }
    477     sal_memset(TRX_MODPORT_MAP_INFO(unit)->profile_array, 0,
    478                sizeof(bcmi_trx_modport_map_profile_t) *
    479                TRX_MODPORT_MAP_INFO(unit)->num_profiles);
    480 
    481     for (i = 0; i < TRX_MODPORT_MAP_INFO(unit)->num_profiles; i++) {
    482         TRX_MODPORT_MAP_PROFILE(unit, i).num_entries =
    483             (SOC_MODID_MAX(unit) + 1);
    484         if (NULL == TRX_MODPORT_MAP_PROFILE(unit, i).entry_array) {
    485             TRX_MODPORT_MAP_PROFILE(unit, i).entry_array =
    486                 sal_alloc(sizeof(bcmi_trx_modport_map_entry_t) *
    487                           TRX_MODPORT_MAP_PROFILE(unit, i).num_entries,
    488                           "trx modport map entries");
    489             if (NULL == TRX_MODPORT_MAP_PROFILE(unit, i).entry_array) {
    490                 bcmi_trx_modport_map_free_resources(unit);
    491                 return BCM_E_MEMORY;
    492             }
    493         }
    494         sal_memset(TRX_MODPORT_MAP_PROFILE(unit, i).entry_array, 0,
    495                    sizeof(bcmi_trx_modport_map_entry_t) *
    496                    TRX_MODPORT_MAP_PROFILE(unit, i).num_entries);
    497     }
    498 
    499     return rv;
    500 }
    501 #endif /* BCM_TRX_SUPPORT */
    502 
    503 #ifdef BCM_WARM_BOOT_SUPPORT
    504 
    505 #define BCM_WB_VERSION_1_0                SOC_SCACHE_VERSION(1,0)
    506 #define BCM_WB_VERSION_1_1                SOC_SCACHE_VERSION(1,1)
    507 #define BCM_WB_VERSION_1_2                SOC_SCACHE_VERSION(1,2)
    508 #define BCM_WB_VERSION_1_3                SOC_SCACHE_VERSION(1,3)
    509 #define BCM_WB_VERSION_1_4                SOC_SCACHE_VERSION(1,4)
    510 #define BCM_WB_VERSION_1_5                SOC_SCACHE_VERSION(1,5)
    511 #define BCM_WB_VERSION_1_6                SOC_SCACHE_VERSION(1,6)
    512 #define BCM_WB_VERSION_1_7                SOC_SCACHE_VERSION(1,7)
    513 #define BCM_WB_VERSION_1_8                SOC_SCACHE_VERSION(1,8)
    514 #define BCM_WB_VERSION_1_9                SOC_SCACHE_VERSION(1,9)
    515 #define BCM_WB_DEFAULT_VERSION            BCM_WB_VERSION_1_9
    516 
    517 #if defined(BCM_TRX_SUPPORT)
    518 /*
    519  * Function:
    520  *    bcmi_trx_modport_map_scache_size_get
    521  * Purpose:
    522  *    Get scache size needed to store software modport map profile state.
    523  * Parameters:
    524  *    unit - (IN) Unit number
    525  *    max_num_ports - (IN) Maximum number ports
    526  *    size - (OUT) Scache size needed.
    527  * Returns:
    528  *    None
    529  */
    530 STATIC int
    531 bcmi_trx_modport_map_scache_size_get(int unit, int max_num_ports, int *size)
    532 {
    533     /* For each modport map profile entry, max_num_ports bytes of internal
    534      * state need to be stored:
    535      * - First byte to n (n = max_num_ports):
    536      *    bit 7 = dest_istrunk[n], bits 6-0 = dest[n].
    537      */
    538     *size = (max_num_ports * sizeof(uint8)) *
    539             soc_mem_index_count(unit, MODPORT_MAP_SWm);
    540 
    541     return BCM_E_NONE;
    542 }
    543 
    544 /*
    545  * Function:
    546  *    bcmi_trx_modport_map_sync
    547  * Purpose:
    548  *    Store software modport map profile state to scache.
    549  * Parameters:
    550  *    unit - (IN) Unit number
    551  *    scache_ptr - Scache pointer.
    552  * Returns:
    553  *    None
    554  */
    555 STATIC int
    556 bcmi_trx_modport_map_sync(int unit, uint8 **scache_ptr)
    557 {
    558     int i, j, k;
    559     bcmi_trx_modport_map_profile_t profile;
    560     int istrunk, dest;
    561     uint8 dest_byte;
    562 
    563     for (i = 0; i < TRX_MODPORT_MAP_INFO(unit)->num_profiles; i++) {
    564         profile = TRX_MODPORT_MAP_PROFILE(unit, i);
    565         for (j = 0; j < profile.num_entries; j++) {
    566             for (k = 0; k < SOC_MAX_NUM_PORTS; k++) {
    567                 istrunk = profile.entry_array[j].dest_istrunk[k];
    568                 dest = profile.entry_array[j].dest[k];
    569 
    570                 dest_byte = ((istrunk & 0x1) << 7) | (dest & 0x7f);
    571                 sal_memcpy(*scache_ptr, &dest_byte, sizeof(dest_byte));
    572                 *scache_ptr += sizeof(dest_byte);
    573             }
    574         }
    575     }
    576 
    577     return BCM_E_NONE;
    578 }
    579 
    580 /*
    581  * Function:
    582  *    bcmi_trx_modport_map_reinit
    583  * Purpose:
    584  *    Retrieve software modport map profile state from scache.
    585  * Parameters:
    586  *    unit - (IN) Unit number
    587  *    max_num_ports - (IN) Maximum number ports
    588  *    scache_ptr - Scache pointer.
    589  * Returns:
    590  *    None
    591  */
    592 STATIC int
    593 bcmi_trx_modport_map_reinit(int unit, int max_num_ports, uint8 **scache_ptr)
    594 {
    595     int rv = BCM_E_NONE;
    596     bcm_port_t ing_port;
    597     uint32 val;
    598     int profile_index;
    599     int i, j, k;
    600     soc_mem_t mem;
    601     bcmi_trx_modport_map_profile_t profile;
    602     int modport_map_entry_dw, modport_map_entry_sz;
    603     int modport_map_buf_size;
    604     uint8 *modport_map_buf = NULL;
    605     int index_min, index_max;
    606     modport_map_entry_t *entry_p;
    607     pbmp_t pbmp;
    608     uint8 dest_byte;
    609     bcm_pbmp_t all_pbmp;
    610 
    611     BCM_PBMP_CLEAR(all_pbmp);
    612     BCM_PBMP_ASSIGN(all_pbmp, PBMP_ALL(unit));
    613 
    614     /* Recover each profile's reference count */
    615     PBMP_ITER(all_pbmp, ing_port) {
    616         BCM_IF_ERROR_RETURN(
    617             READ_MODPORT_MAP_SELr(unit, ing_port, &val));
    618         profile_index = soc_reg_field_get(unit, MODPORT_MAP_SELr, val,
    619                                           MODPORT_MAP_INDEX_UPPERf);
    620         TRX_MODPORT_MAP_PROFILE(unit, profile_index).ref_count++;
    621     }
    622 
    623     mem = MODPORT_MAP_SWm;
    624     for (i = 0; i < TRX_MODPORT_MAP_INFO(unit)->num_profiles; i++) {
    625         profile = TRX_MODPORT_MAP_PROFILE(unit, i);
    626         if (profile.ref_count == 0) {
    627             /* Skip the scache region containing the state of this profile */
    628             if (*scache_ptr != NULL) {
    629                 *scache_ptr += profile.num_entries *
    630                                (max_num_ports * sizeof(dest_byte));
    631             }
    632             continue;
    633         }
    634 
    635         /* Read profile from MODPOR_MAP_SWm */
    636         modport_map_entry_dw = soc_mem_entry_words(unit, mem);
    637         modport_map_entry_sz = modport_map_entry_dw * sizeof(uint32);
    638         modport_map_buf_size = profile.num_entries * modport_map_entry_sz;
    639         modport_map_buf = soc_cm_salloc(unit, modport_map_buf_size,
    640                                         "modport map buffer");
    641         if (NULL == modport_map_buf) {
    642             return BCM_E_MEMORY;
    643         }
    644 
    645         index_min = i * profile.num_entries;
    646         index_max = index_min + profile.num_entries - 1;
    647         rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY,
    648                                 index_min, index_max, modport_map_buf);
    649         if (BCM_FAILURE(rv)) {
    650             soc_cm_sfree(unit, modport_map_buf);
    651             return rv;
    652         }
    653 
    654         /* Recover profile state */
    655         for (j = 0; j < profile.num_entries; j++) {
    656             entry_p = soc_mem_table_idx_to_pointer(unit, mem,
    657                                                    modport_map_entry_t *,
    658                                                    modport_map_buf, j);
    659             soc_mem_pbmp_field_get(unit, mem, entry_p,
    660                                    HIGIG_PORT_BITMAPf, &pbmp);
    661             for (k = 0; k < max_num_ports; k++) {
    662                 if (*scache_ptr != NULL) {
    663                     sal_memcpy(&dest_byte, *scache_ptr, sizeof(dest_byte));
    664                     *scache_ptr += sizeof(dest_byte);
    665                     profile.entry_array[j].dest_istrunk[k] =
    666                         (dest_byte >> 7) & 0x1;
    667                     profile.entry_array[j].dest[k] = dest_byte & 0x7f;
    668                 } else {
    669                     if (BCM_PBMP_MEMBER(pbmp, k)) {
    670                         profile.entry_array[j].dest_istrunk[k] = 0;
    671                         profile.entry_array[j].dest[k] = k;
    672                     }
    673                 }
    674             }
    675         }
    676 
    677         soc_cm_sfree(unit, modport_map_buf);
    678     }
    679 
    680     return rv;
    681 }
    682 #endif /* BCM_TRX_SUPPORT */
    683 
    684 /*
    685  * Function:
    686  *      _bcm_esw_stk_sync
    687  * Purpose:
    688  *      Record STACK module persisitent info for Level 2 Warm Boot
    689  * Parameters:
    690  *      unit - Unit number.
    691  * Returns:
    692  *      BCM_E_XXX
    693  */
    694 int
    695 _bcm_esw_stk_sync(int unit)
    696 {
    697     soc_scache_handle_t scache_handle;
    698     uint8               *stk_scache_ptr;
    699     int                 rv = BCM_E_NONE;
    700     int                 auto_include_disable = 0;
    701 
    702 #if defined(LOCAL_MODMAP_SUPPORT)
    703     STACK_INIT(unit);
    704 #endif
    705     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_STACK, 0);
    706     BCM_IF_ERROR_RETURN
    707         (_bcm_esw_scache_ptr_get(unit, scache_handle, FALSE,
    708                                  0, &stk_scache_ptr, 
    709                                  BCM_WB_DEFAULT_VERSION, NULL));
    710     /* Stack port bitmaps */
    711     sal_memcpy(stk_scache_ptr, &SOC_PBMP_STACK_CURRENT(unit),
    712                sizeof(soc_pbmp_t));
    713     stk_scache_ptr += sizeof(soc_pbmp_t);
    714     sal_memcpy(stk_scache_ptr, &SOC_PBMP_STACK_INACTIVE(unit),
    715                sizeof(soc_pbmp_t));
    716     stk_scache_ptr += sizeof(soc_pbmp_t);
    717     sal_memcpy(stk_scache_ptr, &SOC_PBMP_STACK_PREVIOUS(unit),
    718                sizeof(soc_pbmp_t));
    719     stk_scache_ptr += sizeof(soc_pbmp_t);
    720 
    721 #if defined(LOCAL_MODMAP_SUPPORT)
    722     /* Modmap */
    723     if (soc_feature(unit, soc_feature_modmap)) {
    724         int    i;
    725         int    port;
    726         int    max_group;
    727         uint8  val;
    728 
    729         for (port = 0; port < SOC_MAX_NUM_PORTS; port++) {
    730             val = mod_map_data[unit]->l_modid[port];
    731             sal_memcpy(stk_scache_ptr, &val, sizeof(val));
    732             stk_scache_ptr += sizeof(val);
    733         }
    734 
    735         for (i = 0; i < _NUM_SL_MOD; i++) {
    736             val = mod_map_data[unit]->thresh_d[i];
    737             sal_memcpy(stk_scache_ptr, &val, sizeof(val));
    738             stk_scache_ptr += sizeof(val);
    739         }
    740 
    741         BCM_IF_ERROR_RETURN
    742             (bcm_esw_stk_port_modmap_group_max_get(unit, &max_group));
    743         for (i = 0; i <= max_group; i++) {
    744             val = mod_map_data[unit]->fmod0[i];
    745             sal_memcpy(stk_scache_ptr, &val, sizeof(val));
    746             stk_scache_ptr += sizeof(val);
    747         }
    748     }
    749 #endif /* LOCAL_MODMAP_SUPPORT */
    750 
    751 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_HURRICANE3_SUPPORT)
    752     if (soc_feature(unit, soc_feature_src_modid_base_index)) {
    753         int         i, modid;
    754         uint8       val;
    755         soc_info_t *si = &SOC_INFO(unit);
    756 
    757         for (i = 0; i <= SOC_MODID_MAX(unit); i++) {
    758             /* num_ports is uint16, here store the low 8bits,
    759              * the high 8bits see below. */
    760             val = src_modid_base_index_bk[unit]->num_ports[i] & 0xff;
    761             sal_memcpy(stk_scache_ptr, &val, sizeof(val));
    762             stk_scache_ptr += sizeof(val);
    763         }
    764 
    765         if(soc_feature(unit, soc_feature_hgproxy_subtag_coe)) {
    766             for (i = 0; i < si->num_coe_modules; i++) {
    767                 modid = src_modid_base_index_bk[unit]->
    768                             coe_module_id_list[i];
    769                 sal_memcpy(stk_scache_ptr, &modid, sizeof(modid));
    770                 stk_scache_ptr += sizeof(modid);
    771             }
    772         }
    773 
    774         /* Version_1_4 -> Version_1_5:
    775                * module_id_range is introduced by Version_1_5
    776                * Store src_modid_base_index_bk[unit]->module_id_range to scache. */
    777         if(soc_feature(unit, soc_feature_multi_next_hops_on_port)) {
    778             int mod_base = 0;
    779             uint32 mod_mask = 0;
    780 
    781             mod_base = src_modid_base_index_bk[unit]->module_id_range.mod_base;
    782             sal_memcpy(stk_scache_ptr, &mod_base, sizeof(mod_base));
    783             stk_scache_ptr += sizeof(mod_base);
    784             mod_mask = src_modid_base_index_bk[unit]->module_id_range.mod_mask;
    785             sal_memcpy(stk_scache_ptr, &mod_mask, sizeof(mod_mask));
    786             stk_scache_ptr += sizeof(mod_mask);
    787         }
    788     }
    789 #endif /* BCM_TRIDENT_SUPPORT || BCM_HURRICANE3_SUPPORT */
    790 
    791 #if defined(BCM_TRIDENT_SUPPORT)
    792     if (soc_feature(unit, soc_feature_modport_map_dest_is_port_or_trunk)) {
    793         BCM_IF_ERROR_RETURN(bcm_td_modport_map_sync(unit, &stk_scache_ptr));
    794     }
    795 #endif /* BCM_TRIDENT_SUPPORT */
    796 
    797 #if defined(BCM_TRX_SUPPORT)
    798     if (soc_feature(unit, soc_feature_modport_map_dest_is_hg_port_bitmap)) {
    799         BCM_IF_ERROR_RETURN(
    800             bcmi_trx_modport_map_sync(unit, &stk_scache_ptr));
    801     }
    802 #endif /* BCM_TRX_SUPPORT */
    803 
    804     rv = bcm_esw_switch_control_get(unit,
    805             bcmSwitchFabricTrunkAutoIncludeDisable, &auto_include_disable);
    806     if (BCM_E_UNAVAIL == rv) {
    807         auto_include_disable = 0;
    808     } else if (BCM_FAILURE(rv)) {
    809         return rv;
    810     }
    811     sal_memcpy(stk_scache_ptr, &auto_include_disable, sizeof(int));
    812     stk_scache_ptr += sizeof(int);
    813 
    814 #if defined(BCM_TRIDENT_SUPPORT)
    815     if (soc_feature(unit, soc_feature_modport_map_dest_is_port_or_trunk)) {
    816         BCM_IF_ERROR_RETURN(
    817             bcm_td_stk_trunk_override_hi_sync(unit, &stk_scache_ptr));
    818     }
    819 #endif /* BCM_TRIDENT_SUPPORT */
    820 #if defined(BCM_TRIUMPH3_SUPPORT)
    821     if (soc_feature(unit, soc_feature_epc_linkflap_recover)) {
    822         BCM_IF_ERROR_RETURN(
    823             bcm_td_modport_map_enable_sync(unit, &stk_scache_ptr));
    824     }
    825 #endif /* defined(BCM_TRIUMPH3_SUPPORT) */
    826 
    827     /* Version_1_5 -> Version_1_6:
    828      * uint8 is not enough for src_modid_base_index_bk[unit]->num_ports
    829      * Store the High-unit8 to scache */
    830 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_HURRICANE3_SUPPORT)
    831     if (soc_feature(unit, soc_feature_src_modid_base_index)) {
    832         int     i;
    833         uint8   val;
    834         for (i = 0; i <= SOC_MODID_MAX(unit); i++) {
    835             val = (src_modid_base_index_bk[unit]->num_ports[i] >> 8);
    836             sal_memcpy(stk_scache_ptr, &val, sizeof(val));
    837             stk_scache_ptr += sizeof(val);
    838         }
    839     }
    840 #endif
    841 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_HELIX4_SUPPORT)
    842     if (soc_feature(unit, soc_feature_epc_linkflap_recover)) {
    843         BCM_IF_ERROR_RETURN(
    844             bcm_td_linkflap_trunk_map_sync(unit, &stk_scache_ptr));
    845     }
    846 #endif /* defined(BCM_TRIUMPH3_SUPPORT) */
    847 
    848     /* Version_1_8 -> Version_1_9:
    849      * module_id_type_list & multi_nexthop_module_id_list are introduced by Version_1_9
    850      * Store src_modid_base_index_bk[unit]->module_id_type_list and
    851      * src_modid_base_index_bk[unit]->multi_nexthop_module_id_list to scache. */
    852 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
    853     if (soc_feature(unit, soc_feature_multi_next_hops_on_port)) {
    854         int i, val;
    855         soc_info_t *si = &SOC_INFO(unit);
    856         for (i = 0; i < si->num_modules; i++) {
    857             val = src_modid_base_index_bk[unit]->module_id_type_list[i];
    858             sal_memcpy(stk_scache_ptr, &val, sizeof(val));
    859             stk_scache_ptr += sizeof(val);
    860         }
    861 
    862         for (i = 0; i < si->num_modules; i++) {
    863             val = src_modid_base_index_bk[unit]->multi_nexthop_module_id_list[i];
    864             sal_memcpy(stk_scache_ptr, &val, sizeof(val));
    865             stk_scache_ptr += sizeof(val);
    866         }
    867     }
    868 #endif
    869 
    870     return BCM_E_NONE;
    871 }
    872 
    873 /*
    874  * Function:
    875  *      _bcm_stk_reinit
    876  * Purpose:
    877  *      Recover STACK software state.
    878  * Parameters:
    879  *      unit - Unit number.
    880  * Returns:
    881  *      BCM_E_XXX
    882  */
    883 STATIC int
    884 _bcm_stk_reinit(int unit)
    885 {
    886     int                 rv;
    887     soc_scache_handle_t scache_handle;
    888     uint8               *stk_scache_ptr;
    889     uint16              recovered_ver;
    890     int                 auto_include_disable;
    891     int                 realloc_sz;
    892 #if defined(LOCAL_MODMAP_SUPPORT)
    893     int                 max_num_ports = SOC_MAX_NUM_PORTS;
    894 #endif /* LOCAL_MODMAP_SUPPORT */
    895 
    896     realloc_sz = 0;
    897     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_STACK, 0);
    898     rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE,
    899                                  0, &stk_scache_ptr, 
    900                                  BCM_WB_DEFAULT_VERSION, &recovered_ver);
    901 
    902     if (rv == BCM_E_NOT_FOUND) {
    903         stk_scache_ptr = NULL;
    904     } else if (BCM_FAILURE(rv)) {
    905         return rv;
    906     }
    907 
    908 #if defined(LOCAL_MODMAP_SUPPORT)
    909     if (stk_scache_ptr != NULL) {
    910         max_num_ports = soc_scache_dictionary_entry_get(unit, 
    911                                      ssden_SOC_MAX_NUM_PORTS,
    912                                      SOC_MAX_NUM_PORTS);
    913     }
    914 #endif /* LOCAL_MODMAP_SUPPORT */
    915 
    916     if (stk_scache_ptr != NULL) {
    917         /* Stack port bitmaps */
    918         sal_memcpy(&SOC_PBMP_STACK_CURRENT(unit), stk_scache_ptr,
    919                    sizeof(soc_pbmp_t));
    920         stk_scache_ptr += sizeof(soc_pbmp_t);
    921         sal_memcpy(&SOC_PBMP_STACK_INACTIVE(unit), stk_scache_ptr,
    922                    sizeof(soc_pbmp_t));
    923         stk_scache_ptr += sizeof(soc_pbmp_t);
    924         sal_memcpy(&SOC_PBMP_STACK_PREVIOUS(unit), stk_scache_ptr,
    925                    sizeof(soc_pbmp_t));
    926         stk_scache_ptr += sizeof(soc_pbmp_t);
    927     } else {
    928         BCM_PBMP_CLEAR(SOC_PBMP_STACK_CURRENT(unit));
    929         BCM_PBMP_CLEAR(SOC_PBMP_STACK_INACTIVE(unit));
    930         BCM_PBMP_CLEAR(SOC_PBMP_STACK_PREVIOUS(unit));
    931     }
    932     
    933     BCM_IF_ERROR_RETURN(_bcm_esw_stk_init());
    934 
    935 #if defined(LOCAL_MODMAP_SUPPORT)
    936     /* Modmap */
    937     if (soc_feature(unit, soc_feature_modmap)) {
    938         int    i;
    939         int    port;
    940         int    max_group;
    941         uint8  val;
    942 
    943         BCM_IF_ERROR_RETURN(_bcm_esw_modmap_init(unit));
    944 
    945         /* Recover l_modid, thresh_d, and fmod0 */
    946         if (stk_scache_ptr != NULL) {
    947             for (port = 0; port < max_num_ports; port++) {
    948                 if (port < SOC_MAX_NUM_PORTS) {
    949                     sal_memcpy(&val, stk_scache_ptr, sizeof(val));
    950                     mod_map_data[unit]->l_modid[port] = val;
    951                 }
    952                 stk_scache_ptr += sizeof(val);
    953             }
    954             realloc_sz += (SOC_MAX_NUM_PORTS - max_num_ports) * sizeof(val);
    955 
    956             for (i = 0; i < _NUM_SL_MOD; i++) {
    957                 sal_memcpy(&val, stk_scache_ptr, sizeof(val));
    958                 mod_map_data[unit]->thresh_d[i] = val;
    959                 stk_scache_ptr += sizeof(val);
    960             }
    961 
    962             BCM_IF_ERROR_RETURN
    963                 (bcm_esw_stk_port_modmap_group_max_get(unit, &max_group));
    964             for (i = 0; i <= max_group; i++) {
    965                 sal_memcpy(&val, stk_scache_ptr, sizeof(val));
    966                 mod_map_data[unit]->fmod0[i] = val;
    967                 stk_scache_ptr += sizeof(val);
    968             }
    969         }
    970     }
    971 #endif /* LOCAL_MODMAP_SUPPORT */
    972 
    973 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_HURRICANE3_SUPPORT)
    974     if (soc_feature(unit, soc_feature_src_modid_base_index)) {
    975         int i, modId;
    976         uint8 val;
    977         uint8 *stm_modoffset_buf = NULL;
    978         source_trunk_map_modbase_entry_t *stm_modoffset_entry;
    979         int start, end, offset, offset_max;
    980         soc_info_t  *si = &SOC_INFO(unit);
    981 
    982         BCM_IF_ERROR_RETURN(bcmi_esw_src_modid_base_index_bk_init(unit));
    983 
    984         stm_modoffset_buf = soc_cm_salloc(unit,
    985                 SOC_MEM_TABLE_BYTES(unit, SOURCE_TRUNK_MAP_MODBASEm),
    986                 "SOURCE_TRUNK_MAP_MODBASE buffer");
    987         if (NULL == stm_modoffset_buf) {
    988             return BCM_E_MEMORY;
    989         }
    990 
    991         start = soc_mem_index_min(unit, SOURCE_TRUNK_MAP_MODBASEm);
    992         end = soc_mem_index_max(unit, SOURCE_TRUNK_MAP_MODBASEm);
    993         rv = soc_mem_read_range(unit, SOURCE_TRUNK_MAP_MODBASEm,
    994                 MEM_BLOCK_ANY, start, end, stm_modoffset_buf);
    995         if (SOC_FAILURE(rv)) {
    996             soc_cm_sfree(unit, stm_modoffset_buf);
    997             return rv;
    998         }
    999 
   1000         if (stk_scache_ptr != NULL) {
   1001 
   1002             /* Recover low-8bits of src_modid_base_index_bk[unit]->num_ports array */
   1003             for (i = 0; i <= SOC_MODID_MAX(unit); i++) {
   1004                 sal_memcpy(&val, stk_scache_ptr, sizeof(val));
   1005                 src_modid_base_index_bk[unit]->num_ports[i] = val;
   1006                 stk_scache_ptr += sizeof(val);
   1007             }
   1008 
   1009             if(soc_feature(unit, soc_feature_hgproxy_subtag_coe)) {
   1010                 for (i = 0; i < si->num_coe_modules; i++) {
   1011                     sal_memcpy(&modId, stk_scache_ptr, sizeof(modId));
   1012                     src_modid_base_index_bk[unit]->coe_module_id_list[i] = modId;
   1013                     stk_scache_ptr += sizeof(modId);
   1014                 }
   1015             }
   1016 
   1017             /* Version_1_4 -> Version_1_5:
   1018                       * module_id_range is introduced by Version_1_5
   1019                       * Recover src_modid_base_index_bk[unit]->module_id_range from scache. */
   1020             if(soc_feature(unit, soc_feature_multi_next_hops_on_port)) {
   1021                 int mod_base = 0;
   1022                 uint32 mod_mask = 0;
   1023 
   1024                 sal_memcpy(&mod_base, stk_scache_ptr, sizeof(mod_base));
   1025                 src_modid_base_index_bk[unit]->module_id_range.mod_base = mod_base;
   1026                 stk_scache_ptr += sizeof(mod_base);
   1027                 sal_memcpy(&mod_mask, stk_scache_ptr, sizeof(mod_mask));
   1028                 src_modid_base_index_bk[unit]->module_id_range.mod_mask = mod_mask;
   1029                 stk_scache_ptr += sizeof(mod_mask); 
   1030             }
   1031         } else {
   1032             /* In Level 1 recovery of src_modid_base_index_bk[unit]->
   1033              * src_mod_port_table_bitmap, it's not known how many
   1034              * SOURCE_TRUNK_MAP entries each module ID occupies.
   1035              * Hence, we conservatively assume that all
   1036              * SOURCE_TRUNK_MAP entries from index 0 to (highest
   1037              * SOURCE_TRUNK_MAP_MODBASE.BASE + SOC_PORT_ADDR_MAX)
   1038              * are used.
   1039              */
   1040             offset_max = 0;
   1041             for (i = start; i <= end; i++) {
   1042                 stm_modoffset_entry = soc_mem_table_idx_to_pointer
   1043                     (unit, SOURCE_TRUNK_MAP_MODBASEm,
   1044                      source_trunk_map_modbase_entry_t *, stm_modoffset_buf, i);
   1045                 offset = soc_SOURCE_TRUNK_MAP_MODBASEm_field32_get(unit,
   1046                         stm_modoffset_entry, BASEf);
   1047                 if (offset > offset_max) {
   1048                     offset_max = offset;
   1049                 }
   1050             }
   1051             _BCM_SRC_MOD_PORT_TABLE_USED_SET_RANGE(unit, 0,
   1052                     (offset_max + SOC_PORT_ADDR_MAX(unit) + 1));
   1053         }
   1054 
   1055         soc_cm_sfree(unit, stm_modoffset_buf);
   1056     }
   1057 #endif /* BCM_TRIDENT_SUPPORT || BCM_HURRICANE3_SUPPORT */
   1058 
   1059 #if defined(BCM_TRX_SUPPORT)
   1060     /* Modport profile */
   1061 #ifdef BCM_TRIDENT_SUPPORT
   1062     if (soc_feature(unit, soc_feature_modport_map_dest_is_port_or_trunk)) {
   1063         BCM_IF_ERROR_RETURN(bcm_td_modport_map_init(unit));
   1064         if (stk_scache_ptr != NULL) {
   1065             if (recovered_ver >= BCM_WB_VERSION_1_1) { 
   1066                 /* Retrieve modport map profile info from scache */
   1067                 BCM_IF_ERROR_RETURN(bcm_td_modport_map_reinit(unit,
   1068                             &stk_scache_ptr));
   1069             } else {
   1070                 uint8 *null_scache_ptr = NULL;
   1071                 int modport_map_scache_size;
   1072 
   1073                 /* Retrieve modport map profile info from hardware */
   1074                 BCM_IF_ERROR_RETURN(bcm_td_modport_map_reinit(unit,
   1075                             &null_scache_ptr));
   1076                 BCM_IF_ERROR_RETURN(bcm_td_modport_map_scache_size_get(unit,
   1077                                             &modport_map_scache_size));
   1078                 realloc_sz += modport_map_scache_size;
   1079             }
   1080         } else { /* Level 1 warm boot */
   1081             uint8 *null_scache_ptr = NULL;
   1082 
   1083             /* Retrieve modport map profile info from hardware */
   1084             BCM_IF_ERROR_RETURN(bcm_td_modport_map_reinit(unit,
   1085                         &null_scache_ptr));
   1086         }
   1087     } else
   1088 #endif /* BCM_TRIDENT_SUPPORT */
   1089     if (SOC_IS_TR_VL(unit)) {
   1090         BCM_IF_ERROR_RETURN(_bcm_stk_modport_profile_init(unit));
   1091     }
   1092 
   1093     if (soc_feature(unit, soc_feature_modport_map_dest_is_hg_port_bitmap)) {
   1094         BCM_IF_ERROR_RETURN(bcmi_trx_modport_map_init(unit));
   1095         if (stk_scache_ptr != NULL) {
   1096             if (recovered_ver >= BCM_WB_VERSION_1_1) {
   1097                 /* Retrieve modport map profile info from scache */
   1098                 BCM_IF_ERROR_RETURN(
   1099                     bcmi_trx_modport_map_reinit(unit, max_num_ports,
   1100                                                 &stk_scache_ptr));
   1101             } else {
   1102                 uint8 *null_scache_ptr = NULL;
   1103                 int modport_map_scache_size;
   1104 
   1105                 /* Retrieve modport map profile info from hardware */
   1106                 BCM_IF_ERROR_RETURN(
   1107                     bcmi_trx_modport_map_reinit(unit, max_num_ports,
   1108                                                 &null_scache_ptr));
   1109                 BCM_IF_ERROR_RETURN(
   1110                     bcmi_trx_modport_map_scache_size_get
   1111                         (unit, max_num_ports, &modport_map_scache_size));
   1112                 realloc_sz += modport_map_scache_size;
   1113             }
   1114         } else {  /* Level 1 warm boot */
   1115             uint8 *null_scache_ptr = NULL;
   1116 
   1117             /* Retrieve modport map profile info from hardware */
   1118             BCM_IF_ERROR_RETURN(
   1119                 bcmi_trx_modport_map_reinit(unit, max_num_ports,
   1120                                             &null_scache_ptr));
   1121         }
   1122     }
   1123 #endif /* BCM_TRX_SUPPORT */
   1124 
   1125     auto_include_disable = 0;
   1126     if (stk_scache_ptr != NULL) {
   1127         if (recovered_ver >= BCM_WB_VERSION_1_2) {
   1128             /* Retrieve bcmSwitchFabricTrunkAutoIncludeDisable value */
   1129             sal_memcpy(&auto_include_disable, stk_scache_ptr, sizeof(int));
   1130             stk_scache_ptr += sizeof(int);
   1131         } else {
   1132             realloc_sz += sizeof(int);
   1133         }
   1134     }
   1135     rv = bcm_esw_switch_control_set(unit, bcmSwitchFabricTrunkAutoIncludeDisable,
   1136             auto_include_disable);
   1137     if (BCM_FAILURE(rv) && (BCM_E_UNAVAIL != rv)) {
   1138         return rv;
   1139     }
   1140 #ifdef BCM_TRIDENT_SUPPORT
   1141     if (soc_feature(unit, soc_feature_modport_map_dest_is_port_or_trunk)) {
   1142         if (stk_scache_ptr != NULL) {
   1143             if (recovered_ver >= BCM_WB_VERSION_1_3) { 
   1144                 /* Retrieve modport map profile info from scache */
   1145                 BCM_IF_ERROR_RETURN(bcm_td_stk_trunk_override_hi_reinit(unit,
   1146                             &stk_scache_ptr));
   1147             } else {
   1148                 int higig_trunk_override_hi_scache_size;
   1149                 BCM_IF_ERROR_RETURN
   1150                     (bcm_td_stk_trunk_override_hi_scache_size_get(unit, 
   1151                                 &higig_trunk_override_hi_scache_size));
   1152                 realloc_sz += higig_trunk_override_hi_scache_size;
   1153             }
   1154         }
   1155     }
   1156 #endif /* BCM_TRIDENT_SUPPORT */
   1157 
   1158 #if defined(BCM_TRIUMPH3_SUPPORT)
   1159     if (soc_feature(unit, soc_feature_epc_linkflap_recover)) {
   1160         if (stk_scache_ptr != NULL) {
   1161             if (recovered_ver >= BCM_WB_VERSION_1_4) {
   1162                 BCM_IF_ERROR_RETURN(bcm_td_modport_map_enable_reinit(unit,
   1163                                     &stk_scache_ptr));
   1164             } else {
   1165                 int modport_map_enable_size;
   1166                 BCM_IF_ERROR_RETURN(
   1167                     bcm_td_modport_map_enable_scache_size_get(unit,
   1168                                     &modport_map_enable_size));
   1169                 realloc_sz += modport_map_enable_size;
   1170             }
   1171         }
   1172     }
   1173 #endif /* defined(BCM_TRIUMPH3_SUPPORT) */
   1174 
   1175    /* Version_1_5 -> Version_1_6:
   1176     * uint8 is not enough for src_modid_base_index_bk[unit]->num_ports
   1177     * Store the High-unit8 to scache */
   1178 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_HURRICANE3_SUPPORT)
   1179     if (soc_feature(unit, soc_feature_src_modid_base_index)) {
   1180         int     i;
   1181         uint8   val;
   1182         uint8 *stm_modbase_buf = NULL;
   1183         source_trunk_map_modbase_entry_t *stm_modbase_entry;
   1184         int index_min, index_max, base, num_ports;
   1185 
   1186 #ifdef BCM_TRIDENT2PLUS_SUPPORT
   1187         bcm_module_t my_modid = 0;
   1188         int skip_base_idx = 0;
   1189 #endif
   1190 
   1191         stm_modbase_buf = soc_cm_salloc(unit,
   1192                 SOC_MEM_TABLE_BYTES(unit, SOURCE_TRUNK_MAP_MODBASEm),
   1193                 "SOURCE_TRUNK_MAP_MODBASE buffer");
   1194         if (NULL == stm_modbase_buf) {
   1195             return BCM_E_MEMORY;
   1196         }
   1197 
   1198         index_min = soc_mem_index_min(unit, SOURCE_TRUNK_MAP_MODBASEm);
   1199         index_max = soc_mem_index_max(unit, SOURCE_TRUNK_MAP_MODBASEm);
   1200         rv = soc_mem_read_range(unit, SOURCE_TRUNK_MAP_MODBASEm,
   1201                 MEM_BLOCK_ANY, index_min, index_max, stm_modbase_buf);
   1202         if (SOC_FAILURE(rv)) {
   1203             soc_cm_sfree(unit, stm_modbase_buf);
   1204             return rv;
   1205         }
   1206 
   1207         /* Recover high-8bits of num_ports */
   1208         if (stk_scache_ptr != NULL) {
   1209             if (recovered_ver >= BCM_WB_VERSION_1_6) {
   1210                 for (i = 0; i <= SOC_MODID_MAX(unit); i++) {
   1211                     sal_memcpy(&val, stk_scache_ptr, sizeof(val));
   1212                     src_modid_base_index_bk[unit]->num_ports[i] |= (val << 8);
   1213                     stk_scache_ptr += sizeof(val);
   1214                 }
   1215             } else {
   1216                 for (i = 0; i <= SOC_MODID_MAX(unit); i++) {
   1217                     realloc_sz += sizeof(val);
   1218                 }
   1219             }
   1220         }
   1221 
   1222 #ifdef BCM_TRIDENT2PLUS_SUPPORT
   1223             if (SOC_IS_TD2P_TT2P(unit) || SOC_IS_APACHE(unit)) {
   1224                 BCM_IF_ERROR_RETURN(
   1225                     bcm_esw_stk_my_modid_get(unit, &my_modid));
   1226             }
   1227 #endif
   1228  
   1229         /* Recover src_modid_base_index_bk[unit]->src_mod_port_table_bitmap */
   1230         for (i = index_min; i <= index_max; i++) {
   1231             stm_modbase_entry = soc_mem_table_idx_to_pointer
   1232                 (unit, SOURCE_TRUNK_MAP_MODBASEm,
   1233                  source_trunk_map_modbase_entry_t *, stm_modbase_buf, i);
   1234 
   1235             base = soc_SOURCE_TRUNK_MAP_MODBASEm_field32_get(unit,
   1236                     stm_modbase_entry, BASEf);
   1237             num_ports = src_modid_base_index_bk[unit]->num_ports[i];
   1238 #ifdef BCM_TRIDENT2PLUS_SUPPORT
   1239             if (SOC_IS_TD2P_TT2P(unit) || SOC_IS_APACHE(unit) ||
   1240                 SOC_IS_TRIDENT3X(unit)) {
   1241                 skip_base_idx =
   1242                     src_modid_base_index_bk[unit]->default_base_idx;
   1243                 if (((base < skip_base_idx) &&
   1244                      ((base + num_ports) >= skip_base_idx)) ||
   1245                     ((base >= skip_base_idx) &&
   1246                      (base <= (SOC_PORT_ADDR_MAX(unit) + skip_base_idx)))) {
   1247                     /* If the retrieved base index lies in between the range
   1248                      * of entries blocked for non-configured MOD IDs then
   1249                      * skip learning those. This should only happen in cases
   1250                      * if upgrading from older version which did not have
   1251                      * support for blocking explicit entries for non
   1252                      * configured MOD IDs. It is highly unlikely that this
   1253                      * range i.e base index of 8K-128 will be used for valid
   1254                      * MOD IDs in older version. Although it is possible but
   1255                      * chances are truly very low. If such scenario exists
   1256                      * we will just lose that MOD ID configuration.
   1257                      */
   1258                     continue;
   1259                 } else if ((0==base) &&
   1260                     (recovered_ver<=BCM_WB_VERSION_1_6) && (i!=my_modid)) {
   1261                     /* Older versions shared base index 0 for
   1262                      * non-configured MOD IDs and local Mod ID
   1263                      */
   1264                     continue;
   1265                 }
   1266             } else
   1267 #endif
   1268             {
   1269                 if (0 == base) {
   1270                     continue;
   1271                 }
   1272             }
   1273 
   1274             _BCM_SRC_MOD_PORT_TABLE_USED_SET_RANGE(unit, base, num_ports);
   1275 
   1276             /* Recover source trunk mapping cache and trunk members
   1277              * that have EGRESS_DISABLE flags set.
   1278              */
   1279 #ifdef BCM_HURRICANE3_SUPPORT
   1280             if (SOC_IS_HURRICANE3(unit)) {
   1281                 rv = _bcm_xgs3_trunk_mod_port_map_reinit(unit, i, base,
   1282                         num_ports);
   1283             } else
   1284 #endif /* BCM_HURRICANE3_SUPPORT */
   1285             {
   1286 #ifdef BCM_TRIDENT_SUPPORT
   1287                 rv = _bcm_trident_trunk_mod_port_map_reinit(unit, i, base,
   1288                         num_ports);
   1289 #endif /* BCM_TRIDENT_SUPPORT */
   1290             }
   1291             if (SOC_FAILURE(rv)) {
   1292                 soc_cm_sfree(unit, stm_modbase_buf);
   1293                 return rv;
   1294             }
   1295         }
   1296 
   1297         soc_cm_sfree(unit, stm_modbase_buf);
   1298     }
   1299 #endif /* BCM_TRIDENT_SUPPORT || BCM_HURRICANE3_SUPPORT */
   1300 
   1301    /* Version_1_7 -> Version_1_8*/
   1302 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_HELIX4_SUPPORT)
   1303     if (soc_feature(unit, soc_feature_epc_linkflap_recover)) {
   1304         if (stk_scache_ptr != NULL) {
   1305             if (recovered_ver >= BCM_WB_VERSION_1_8) {
   1306                 BCM_IF_ERROR_RETURN(bcm_td_linkflap_trunk_map_reinit(unit,
   1307                                     &stk_scache_ptr));
   1308             } else {
   1309                 int linkflap_trunk_map_size;
   1310                 BCM_IF_ERROR_RETURN(
   1311                     bcm_td_linkflap_trunk_map_scache_size_get(unit,
   1312                                     &linkflap_trunk_map_size));
   1313                 realloc_sz += linkflap_trunk_map_size;
   1314             }
   1315         }
   1316     }
   1317 #endif /* defined(BCM_TRIUMPH3_SUPPORT) */
   1318 
   1319     /* Version_1_8 -> Version_1_9:
   1320      * module_id_type_list & multi_nexthop_module_id_list are  introduced by Version_1_9
   1321      * Recover src_modid_base_index_bk[unit]->module_id_type_list and
   1322      * src_modid_base_index_bk[unit]->multi_nexthop_module_id_list from scache. */
   1323 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   1324     if (soc_feature(unit, soc_feature_multi_next_hops_on_port)) {
   1325         int i, val;
   1326         soc_info_t *si = &SOC_INFO(unit);
   1327 
   1328         if (stk_scache_ptr != NULL) {
   1329             if (recovered_ver >= BCM_WB_VERSION_1_9) {
   1330                 for (i = 0; i < si->num_modules; i++) {
   1331                     sal_memcpy(&val, stk_scache_ptr, sizeof(val));
   1332                     src_modid_base_index_bk[unit]->module_id_type_list[i] = val;
   1333                     stk_scache_ptr += sizeof(val);
   1334                 }
   1335 
   1336                 for (i = 0; i < si->num_modules; i++) {
   1337                     sal_memcpy(&val, stk_scache_ptr, sizeof(val));
   1338                     src_modid_base_index_bk[unit]->multi_nexthop_module_id_list[i] = val;
   1339                     stk_scache_ptr += sizeof(val);
   1340                 }
   1341             } else {
   1342                 for (i = 0; i <= si->num_modules; i++) {
   1343                     realloc_sz += sizeof(val) * 2;
   1344                 }
   1345             }
   1346         }
   1347     }
   1348 #endif
   1349 
   1350     if (realloc_sz > 0) {
   1351         BCM_IF_ERROR_RETURN(
   1352             soc_scache_realloc(unit, scache_handle, realloc_sz));
   1353     }
   1354 
   1355     return BCM_E_NONE;
   1356 }
   1357 #endif /* BCM_WARM_BOOT_SUPPORT */
   1358 
   1359 /*
   1360  * Function:
   1361  *      _bcm_esw_stk_prepare
   1362  * Purpose:
   1363  *      prepare initialize device stacking
   1364  *      no need to prepare _src_modid_base_index_bk
   1365  *      as it is already initialized during common init
   1366  * Parameters:
   1367  *      unit  - (IN) BCM device number.
   1368  * Returns:
   1369  *      BCM_E_XXX
   1370  */
   1371 
   1372 STATIC int
   1373 _bcm_esw_stk_init_prepare(int unit)
   1374 {
   1375     if (stack_mutex != NULL) {
   1376         sal_mutex_destroy(stack_mutex);
   1377         stack_mutex = NULL;
   1378     }
   1379 
   1380     BCM_IF_ERROR_RETURN(bcm_esw_stk_modmap_unregister(unit));
   1381 
   1382 #if defined(LOCAL_MODMAP_SUPPORT)
   1383     if (soc_feature(unit, soc_feature_modmap)) {
   1384         SOC_IF_ERROR_RETURN(_bcm_esw_modmap_detach(unit));
   1385     }
   1386 #endif /* MODMAP_SUPPORT */
   1387 
   1388 #if defined(BCM_TRX_SUPPORT)
   1389     if (modport_profile[unit]) {
   1390         soc_profile_mem_destroy(unit, modport_profile[unit]);
   1391         sal_free(modport_profile[unit]);
   1392         modport_profile[unit] = NULL;
   1393     }
   1394 
   1395     if (soc_feature(unit, soc_feature_modport_map_dest_is_hg_port_bitmap)) {
   1396         BCM_IF_ERROR_RETURN(bcmi_trx_modport_map_detach(unit));
   1397     }
   1398 #endif /* BCM_TRX_SUPPORT */
   1399 
   1400 #if defined(BCM_TRIDENT_SUPPORT)
   1401     if (soc_feature(unit, soc_feature_modport_map_dest_is_port_or_trunk)) {
   1402         BCM_IF_ERROR_RETURN(bcm_td_modport_map_detach(unit));
   1403     }
   1404 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_HELIX4_SUPPORT)
   1405     if (soc_feature(unit, soc_feature_epc_linkflap_recover)) {
   1406         bcm_esw_linkscan_unregister(unit, _bcm_stk_modport_map_linkscan_handler);
   1407     }
   1408 #endif
   1409 #endif /* BCM_TRIDENT_SUPPORT */
   1410     return BCM_E_NONE;
   1411 }
   1412 
   1413 
   1414 /*
   1415  * Function:
   1416  *      bcm_stk_init
   1417  * Purpose:
   1418  *      Initialize device stacking
   1419  * Parameters:
   1420  *      unit  - SOC unit #
   1421  * Returns:
   1422  *      BCM_E_XXX
   1423  */
   1424 
   1425 int
   1426 bcm_esw_stk_init(int unit)
   1427 {
   1428     int rv;
   1429 #ifdef BCM_WARM_BOOT_SUPPORT
   1430     soc_scache_handle_t scache_handle;
   1431     uint32              stk_scache_size;
   1432     uint8               *stk_scache_ptr;
   1433 #endif /* BCM_WARM_BOOT_SUPPORT */
   1434 
   1435     BCM_STK_API_TH3_SUPPORT_CHECK(unit);
   1436 
   1437     LOG_VERBOSE(BSL_LS_BCM_STK,
   1438                 (BSL_META_U(unit,
   1439                             "STK %d: Init\n"),
   1440                  unit));
   1441 
   1442     if (SOC_IS_SHADOW(unit)) {
   1443         return BCM_E_UNAVAIL;
   1444     }
   1445 
   1446 
   1447 #ifdef BCM_WARM_BOOT_SUPPORT
   1448     /* Warm boot level 2 cache size */
   1449     /* Stack ports current, inactive, previous */
   1450     stk_scache_size = sizeof(soc_pbmp_t) * 3;
   1451 
   1452 #if defined(LOCAL_MODMAP_SUPPORT)
   1453     /* Modmap */
   1454     if (soc_feature(unit, soc_feature_modmap)) {
   1455         int max_group;
   1456 
   1457         BCM_IF_ERROR_RETURN
   1458         (bcm_esw_stk_port_modmap_group_max_get(unit, &max_group));
   1459         
   1460         /* Max values for l_modid, thresh_d, fmod0 fits in uint8 */
   1461         stk_scache_size += (sizeof(uint8) * SOC_MAX_NUM_PORTS);  /* l_modid  */
   1462         stk_scache_size += (sizeof(uint8) * _NUM_SL_MOD);        /* thresh_d */
   1463         stk_scache_size += (sizeof(uint8) * (max_group + 1));    /* fmod0    */
   1464     }
   1465 #endif /* LOCAL_MODMAP_SUPPORT */
   1466 
   1467 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_HURRICANE3_SUPPORT)
   1468     if (soc_feature(unit, soc_feature_src_modid_base_index)) {
   1469         /* Allocate space for src_modid_base_index_bk[unit]->num_ports array */
   1470         stk_scache_size += (sizeof(uint8) * (SOC_MODID_MAX(unit) + 1));
   1471         if(soc_feature(unit, soc_feature_hgproxy_subtag_coe)) {
   1472             stk_scache_size += (sizeof(int) * (SOC_MODID_MAX(unit) + 1));
   1473         }
   1474 
   1475         /* Version_1_4 -> Version_1_5:
   1476                * module_id_range is introduced by Version_1_5
   1477                * Allocate space for src_modid_base_index_bk[unit]->module_id_range */
   1478         if(soc_feature(unit, soc_feature_multi_next_hops_on_port)) {
   1479             stk_scache_size += sizeof(module_id_mask_t);
   1480         }
   1481     }
   1482 #endif /* BCM_TRIDENT_SUPPORT || BCM_HURRICANE3_SUPPORT */
   1483 #if defined(BCM_TRIDENT_SUPPORT)
   1484     if (soc_feature(unit, soc_feature_modport_map_dest_is_port_or_trunk)) {
   1485         int modport_map_scache_size;
   1486         BCM_IF_ERROR_RETURN
   1487             (bcm_td_modport_map_scache_size_get(unit, &modport_map_scache_size));
   1488         stk_scache_size += modport_map_scache_size;
   1489     }
   1490 #endif /* BCM_TRIDENT_SUPPORT */
   1491 
   1492 #if defined(BCM_TRX_SUPPORT)
   1493     if (soc_feature(unit, soc_feature_modport_map_dest_is_hg_port_bitmap)) {
   1494         int modport_map_scache_size;
   1495         BCM_IF_ERROR_RETURN(
   1496             bcmi_trx_modport_map_scache_size_get(unit, SOC_MAX_NUM_PORTS,
   1497                                                  &modport_map_scache_size));
   1498         stk_scache_size += modport_map_scache_size;
   1499     }
   1500 #endif /* BCM_TRX_SUPPORT */
   1501 
   1502     /* Allocate space for the bcmSwitchFabricTrunkAutoIncludeDisable value */
   1503     stk_scache_size += sizeof(int);
   1504 
   1505 #if defined(BCM_TRIDENT_SUPPORT)
   1506     if (soc_feature(unit, soc_feature_modport_map_dest_is_port_or_trunk)) {
   1507         int higig_trunk_override_hi_scache_size;
   1508         BCM_IF_ERROR_RETURN
   1509             (bcm_td_stk_trunk_override_hi_scache_size_get(unit, 
   1510                                         &higig_trunk_override_hi_scache_size));
   1511         stk_scache_size += higig_trunk_override_hi_scache_size;
   1512     }
   1513 #endif /* BCM_TRIDENT_SUPPORT */
   1514 
   1515 #if defined(BCM_TRIUMPH3_SUPPORT)
   1516     if (soc_feature(unit, soc_feature_epc_linkflap_recover)) {
   1517         int modport_map_enable_size;
   1518         BCM_IF_ERROR_RETURN(
   1519             bcm_td_modport_map_enable_scache_size_get(unit,
   1520                             &modport_map_enable_size));
   1521         stk_scache_size += modport_map_enable_size;
   1522     }
   1523 #endif /* defined(BCM_TRIUMPH3_SUPPORT) */
   1524 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_HURRICANE3_SUPPORT)
   1525     if (soc_feature(unit, soc_feature_src_modid_base_index)) {
   1526         /* Version_1_5 -> Version_1_6:
   1527          * Allocate space for hi 8bits of src_modid_base_index_bk[unit]->num_ports array */
   1528         stk_scache_size += (sizeof(uint8) * (SOC_MODID_MAX(unit) + 1));
   1529     }
   1530 #endif /* BCM_TRIDENT_SUPPORT || BCM_HURRICANE3_SUPPORT */
   1531 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_HELIX4_SUPPORT)
   1532     if (soc_feature(unit, soc_feature_epc_linkflap_recover)) {
   1533         int linkflap_trunk_map_size;
   1534         BCM_IF_ERROR_RETURN(
   1535             bcm_td_linkflap_trunk_map_scache_size_get(unit,
   1536                             &linkflap_trunk_map_size));
   1537         stk_scache_size += linkflap_trunk_map_size;
   1538     }
   1539 #endif /* defined(BCM_TRIUMPH3_SUPPORT) */
   1540 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   1541     /* Version_1_8 -> Version_1_9:
   1542      * module_id_type_list & multi_nexthop_module_id_list are introduced by Version_1_9
   1543      * Allocate space for src_modid_base_index_bk[unit]->module_id_type_list and
   1544      * src_modid_base_index_bk[unit]->multi_nexthop_module_id_list. */
   1545     if (soc_feature(unit, soc_feature_multi_next_hops_on_port)) {
   1546         stk_scache_size += (sizeof(int) * (SOC_MODID_MAX(unit) + 1)) * 2;
   1547     }
   1548 #endif
   1549 
   1550     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_STACK, 0);
   1551     rv = _bcm_esw_scache_ptr_get(unit, scache_handle,
   1552                                  (0 == SOC_WARM_BOOT(unit)),
   1553                                  stk_scache_size, &stk_scache_ptr, 
   1554                                  BCM_WB_DEFAULT_VERSION, NULL);
   1555     if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) {
   1556         return rv;
   1557     }
   1558 #endif /* BCM_WARM_BOOT_SUPPORT */
   1559     rv = _bcm_esw_stk_init_prepare(unit);
   1560     BCM_IF_ERROR_RETURN(rv);
   1561 
   1562     if (!SOC_WARM_BOOT(unit) && !SOC_IS_RCPU_ONLY(unit)) {
   1563         if (soc_feature(unit, soc_feature_modport_map_dest_is_port_or_trunk)) {
   1564             SOC_IF_ERROR_RETURN
   1565                 (soc_mem_clear(unit, MODPORT_MAP_SWm, MEM_BLOCK_ALL, 0));
   1566             SOC_IF_ERROR_RETURN
   1567                 (soc_mem_clear(unit, MODPORT_MAP_MIRRORm, MEM_BLOCK_ALL, 0));
   1568         } else if (SOC_IS_TR_VL(unit) && SOC_MEM_IS_VALID(unit, MODPORT_MAPm)) {
   1569             SOC_IF_ERROR_RETURN
   1570                 (soc_mem_clear(unit, MODPORT_MAPm, MEM_BLOCK_ALL, 0));
   1571         } else {
   1572             BCM_IF_ERROR_RETURN(bcm_esw_stk_modport_clear_all(unit));
   1573         }
   1574     }
   1575 
   1576     rv = _bcm_esw_stk_init();
   1577     if (BCM_FAILURE(rv)) {
   1578         _bcm_esw_stk_detach(unit);
   1579         return (rv);
   1580     }
   1581 
   1582 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_HELIX4_SUPPORT)
   1583     if (soc_feature(unit, soc_feature_epc_linkflap_recover)) {
   1584         bcm_port_t p;
   1585         PBMP_PORT_ITER(unit, p) {
   1586             _BCM_PORT_TRUNK_LINKFLAP_CLEAR(unit, p);
   1587         }
   1588         BCM_IF_ERROR_RETURN(
   1589             bcm_esw_linkscan_register(unit, _bcm_stk_modport_map_linkscan_handler));
   1590     }
   1591 #endif
   1592 
   1593     SOC_DEFAULT_DMA_SRCPORT_SET(unit, CMIC_PORT(unit));
   1594 
   1595     if (!SOC_WARM_BOOT(unit) && !SOC_IS_RCPU_ONLY(unit)) {
   1596         /* Blank slate for stack info */
   1597         BCM_PBMP_CLEAR(SOC_PBMP_STACK_CURRENT(unit));
   1598         BCM_PBMP_CLEAR(SOC_PBMP_STACK_INACTIVE(unit));
   1599         BCM_PBMP_CLEAR(SOC_PBMP_STACK_PREVIOUS(unit));
   1600 
   1601         switch (BCM_CHIP_FAMILY(unit)) {
   1602 
   1603         case BCM_FAMILY_HERCULES:
   1604             rv = _bcm_xgs_fabric_stk_init(unit);
   1605             break;
   1606         case BCM_FAMILY_HUMV:
   1607         case BCM_FAMILY_CONQUEROR:
   1608         case BCM_FAMILY_TITAN:
   1609             rv =  _bcm_xgs3_ignore_my_modid(unit);
   1610             if (BCM_FAILURE(rv)) {
   1611                 break;
   1612             }
   1613             /* fall through */
   1614         case BCM_FAMILY_BRADLEY:
   1615         case BCM_FAMILY_FIREBOLT:
   1616         case BCM_FAMILY_TRIUMPH:
   1617         case BCM_FAMILY_SCORPION:
   1618         case BCM_FAMILY_TRIUMPH2:
   1619         case BCM_FAMILY_TRIDENT:
   1620         case BCM_FAMILY_KATANA:
   1621             rv = _bcm_xgs3_stk_init(unit);
   1622             break;
   1623         default:
   1624             rv = BCM_E_UNAVAIL;
   1625             break;
   1626             
   1627         }
   1628 
   1629         if (BCM_FAILURE(rv)) {
   1630             _bcm_esw_stk_detach(unit);
   1631             return (rv);
   1632         }
   1633     }
   1634 
   1635 #ifdef BCM_WARM_BOOT_SUPPORT
   1636     if (SOC_WARM_BOOT(unit)) {
   1637         rv = _bcm_stk_reinit(unit);
   1638         if (BCM_FAILURE(rv)) {
   1639             _bcm_esw_stk_detach(unit);
   1640             return (rv);
   1641         }
   1642     }
   1643 #endif /* BCM_WARM_BOOT_SUPPORT */
   1644 
   1645     return rv;
   1646 }
   1647 
   1648 /****************************************************************
   1649  *
   1650  * Per device stacking initialization
   1651  * Clears stacking configuration
   1652  */
   1653 
   1654 STATIC int
   1655 _bcm_xgs_fabric_stk_init(int unit)
   1656 {
   1657 #if defined(BCM_HERCULES_SUPPORT) ||  defined(BCM_BRADLEY_SUPPORT)
   1658     int port;
   1659 
   1660     PBMP_HG_ITER(unit, port) {
   1661         BCM_IF_ERROR_RETURN
   1662             (bcm_esw_port_stp_set(unit, port, BCM_STG_STP_FORWARD));
   1663     }
   1664 
   1665 #if defined(LOCAL_MODMAP_SUPPORT)
   1666     if (soc_feature(unit, soc_feature_modmap)) {
   1667         BCM_IF_ERROR_RETURN(_bcm_esw_modmap_init(unit));
   1668     }
   1669 #endif /* MODMAP_SUPPORT */
   1670 #endif
   1671 
   1672     return BCM_E_NONE;
   1673 }
   1674 
   1675 
   1676 STATIC int
   1677 _bcm_xgs3_ignore_my_modid(int unit)
   1678 {
   1679     int rv = BCM_E_UNAVAIL;
   1680 #if defined(BCM_BRADLEY_SUPPORT)
   1681 #if defined(BCM_SCORPION_SUPPORT) || defined(BCM_TRIDENT_SUPPORT)
   1682     if (SOC_IS_SC_CQ(unit) || SOC_IS_TD_TT(unit)) {
   1683         uint64 config, oconfig;
   1684 
   1685         SOC_IF_ERROR_RETURN(READ_ING_CONFIG_64r(unit, &config));
   1686         oconfig = config;
   1687         soc_reg64_field32_set(unit, ING_CONFIG_64r, &config,
   1688                             IGNORE_MY_MODIDf, 1);
   1689         if (COMPILER_64_NE(config, oconfig)) {
   1690             SOC_IF_ERROR_RETURN(WRITE_ING_CONFIG_64r(unit, config));
   1691         }
   1692 
   1693         rv = BCM_E_NONE;
   1694     } else
   1695 #endif
   1696     {
   1697         uint32 config, oconfig;
   1698 
   1699         SOC_IF_ERROR_RETURN(READ_ING_CONFIGr(unit, &config));
   1700         oconfig = config;
   1701         soc_reg_field_set(unit, ING_CONFIGr, &config,
   1702                           IGNORE_MY_MODIDf, 1);
   1703         if (config != oconfig) {
   1704             SOC_IF_ERROR_RETURN(WRITE_ING_CONFIGr(unit, config));
   1705         }
   1706 
   1707         rv = BCM_E_NONE;
   1708     }
   1709 #endif
   1710     return rv;
   1711 }
   1712 
   1713 STATIC int
   1714 _bcm_xgs3_stk_init(int unit)
   1715 {
   1716 #if defined(BCM_XGS3_SWITCH_SUPPORT)
   1717     int pbm_len;
   1718     bcm_port_t port;
   1719     uint32 cpu_pbm, obm_reg;
   1720     uint64 obm_reg_64;
   1721     soc_pbmp_t pbmp;
   1722 
   1723     /* Set modid to 0 */
   1724     if (!SOC_WARM_BOOT(unit) && !SOC_IS_RCPU_ONLY(unit)) {
   1725         BCM_IF_ERROR_RETURN(bcm_esw_stk_modid_set(unit, 0));
   1726     }
   1727 
   1728     if (SOC_IS_TD_TT(unit) || SOC_IS_KATANAX(unit) || 
   1729         SOC_IS_TRIUMPH3(unit)) {
   1730         SOC_PBMP_CLEAR(pbmp);
   1731         SOC_PBMP_PORT_SET(pbmp, CMIC_PORT(unit));
   1732     } else if (SOC_IS_TR_VL(unit) && !SOC_IS_TRIUMPH2(unit)
   1733         && !SOC_IS_APOLLO(unit) && !SOC_IS_VALKYRIE2(unit)) {
   1734         SOC_IF_ERROR_RETURN
   1735             (soc_xgs3_port_to_higig_bitmap(unit, CMIC_PORT(unit),
   1736                                            &cpu_pbm));
   1737     } else if (CMIC_PORT(unit)) {
   1738         pbm_len = soc_reg_field_length(unit, ICONTROL_OPCODE_BITMAPr, BITMAPf);
   1739         if (pbm_len >= 1) {
   1740             cpu_pbm = 1 << (pbm_len - 1);
   1741         } else {
   1742             cpu_pbm = 1;
   1743         }
   1744     } else {
   1745         cpu_pbm = 1;
   1746     }
   1747 
   1748     PBMP_ST_ITER(unit, port) {
   1749         /* HG ports to forwarding */
   1750         BCM_IF_ERROR_RETURN(bcm_esw_port_stp_set(unit, port,
   1751                                                  BCM_STG_STP_FORWARD));
   1752 
   1753         /* Set HG ingress CPU Opcode map to the CPU */
   1754         if (SOC_IS_TD_TT(unit) || SOC_IS_KATANAX(unit) || 
   1755             SOC_IS_TRIUMPH3(unit)) {
   1756             icontrol_opcode_bitmap_entry_t entry;
   1757             SOC_IF_ERROR_RETURN
   1758                 (READ_ICONTROL_OPCODE_BITMAPm(unit, MEM_BLOCK_ANY, port,
   1759                                               &entry));
   1760             soc_mem_pbmp_field_set(unit, ICONTROL_OPCODE_BITMAPm, &entry,
   1761                                    BITMAPf, &pbmp);
   1762             SOC_IF_ERROR_RETURN
   1763                 (WRITE_ICONTROL_OPCODE_BITMAPm(unit, MEM_BLOCK_ANY, port,
   1764                                                &entry));
   1765         } else if (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) || 
   1766             SOC_IS_VALKYRIE2(unit)) {
   1767             uint64 cpu_pbm_64;
   1768             COMPILER_64_ZERO(cpu_pbm_64);
   1769             COMPILER_64_SET(cpu_pbm_64, 0, cpu_pbm);
   1770             SOC_IF_ERROR_RETURN(READ_ICONTROL_OPCODE_BITMAP_64r(unit, port,
   1771                                                              &obm_reg_64));
   1772             soc_reg64_field_set(unit, ICONTROL_OPCODE_BITMAP_64r, &obm_reg_64,
   1773                               BITMAPf, cpu_pbm_64);
   1774             SOC_IF_ERROR_RETURN(WRITE_ICONTROL_OPCODE_BITMAP_64r(unit, port,
   1775                                                               obm_reg_64));
   1776         } else if (SOC_IS_GREYHOUND2(unit)) {
   1777             uint64 cpu_pbm_64;
   1778             COMPILER_64_ZERO(cpu_pbm_64);
   1779             COMPILER_64_SET(cpu_pbm_64, 0, cpu_pbm);
   1780             SOC_IF_ERROR_RETURN(READ_ICONTROL_OPCODE_BITMAP_LOr(unit, port,
   1781                                 &obm_reg_64));
   1782             soc_reg64_field_set(unit, ICONTROL_OPCODE_BITMAP_LOr, &obm_reg_64,
   1783                                 BITMAPf, cpu_pbm_64);
   1784             SOC_IF_ERROR_RETURN(WRITE_ICONTROL_OPCODE_BITMAP_LOr(unit, port,
   1785                                 obm_reg_64));
   1786 #ifdef BCM_SHADOW_SUPPORT
   1787         } else if (SOC_IS_SHADOW(unit)) {
   1788             SOC_IF_ERROR_RETURN(READ_ICONTROL_OPCODEr(unit, port, &obm_reg));
   1789             soc_reg_field_set(unit, ICONTROL_OPCODEr, &obm_reg, PORT_NUMf, 0);
   1790             SOC_IF_ERROR_RETURN(WRITE_ICONTROL_OPCODEr(unit, port, obm_reg));
   1791 #endif
   1792         } else {
   1793             SOC_IF_ERROR_RETURN(READ_ICONTROL_OPCODE_BITMAPr(unit, port,
   1794                                                              &obm_reg));
   1795             soc_reg_field_set(unit, ICONTROL_OPCODE_BITMAPr, &obm_reg,
   1796                               BITMAPf, cpu_pbm);
   1797             SOC_IF_ERROR_RETURN(WRITE_ICONTROL_OPCODE_BITMAPr(unit, port,
   1798                                                               obm_reg));
   1799         }
   1800     }
   1801 #if defined(LOCAL_MODMAP_SUPPORT)
   1802     if (soc_feature(unit, soc_feature_modmap)) {
   1803         SOC_IF_ERROR_RETURN(_bcm_esw_modmap_init(unit));
   1804     }
   1805 #endif
   1806 
   1807 #ifdef BCM_TRIDENT_SUPPORT
   1808     if (soc_feature(unit, soc_feature_modport_map_dest_is_port_or_trunk)) {
   1809         BCM_IF_ERROR_RETURN(bcm_td_modport_map_init(unit));
   1810     }
   1811 #endif
   1812 
   1813 #ifdef BCM_TRX_SUPPORT
   1814     if (soc_feature(unit, soc_feature_modport_map_dest_is_hg_port_bitmap)) {
   1815         BCM_IF_ERROR_RETURN(bcmi_trx_modport_map_init(unit));
   1816     }
   1817 #endif /* BCM_TRX_SUPPORT */
   1818 
   1819 #ifdef BCM_TRIUMPH3_SUPPORT
   1820     /* Setting ESM eligibility is done here because
   1821      * the ESM offset and priority fields are located
   1822      * in SOURCE_TRUNK_MAP table, and the index to the
   1823      * SOURCE_TRUNK_MAP table can be computed only after
   1824      * my_modid is set.
   1825      */
   1826     if (soc_feature(unit, soc_feature_etu_support)) {
   1827         pbmp_t esm_eligible_pbmp, default_pbmp;
   1828         bcm_port_t esm_port;
   1829 
   1830         BCM_PBMP_ASSIGN(default_pbmp, PBMP_E_ALL(unit));
   1831         esm_eligible_pbmp = soc_property_get_pbmp_default(unit,
   1832                 spn_PBMP_ESM_ELIGIBLE, default_pbmp);
   1833         BCM_PBMP_ITER(esm_eligible_pbmp, esm_port) {
   1834             BCM_IF_ERROR_RETURN(bcm_esw_port_control_set(unit,
   1835                         esm_port, bcmPortControlEsmEligibility, TRUE));
   1836         }
   1837     }
   1838 #endif /* BCM_TRIUMPH3_SUPPORT */
   1839 
   1840 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   1841     if ((SOC_IS_TD2P_TT2P(unit) || SOC_IS_TRIDENT3X(unit) || SOC_IS_APACHE(unit)) &&
   1842         soc_feature(unit, soc_feature_src_modid_base_index)) {
   1843         /* If the default base index and local modid's base index is
   1844          * different then replicate the configuration of local MODID's
   1845          * base index to default base index. This is needed as the
   1846          * corresponding entries in the src_mod_port_mems has to be
   1847          * configured to some default correct working values. At this
   1848          * point in code, all configuration for local MODID has been
   1849          * done and instead of creating another set of default values
   1850          * we can just use the local MODID's configuration to beginwith.
   1851          */
   1852         int i;
   1853         int rv;
   1854         int entry_size;
   1855         void *entry_buffer;
   1856         int src_base_index;
   1857         int local_modid = SOC_BASE_MODID(unit);
   1858         int entry_cnt = BCM_STK_TD2P_NUM_LPORTS;
   1859         source_trunk_map_modbase_entry_t stm_modbase_entry;
   1860         int dst_base_index = src_modid_base_index_bk[unit]->default_base_idx;
   1861 
   1862         if (SOC_MODID_ADDRESSABLE(unit, local_modid)) {
   1863             /* Retrieve the local MODID's base index from memory */
   1864             SOC_IF_ERROR_RETURN(
   1865                 READ_SOURCE_TRUNK_MAP_MODBASEm(
   1866                     unit, MEM_BLOCK_ANY, local_modid, &stm_modbase_entry));
   1867 
   1868             src_base_index =
   1869                 soc_SOURCE_TRUNK_MAP_MODBASEm_field32_get(
   1870                             unit, &stm_modbase_entry, BASEf);
   1871         } else {
   1872             /* If local MODID is not accessible use base index 0 */
   1873             src_base_index = 0;
   1874         }
   1875 #if defined(BCM_APACHE_SUPPORT)
   1876         if (SOC_IS_APACHE(unit)) {
   1877             entry_cnt = BCM_STK_APACHE_NUM_LPORTS;
   1878         }
   1879 #endif
   1880 #if defined(BCM_MONTEREY_SUPPORT)
   1881         if (SOC_IS_MONTEREY(unit)) {
   1882             entry_cnt = BCM_STK_MONTEREY_NUM_LPORTS;
   1883         }
   1884 #endif
   1885 #if defined(BCM_TRIDENT3_SUPPORT)
   1886         if (SOC_IS_TRIDENT3X(unit)) {
   1887             if (SOC_IS_TRIDENT3(unit)) {
   1888                 entry_cnt = TRIDENT3_DEV_PORTS_PER_DEV;
   1889             }
   1890 
   1891 #if defined(BCM_MAVERICK2_SUPPORT)
   1892             if (SOC_IS_MAVERICK2(unit)) {
   1893                 entry_cnt = MAVERICK2_DEV_PORTS_PER_DEV;
   1894             }
   1895 #endif
   1896 
   1897 #if defined(BCM_HELIX5_SUPPORT)
   1898             if (SOC_IS_HELIX5(unit)) {
   1899                 entry_cnt = HELIX5_DEV_PORTS_PER_DEV;
   1900             }
   1901 #endif
   1902         }
   1903 #endif
   1904         /* Only replicate if base index differ */
   1905         if (src_base_index != dst_base_index) {
   1906 
   1907             for (i = 0; i < COUNTOF(src_mod_port_mems); i++) {
   1908                 if(!soc_mem_is_valid(unit, src_mod_port_mems[i])) {
   1909                     continue;
   1910                 }
   1911                 /* Get a buffer to hold the data worth of mutliple entries */
   1912                 entry_size =
   1913                    WORDS2BYTES(soc_mem_entry_words(unit, src_mod_port_mems[i]));
   1914                 entry_buffer = soc_cm_salloc(unit,
   1915                     (entry_size * entry_cnt), "mod table entry block");
   1916                 if (!entry_buffer) {
   1917                     return BCM_E_MEMORY;
   1918                 }
   1919 
   1920                 /* Clear the buffer to begin-with */
   1921                 sal_memset(entry_buffer, 0x0, entry_size * entry_cnt);
   1922 
   1923                 /* Read the entire range of entries starting from local MODID's
   1924                  * base index till the number of ports supported in one shot
   1925                  */
   1926                 rv = soc_mem_read_range(unit,
   1927                                         src_mod_port_mems[i],
   1928                                         MEM_BLOCK_ANY,
   1929                                         src_base_index,
   1930                                         src_base_index + entry_cnt - 1,
   1931                                         entry_buffer);
   1932 
   1933                 /* Write the entire range at default base index at once */
   1934                 if (BCM_SUCCESS(rv)) {
   1935                     rv = soc_mem_write_range(unit,
   1936                                             src_mod_port_mems[i],
   1937                                             MEM_BLOCK_ANY,
   1938                                             dst_base_index,
   1939                                             dst_base_index + entry_cnt - 1,
   1940                                             entry_buffer);
   1941                 }
   1942 
   1943                 /* Deallocate the buffer as it is not needed now */
   1944                 soc_cm_sfree(unit, entry_buffer);
   1945 
   1946                 /* Bail out on error */
   1947                 SOC_IF_ERROR_RETURN(rv);
   1948             }
   1949         }
   1950     }
   1951 #endif /* BCM_TRIDENT2PLUS_SUPPORT */
   1952 
   1953 #endif /* BCM_XGS3_SWITCH_SUPPORT */
   1954 
   1955     return BCM_E_NONE;
   1956 }
   1957 
   1958 /****************************************************************
   1959  *
   1960  * Stack port set calls:
   1961  *
   1962  *    Callback into BCM layer for notification
   1963  *    Callback to application for notification
   1964  */
   1965 
   1966 
   1967 /* Linked list of callback registrants */
   1968 typedef struct _esw_stk_callback_s {
   1969     struct _esw_stk_callback_s *next;
   1970     bcm_stk_cb_f fn;
   1971     void *cookie;
   1972 } _esw_stk_callback_t;
   1973 
   1974 /*
   1975  * Function:
   1976  *      bcm_esw_stk_update_callback_register/unregister
   1977  * Purpose:
   1978  *      (Un)register an application function for calbacks from stack port set
   1979  * Parameters:
   1980  *      unit   - ignored
   1981  *      cb     - callback function
   1982  *      cookie - anonymous data passed to callback
   1983  * Returns:
   1984  *      BCM_E_XXX
   1985  * Notes:
   1986  *      Will only register a given (callback, cookie) pair once.
   1987  *      On unregister, both the callback and cookie must match.
   1988  *      Callbacks are made in the order they are registered.  Enqueue
   1989  *      new registrants at the end of the linked list.
   1990  */
   1991 
   1992 static _esw_stk_callback_t *_esw_stk_cb;
   1993 static _esw_stk_callback_t *_esw_stk_cb_tail;
   1994 
   1995 /* Register stack update callback at end of list */
   1996 
   1997 int
   1998 bcm_esw_stk_update_callback_register(int unit, bcm_stk_cb_f cb, void *cookie)
   1999 {
   2000     _esw_stk_callback_t *node;
   2001     int rv = BCM_E_NONE;
   2002 
   2003     COMPILER_REFERENCE(unit);
   2004 
   2005     BCM_STK_API_TH3_SUPPORT_CHECK(unit);
   2006 
   2007     BCM_IF_ERROR_RETURN(_bcm_esw_stk_init());
   2008 
   2009     ESW_STK_LOCK;
   2010     /* See if already present */
   2011     node = _esw_stk_cb;
   2012     while (node != NULL) {
   2013         if (node->fn == cb && node->cookie == cookie) {
   2014             break; /* Found it */
   2015         }
   2016         node = node->next;
   2017     }
   2018 
   2019     if (node == NULL) { /* Not there yet */
   2020         node = sal_alloc(sizeof(*node), "bcm_esw_stk_cb");
   2021         if (node != NULL) {
   2022             node->fn = cb;
   2023             node->cookie = cookie;
   2024             node->next = NULL;
   2025 
   2026             /* Enqueue at tail */
   2027             if (_esw_stk_cb_tail == NULL) {
   2028                 _esw_stk_cb = node;
   2029             } else {
   2030                 _esw_stk_cb_tail->next = node;
   2031             }
   2032             _esw_stk_cb_tail = node;
   2033         } else {
   2034             rv = BCM_E_MEMORY;
   2035         }
   2036     }
   2037     ESW_STK_UNLOCK;
   2038 
   2039     return rv;
   2040 }
   2041 
   2042 int
   2043 bcm_esw_stk_update_callback_unregister(int unit, bcm_stk_cb_f cb, void *cookie)
   2044 {
   2045     _esw_stk_callback_t *node;
   2046     _esw_stk_callback_t *prev;
   2047     int                 rv;
   2048 
   2049     COMPILER_REFERENCE(unit);
   2050 
   2051     BCM_STK_API_TH3_SUPPORT_CHECK(unit);
   2052 
   2053     BCM_IF_ERROR_RETURN(_bcm_esw_stk_init());
   2054 
   2055     ESW_STK_LOCK;
   2056     node = _esw_stk_cb;
   2057     prev = NULL;
   2058 
   2059     /* Scan list for match of both function and cookie */
   2060     while (node != NULL) {
   2061         if ((node->fn == cb) && (node->cookie == cookie)) {
   2062             break; /* Found it */
   2063         }
   2064         prev = node;
   2065         node = node->next;
   2066     }
   2067 
   2068     if (node != NULL) { /* Found */
   2069         if (prev == NULL) { /* First on list */
   2070             _esw_stk_cb = node->next;
   2071         } else { /* Update previous */
   2072             prev->next = node->next;
   2073         }
   2074         if (_esw_stk_cb_tail == node) { /* Was last on list */
   2075             _esw_stk_cb_tail = prev;
   2076         }
   2077         rv = BCM_E_NONE;
   2078     } else {
   2079         rv = BCM_E_NOT_FOUND;
   2080     }
   2081     ESW_STK_UNLOCK;
   2082 
   2083     if (node != NULL) {
   2084         sal_free(node);
   2085     }
   2086 
   2087     return (rv);
   2088 }
   2089 
   2090 /*
   2091  * Force stack ports into ptable tagged bitmap and out of untagged bitmap
   2092  * Note that if a device has no ethernet ports, this will just return.
   2093  */
   2094 STATIC int
   2095 _bcm_stk_ptable_update(int unit)
   2096 {
   2097     bcm_port_cfg_t pcfg;
   2098     int port;
   2099     bcm_pbmp_t old_pbm, old_upbm;
   2100 
   2101     PBMP_E_ITER(unit, port) {
   2102         SOC_IF_ERROR_RETURN(
   2103             mbcm_driver[unit]->mbcm_port_cfg_get(unit, port, &pcfg));
   2104         SOC_PBMP_ASSIGN(old_pbm, pcfg.pc_pbm);
   2105         SOC_PBMP_ASSIGN(old_upbm, pcfg.pc_ut_pbm);
   2106         SOC_PBMP_OR(pcfg.pc_pbm, SOC_PBMP_STACK_CURRENT(unit));
   2107         SOC_PBMP_REMOVE(pcfg.pc_ut_pbm, SOC_PBMP_STACK_CURRENT(unit));
   2108 
   2109         if (SOC_PBMP_NEQ(old_pbm, pcfg.pc_pbm) ||
   2110             SOC_PBMP_NEQ(old_upbm, pcfg.pc_ut_pbm)) {
   2111             SOC_IF_ERROR_RETURN(
   2112                 mbcm_driver[unit]->mbcm_port_cfg_set(unit, port, &pcfg));
   2113         }
   2114     }
   2115 
   2116     return BCM_E_NONE;
   2117 }
   2118 
   2119 STATIC int
   2120 _esw_stk_update_callbacks(int unit,
   2121                           bcm_port_t port,
   2122                           uint32 flags,
   2123                           int inactiveChkReqd)
   2124 {
   2125     _esw_stk_callback_t *node;
   2126 
   2127     /* Internal port-table update (for untagged port setting */
   2128     BCM_IF_ERROR_RETURN(_bcm_stk_ptable_update(unit));
   2129 
   2130     if ( (SOC_PBMP_NEQ(SOC_PBMP_STACK_CURRENT(unit),
   2131                      SOC_PBMP_STACK_PREVIOUS(unit))) || inactiveChkReqd ) {
   2132         /* Make internal callbacks if stack ports have changed */
   2133         BCM_IF_ERROR_RETURN(_bcm_esw_vlan_stk_update(unit, flags));
   2134         BCM_IF_ERROR_RETURN(_bcm_esw_mcast_stk_update(unit, flags));
   2135         BCM_IF_ERROR_RETURN(_bcm_esw_ipmc_stk_update(unit, flags));
   2136     }
   2137 
   2138     /* Make registered callbacks.  Assumes lock is held by caller. */
   2139     node = _esw_stk_cb;
   2140     while (node != NULL) {
   2141         (node->fn)(unit, port, flags, node->cookie);
   2142         node = node->next;
   2143     }
   2144 
   2145     return BCM_E_NONE;
   2146 }
   2147 
   2148 /*
   2149  * Function:
   2150  *      bcm_esw_stk_port_set
   2151  * Purpose:
   2152  *      Set stacking mode for a port
   2153  * Parameters:
   2154  *      unit     BCM device number
   2155  *      port     BCM port number on device
   2156  *      flags    See bcm/stack.h
   2157  * Returns:
   2158  *      BCM_E_XXX
   2159  * Notes:
   2160  *      If neither simplex or duplex is specified, port should be
   2161  *      considered "unresolved"; for example, if discovery has not
   2162  *      completed yet.  In general, this should not change a port's
   2163  *      settings, but it may affect the port's setup.
   2164  *
   2165  *      If port < 0, use the unique IPIC_PORT if present
   2166  *
   2167  *      If flags == 0, then the port does not have to be a stack port.
   2168  */
   2169 
   2170 int
   2171 bcm_esw_stk_port_set(int unit, bcm_port_t port, uint32 flags)
   2172 {
   2173     int rv = BCM_E_NONE;
   2174     int txp, rxp;
   2175 
   2176     if ((!SOC_UNIT_VALID(unit)) || (!BCM_IS_LOCAL(unit))) {
   2177         LOG_WARN(BSL_LS_BCM_STK,
   2178                  (BSL_META_U(unit,
   2179                              "STK: %s unit %d\n"),
   2180                   SOC_UNIT_VALID(unit)?"Invalid":"Remote", unit));
   2181         return BCM_E_UNIT;
   2182     }
   2183 
   2184     BCM_STK_API_TH3_SUPPORT_CHECK(unit);
   2185 
   2186     LOG_VERBOSE(BSL_LS_BCM_STK,
   2187                 (BSL_META_U(unit,
   2188                             "STK %d: Port set: p %d. flags 0x%x\n"),
   2189                  unit, port, flags));
   2190 
   2191     if (BCM_GPORT_INVALID == port) {
   2192         port = IPIC_PORT(unit);
   2193     } else if (BCM_GPORT_IS_SET(port)) {
   2194         BCM_IF_ERROR_RETURN(
   2195             bcm_esw_port_local_get(unit, port, &port));
   2196     }
   2197 
   2198     if (!IS_PORT(unit, port)) {
   2199         LOG_WARN(BSL_LS_BCM_STK,
   2200                  (BSL_META_U(unit,
   2201                              "STK: invalid port (%d,%d)\n"),
   2202                   unit, port));
   2203         return BCM_E_PARAM;
   2204     }
   2205 
   2206     rv = _bcm_esw_stk_init();
   2207     if (BCM_FAILURE(rv)) {
   2208         LOG_WARN(BSL_LS_BCM_STK,
   2209                  (BSL_META_U(unit,
   2210                              "STK: init failure (%d)\n"),
   2211                   rv));
   2212         return rv;
   2213     }
   2214 
   2215     if (flags & (BCM_STK_ENABLE | BCM_STK_CAPABLE)) {
   2216         if (!IS_ST_PORT(unit, port)) {
   2217 
   2218             /* Setting a non-HG port to stacking implies SL mode */
   2219             if ((flags & BCM_STK_HG) || !IS_GE_PORT(unit, port)) {
   2220                 LOG_WARN(BSL_LS_BCM_STK,
   2221                          (BSL_META_U(unit,
   2222                                      "STK: Invalid SL stk cfg. unit %d, port %d\n"),
   2223                           unit, port));
   2224                 return BCM_E_PARAM;
   2225             }
   2226             flags |= BCM_STK_SL; /* Set courtesy flag for callbacks */
   2227 
   2228             /* Turn pause off on SL stack ports */
   2229             rv = bcm_esw_port_pause_get(unit, port, &txp, &rxp);
   2230             if (BCM_FAILURE(rv)) {
   2231                 LOG_WARN(BSL_LS_BCM_STK,
   2232                          (BSL_META_U(unit,
   2233                                      "STK: bcm_port_pause_get failure (%d)\n"),
   2234                           rv));
   2235                 return rv;
   2236             }
   2237 
   2238             if ((txp != 0) || (rxp != 0)) {
   2239                 rv = bcm_esw_port_pause_set(unit, port, 0, 0);
   2240                 if (BCM_FAILURE(rv)) {
   2241                     LOG_WARN(BSL_LS_BCM_STK,
   2242                              (BSL_META_U(unit,
   2243                                          "STK: bcm_port_pause_set failure (%d)\n"),
   2244                               rv));
   2245                     return rv;
   2246                 }
   2247             }
   2248         } else { /* HG port/HG2 over GE port */
   2249             if (flags & BCM_STK_SL) {
   2250                 LOG_WARN(BSL_LS_BCM_STK,
   2251                          (BSL_META_U(unit,
   2252                                      "STK: Invalid HG stk cfg. unit %d, port %d\n"),
   2253                           unit, port));
   2254                 return BCM_E_PARAM;
   2255             }
   2256             flags |= BCM_STK_HG; /* Set courtesy flag for callbacks */
   2257         }
   2258 
   2259         if ((flags & BCM_STK_SIMPLEX) && (flags & BCM_STK_DUPLEX)) {
   2260             LOG_WARN(BSL_LS_BCM_STK,
   2261                      (BSL_META_U(unit,
   2262                                  "STK: Dimplex not supported. unit %d, port %d\n"),
   2263                       unit, port));
   2264             return BCM_E_PARAM;
   2265         }
   2266     }
   2267 
   2268     if ((flags & BCM_STK_CUT) && (flags & BCM_STK_SL)) {
   2269         flags |= BCM_STK_INACTIVE;
   2270     }
   2271 
   2272     ESW_STK_LOCK;
   2273     rv = _esw_stk_port_set(unit, port, flags);
   2274     ESW_STK_UNLOCK;
   2275 
   2276 #ifdef BCM_WARM_BOOT_SUPPORT
   2277     SOC_CONTROL_LOCK(unit);
   2278     SOC_CONTROL(unit)->scache_dirty = 1;
   2279     SOC_CONTROL_UNLOCK(unit);
   2280 #endif
   2281 
   2282     return rv;
   2283 }
   2284 
   2285 /*
   2286  * Function:
   2287  *      bcm_esw_stk_pbmp_get
   2288  * Purpose:
   2289  *      Expose the current enabled and inactive ports
   2290  * Parameters:
   2291  *
   2292  * Returns:
   2293  *      BCM_E_XXX
   2294  * Notes:
   2295  */
   2296 
   2297 int
   2298 bcm_esw_stk_pbmp_get(int unit, bcm_pbmp_t *cur_pbm,
   2299                      bcm_pbmp_t *inactive_pbm)
   2300 {
   2301     if ((!SOC_UNIT_VALID(unit)) || (!BCM_IS_LOCAL(unit))) {
   2302         return BCM_E_UNIT;
   2303     }
   2304 
   2305     BCM_STK_API_TH3_SUPPORT_CHECK(unit);
   2306 
   2307     if (cur_pbm != NULL) {
   2308         BCM_PBMP_ASSIGN(*cur_pbm, SOC_PBMP_STACK_CURRENT(unit));
   2309     }
   2310 
   2311     if (inactive_pbm != NULL) {
   2312         BCM_PBMP_ASSIGN(*inactive_pbm, SOC_PBMP_STACK_INACTIVE(unit));
   2313     }
   2314 
   2315     return BCM_E_NONE;
   2316 }
   2317 
   2318 
   2319 /*
   2320  * Function:
   2321  *      bcm_esw_stk_mode_get
   2322  * Purpose:
   2323  *      Returns current stack mode
   2324  * Parameters:
   2325  *      unit    BCM device number
   2326  *      flags   (OUT) Indication of stack mode
   2327  * Returns:
   2328  *      BCM_E_XXX
   2329  * Notes:
   2330  *      Currently should only return one bit set, but that may
   2331  *      change in the future.  SL has precedence; if that mode is
   2332  *      active on the device, that's what gets returned.  Then, if
   2333  *      the device has any HG ports, HG mode is returned.  Then
   2334  *      "NONE" is returned.  Note that some bit will always be set;
   2335  *      that is, the routine will not return 0.
   2336  */
   2337 
   2338 int
   2339 bcm_esw_stk_mode_get(int unit, uint32 *flags)
   2340 {
   2341     if ((!SOC_UNIT_VALID(unit)) || (!BCM_IS_LOCAL(unit))) {
   2342         return BCM_E_UNIT;
   2343     }
   2344 
   2345     BCM_STK_API_TH3_SUPPORT_CHECK(unit);
   2346 
   2347     if (SOC_SL_MODE(unit)) {
   2348         *flags = BCM_STK_SL;
   2349     } else if (BCM_PBMP_NOT_NULL(PBMP_ST_ALL(unit))) {
   2350         /* HG/HG2 stacking */
   2351         *flags = BCM_STK_HG;
   2352     } else {
   2353         *flags = BCM_STK_NONE;
   2354     }
   2355 
   2356     return BCM_E_NONE;
   2357 }
   2358 
   2359 /*
   2360  * Function:
   2361  *      bcm_esw_stk_mode_set
   2362  * Purpose:
   2363  *      Set the current stack mode
   2364  * Parameters:
   2365  *      unit    BCM device number
   2366  *      flags   Indication of stack mode
   2367  * Returns:
   2368  *      BCM_E_XXX
   2369  * Notes:
   2370  *      The main use of this is to put a chip supporting SL
   2371  *      stacking into SL mode before other things are started.
   2372  *
   2373  *      Only BCM_STK_SL, BCM_STK_HG and BCM_STK_NONE are checked.
   2374  *
   2375  *      Currently only turning on SL stacking is supported.
   2376  */
   2377 
   2378 int
   2379 bcm_esw_stk_mode_set(int unit, uint32 flags)
   2380 {
   2381     if ((!SOC_UNIT_VALID(unit)) || (!BCM_IS_LOCAL(unit))) {
   2382         return BCM_E_UNIT;
   2383     }
   2384 
   2385     BCM_STK_API_TH3_SUPPORT_CHECK(unit);
   2386 
   2387     LOG_VERBOSE(BSL_LS_BCM_STK,
   2388                 (BSL_META_U(unit,
   2389                             "STK %d: Mode set: flags 0x%x\n"),
   2390                  unit, flags));
   2391 
   2392     if (flags & BCM_STK_SL) {
   2393         return BCM_E_UNAVAIL;
   2394     }
   2395 
   2396     if (flags & BCM_STK_NONE) {
   2397         if (SOC_SL_MODE(unit)) {
   2398             return BCM_E_UNAVAIL; /* Not currently supported */
   2399         }
   2400         return BCM_E_NONE;
   2401     }
   2402 
   2403     return BCM_E_NONE;
   2404 }
   2405 
   2406 /*
   2407  * Function:
   2408  *      bcm_esw_stk_port_get
   2409  * Purpose:
   2410  *      Get stack port mode information
   2411  * Parameters:
   2412  *      unit      BCM device number
   2413  *      port      BCM port number on device
   2414  *      flags     (OUT) flags related to stacking
   2415  * Returns:
   2416  *      BCM_E_XXX
   2417  * Notes:
   2418  */
   2419 
   2420 int
   2421 bcm_esw_stk_port_get(int unit, bcm_port_t port, uint32 *flags)
   2422 {
   2423     *flags = 0;
   2424 
   2425     if ((!SOC_UNIT_VALID(unit)) || (!BCM_IS_LOCAL(unit))) {
   2426         return BCM_E_UNIT;
   2427     }
   2428 
   2429     BCM_STK_API_TH3_SUPPORT_CHECK(unit);
   2430 
   2431     if (BCM_GPORT_INVALID == port) {     /* BCM_STK_USE_HG_IF */
   2432         port = IPIC_PORT(unit);
   2433     } else if (BCM_GPORT_IS_SET(port)) {
   2434         BCM_IF_ERROR_RETURN(
   2435             bcm_esw_port_local_get(unit, port, &port));
   2436     }
   2437 
   2438     if (!IS_PORT(unit, port)) {
   2439         return BCM_E_PARAM;
   2440     }
   2441 
   2442     if (BCM_PBMP_MEMBER(SOC_PBMP_STACK_CURRENT(unit), port)) {
   2443         *flags |= BCM_STK_ENABLE;
   2444         if (BCM_PBMP_MEMBER(SOC_PBMP_STACK_INACTIVE(unit), port)) {
   2445             *flags |= BCM_STK_INACTIVE;
   2446         }
   2447         if (IS_ST_PORT(unit, port)) {
   2448             *flags |= BCM_STK_HG;
   2449         } else {
   2450             *flags |= BCM_STK_SL;
   2451         }
   2452     } else {
   2453         *flags |= BCM_STK_NONE;
   2454     }
   2455 
   2456     return BCM_E_NONE;
   2457 }
   2458 
   2459 /****************************************************************
   2460  * The ugly details of adding stack ports
   2461  */
   2462 
   2463 STATIC int
   2464 _xgs3_stk_port_set(int unit, bcm_port_t port, uint32 flags)
   2465 {
   2466     if (SOC_IS_XGS3_SWITCH(unit)) {
   2467 #if defined(BCM_XGS3_SWITCH_SUPPORT)
   2468         if (IS_ST_PORT(unit, port) || flags == 0) {
   2469             /* Only stack ports may be set (flags != 0), but any port
   2470                may be unset (flags == 0) */
   2471             return BCM_E_NONE;
   2472         }
   2473 #endif
   2474     }
   2475 
   2476     return BCM_E_UNAVAIL;
   2477 }
   2478 
   2479 
   2480 STATIC int
   2481 _esw_soc_stk_port_set(int unit, bcm_port_t port, uint32 flags)
   2482 {
   2483 
   2484     /* SL, HG, simplex and duplex are determined per-device */
   2485     switch (BCM_CHIP_FAMILY(unit)) {
   2486     case BCM_FAMILY_FIREBOLT:
   2487     case BCM_FAMILY_BRADLEY:
   2488     case BCM_FAMILY_HUMV:
   2489     case BCM_FAMILY_TRIUMPH:
   2490     case BCM_FAMILY_SCORPION:
   2491     case BCM_FAMILY_CONQUEROR:
   2492     case BCM_FAMILY_TRIUMPH2:
   2493     case BCM_FAMILY_TITAN:
   2494     case BCM_FAMILY_TRIDENT:
   2495     case BCM_FAMILY_KATANA:
   2496         return _xgs3_stk_port_set(unit, port, flags);
   2497 
   2498     default:
   2499         break;
   2500     }
   2501 
   2502     return BCM_E_NONE;
   2503 }
   2504 
   2505 
   2506 STATIC int
   2507 _esw_stk_port_set(int unit, bcm_port_t port, uint32 flags)
   2508 {
   2509     int rv = BCM_E_NONE;
   2510     int isPrevInactiveSet = 0;
   2511     int inactiveChkReqd = 0;
   2512 
   2513     /* Check if SL stacking should be enabled on the device */
   2514     if ((!SOC_SL_MODE(unit)) && (flags & BCM_STK_ENABLE) &&
   2515             (flags & BCM_STK_SL)) {
   2516         return BCM_E_UNAVAIL;
   2517     }
   2518 
   2519     if (SOC_PBMP_MEMBER(SOC_PBMP_STACK_INACTIVE(unit), port))
   2520         isPrevInactiveSet = 1;
   2521 
   2522     /* Program the port appropriately */
   2523     BCM_IF_ERROR_RETURN(_esw_soc_stk_port_set(unit, port, flags));
   2524 
   2525     /* Record old stack port states; make changes to current */
   2526     BCM_PBMP_ASSIGN(SOC_PBMP_STACK_PREVIOUS(unit), SOC_PBMP_STACK_CURRENT(unit));
   2527 
   2528     if (flags & BCM_STK_ENABLE) {
   2529         SOC_PBMP_PORT_ADD(SOC_PBMP_STACK_CURRENT(unit), port);
   2530         if (flags & BCM_STK_INACTIVE) {
   2531             SOC_PBMP_PORT_ADD(SOC_PBMP_STACK_INACTIVE(unit), port);
   2532             if (!isPrevInactiveSet)
   2533                 inactiveChkReqd = 1;
   2534         } else {
   2535             SOC_PBMP_PORT_REMOVE(SOC_PBMP_STACK_INACTIVE(unit), port);
   2536             if (isPrevInactiveSet)
   2537                 inactiveChkReqd = 1;
   2538         }
   2539     } else {
   2540         SOC_PBMP_PORT_REMOVE(SOC_PBMP_STACK_CURRENT(unit), port);
   2541         SOC_PBMP_PORT_REMOVE(SOC_PBMP_STACK_INACTIVE(unit), port);
   2542     }
   2543 
   2544     /* Always make callbacks; callbacks are responsible for determining
   2545      * whether or not anything needs to be done.
   2546      */
   2547     rv = _esw_stk_update_callbacks(unit, port, flags, inactiveChkReqd);
   2548 
   2549     return rv;
   2550 }
   2551 
   2552 /*
   2553  * Function:
   2554  *      bcm_stk_modid_set
   2555  * Purpose:
   2556  *      Set the module id of a unit
   2557  * Parameters:
   2558  *      unit    - device number
   2559  *      modid   - module id
   2560  * Returns:
   2561  *      BCM_E_XXX
   2562  * Notes:
   2563  *      calls bcm_stk_modmap_map (my_modid_set does not)
   2564  */
   2565 int
   2566 bcm_esw_stk_modid_set(int unit, int modid)
   2567 {
   2568     bcm_module_t        mod_out;
   2569     bcm_port_t          port_out;
   2570 
   2571     BCM_IF_ERROR_RETURN
   2572         (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_SET,
   2573                                 modid, -1,
   2574                                 &mod_out, &port_out));
   2575 
   2576     LOG_INFO(BSL_LS_BCM_STK,
   2577              (BSL_META_U(unit,
   2578                          "STK %d: modid set to %d; mapped %d\n"),
   2579               unit,
   2580               modid, mod_out));
   2581     return bcm_esw_stk_my_modid_set(unit, mod_out);
   2582 }
   2583 
   2584 /*
   2585  * Function:
   2586  *      bcm_stk_modid_get
   2587  * Purpose:
   2588  *      Get the module id of a unit
   2589  * Parameters:
   2590  *      unit    - device number
   2591  *      modid   - module id
   2592  * Returns:
   2593  *      BCM_E_XXX
   2594  * Notes:
   2595  *      calls bcm_stk_modmap_map (my_modid_set does not)
   2596  */
   2597 int
   2598 bcm_esw_stk_modid_get(int unit, int *modid)
   2599 {
   2600     bcm_module_t        mod_out;
   2601     bcm_port_t          port_out;
   2602 
   2603     BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, modid));
   2604 
   2605     BCM_IF_ERROR_RETURN
   2606         (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET,
   2607                                 *modid, -1,
   2608                                 &mod_out, &port_out));
   2609     *modid = mod_out;
   2610     return BCM_E_NONE;
   2611 }
   2612 
   2613 /*
   2614  * Function:
   2615  *      bcm_stk_modid_count
   2616  * Purpose:
   2617  *      The number of module identifiers (fabric IDs) needed by the unit
   2618  * Parameters:
   2619  *      unit  - SOC unit#
   2620  *      num_modid - (out)# of MODIDs
   2621  * Returns:
   2622  *      BCM_E_XXX
   2623  */
   2624 int
   2625 bcm_esw_stk_modid_count(int unit, int *num_modid)
   2626 {
   2627     soc_control_t *soc = SOC_CONTROL(unit);
   2628 
   2629     *num_modid = soc->info.modid_count;
   2630 
   2631     return BCM_E_NONE;
   2632 }
   2633 
   2634 /*
   2635  * Function:
   2636  *      _bcm_stk_my_modid_set
   2637  * Purpose:
   2638  *      Sets the module-id in the Port block
   2639  * Parameters:
   2640  *      unit  - SOC unit#
   2641  *      port - port #
   2642  *      my_modid - the value to set
   2643  * Returns:
   2644  *      BCM_E_XXX
   2645  */
   2646 STATIC int
   2647 _bcm_stk_my_modid_set(int unit, int port, int my_modid)
   2648 {
   2649     uint32 config;
   2650 
   2651     if (SOC_USE_PORTCTRL(unit)) {
   2652         return bcmi_esw_portctrl_stk_my_modid_set(unit, port, my_modid);
   2653     }
   2654 
   2655 #ifdef BCM_TRIDENT_SUPPORT
   2656     if (IS_HG_PORT(unit, port) && IS_XL_PORT(unit, port) &&
   2657         SOC_IS_TD_TT(unit)) {
   2658         /* The XLPORT_CONFIG.MY_MODID field is used to fill the module
   2659          * ID field of E2ECC messages. In Trident, this field is
   2660          * limited to 7 bits.
   2661          */
   2662         BCM_IF_ERROR_RETURN
   2663             (READ_XLPORT_CONFIGr(unit, port, &config));
   2664         if (my_modid < (1 << soc_reg_field_length(unit,
   2665                         XLPORT_CONFIGr, MY_MODIDf))) {
   2666             soc_reg_field_set(unit, XLPORT_CONFIGr, &config,
   2667                     MY_MODIDf, my_modid);
   2668         } else {
   2669             soc_reg_field_set(unit, XLPORT_CONFIGr, &config,
   2670                     MY_MODIDf, 0);
   2671         }
   2672         BCM_IF_ERROR_RETURN
   2673             (WRITE_XLPORT_CONFIGr(unit, port, config));
   2674     } else
   2675 #endif /* BCM_TRIDENT_SUPPORT */
   2676     if ((IS_HG_PORT(unit, port) &&
   2677          !(SOC_IS_KATANAX(unit) ||
   2678          SOC_IS_TRIUMPH3(unit) ||
   2679          SOC_IS_HURRICANE2(unit) ||
   2680          SOC_IS_TD2_TT2(unit) ||
   2681          SOC_IS_GREYHOUND(unit) ||
   2682          SOC_IS_HURRICANE3(unit) ||
   2683          SOC_IS_GREYHOUND2(unit))) ||
   2684          (IS_HL_PORT(unit, port) &&
   2685          ((SOC_IS_ENDURO(unit) || SOC_IS_HURRICANE(unit))))) {
   2686 
   2687     
   2688         BCM_IF_ERROR_RETURN(READ_XPORT_CONFIGr(unit, port, &config));
   2689         soc_reg_field_set(unit, XPORT_CONFIGr, &config,
   2690                           MY_MODIDf, my_modid);
   2691         BCM_IF_ERROR_RETURN(WRITE_XPORT_CONFIGr(unit, port, config));
   2692 #if 0
   2693     
   2694         if (SOC_REG_IS_VALID(unit, XPORT_CONFIGr)) {
   2695             BCM_IF_ERROR_RETURN
   2696                 (READ_XPORT_CONFIGr(unit, port, &config));
   2697             soc_reg_field_set(unit, XPORT_CONFIGr, &config,
   2698                               MY_MODIDf, my_modid);
   2699             BCM_IF_ERROR_RETURN
   2700                 (WRITE_XPORT_CONFIGr(unit, port, config));
   2701         } else if (SOC_REG_IS_VALID(unit, XLPORT_CONFIGr)) {
   2702             BCM_IF_ERROR_RETURN
   2703                 (READ_XLPORT_CONFIGr(unit, port, &config));
   2704             soc_reg_field_set(unit, XLPORT_CONFIGr, &config,
   2705                               MY_MODIDf, my_modid);
   2706             BCM_IF_ERROR_RETURN
   2707                 (WRITE_XLPORT_CONFIGr(unit, port, config));
   2708         }
   2709 #endif
   2710     }
   2711 
   2712     return BCM_E_NONE;
   2713 }
   2714 
   2715 /*
   2716  * Function:
   2717  *      bcm_stk_my_modid_set
   2718  * Purpose:
   2719  *      Set the MY_MODID field
   2720  * Parameters:
   2721  *      unit  - SOC unit#
   2722  *      my_modid - the value to set
   2723  * Returns:
   2724  *      BCM_E_XXX
   2725  */
   2726 int
   2727 bcm_esw_stk_my_modid_set(int unit, int my_modid)
   2728 {
   2729     soc_mem_t port_tab = PORT_TABm;
   2730 
   2731     LOG_VERBOSE(BSL_LS_BCM_STK,
   2732                 (BSL_META_U(unit,
   2733                             "STK %d: Set my modid %d\n"),
   2734                  unit, my_modid));
   2735 
   2736     if ((BCM_MODID_INVALID != my_modid) && !SOC_MODID_ADDRESSABLE(unit, my_modid)) {
   2737         return BCM_E_BADID;
   2738     }
   2739 
   2740     if (BCM_MODID_INVALID != my_modid) {
   2741         SOC_DEFAULT_DMA_SRCMOD_SET(unit, my_modid);
   2742     }
   2743 
   2744     if (SOC_MEM_IS_VALID(unit, ING_DEVICE_PORTm)) {
   2745         port_tab = ING_DEVICE_PORTm;
   2746     }
   2747 
   2748     switch (BCM_CHIP_FAMILY(unit)) {
   2749 
   2750 #if defined(BCM_FIREBOLT_SUPPORT)
   2751     case BCM_FAMILY_FIREBOLT:
   2752     case BCM_FAMILY_BRADLEY:
   2753     case BCM_FAMILY_HUMV:
   2754     case BCM_FAMILY_TRIUMPH:
   2755     case BCM_FAMILY_SCORPION:
   2756     case BCM_FAMILY_CONQUEROR:
   2757     case BCM_FAMILY_TRIUMPH2:
   2758     case BCM_FAMILY_TITAN:
   2759     case BCM_FAMILY_TRIDENT:
   2760     case BCM_FAMILY_KATANA:
   2761     {
   2762         int port;
   2763         int cpu_hg_index = 0;
   2764 
   2765         port_tab_entry_t pte;
   2766         if (BCM_MODID_INVALID == my_modid) {
   2767             return BCM_E_BADID;
   2768         }
   2769 
   2770 #ifdef BCM_TRIUMPH_SUPPORT
   2771         if ((BCM_CHIP_FAMILY(unit) == BCM_FAMILY_TRIUMPH ||
   2772              BCM_CHIP_FAMILY(unit) == BCM_FAMILY_TRIUMPH2) &&
   2773             NUM_MODID(unit) > 1) {
   2774             /* Dual-modid is enabled (32-port module mode). The my_modid
   2775              * value specified here needs to be an even number.
   2776              */
   2777             if (my_modid & 0x1) {
   2778                 return BCM_E_BADID;
   2779             }
   2780         }
   2781 #endif
   2782 
   2783         
   2784         PBMP_E_ITER(unit, port) {
   2785             BCM_IF_ERROR_RETURN
   2786                 (soc_mem_read(unit, port_tab, MEM_BLOCK_ANY, port, &pte));
   2787             if (soc_mem_field_valid(unit, port_tab, MY_MODIDf)) {
   2788                 soc_mem_field32_set(unit, port_tab, &pte, MY_MODIDf, my_modid);
   2789             }
   2790             BCM_IF_ERROR_RETURN
   2791                 (soc_mem_write(unit, port_tab, MEM_BLOCK_ALL, port, &pte));
   2792         }
   2793 #ifdef BCM_TRIUMPH2_SUPPORT
   2794         if (soc_feature(unit, soc_feature_wlan) || 
   2795             (soc_feature(unit, soc_feature_mim)) ||
   2796             (soc_feature(unit, soc_feature_proxy_port_property))) {
   2797             soc_info_t *si;
   2798             int i, min, max;
   2799             lport_tab_entry_t lport_profile;
   2800 
   2801             si = &SOC_INFO(unit);
   2802             /* Do it for the loopback port */
   2803             port = SOC_IS_ENDURO(unit)? 1 : si->lb_port;
   2804             BCM_IF_ERROR_RETURN
   2805                 (soc_mem_read(unit, port_tab, MEM_BLOCK_ANY, port, &pte));
   2806             if (soc_mem_field_valid(unit, port_tab, MY_MODIDf)) {
   2807                 soc_mem_field32_set(unit, port_tab, &pte, MY_MODIDf, my_modid);
   2808             }
   2809             BCM_IF_ERROR_RETURN
   2810                 (soc_mem_write(unit, port_tab, MEM_BLOCK_ALL, port, &pte));
   2811 
   2812             /* Update modid for LPORT profiles */
   2813 #if defined(BCM_TRX_SUPPORT)
   2814             if (soc_feature(unit, soc_feature_lport_tab_profile)) {
   2815                 if(SOC_MEM_FIELD_VALID(unit, LPORT_TABm, MY_MODIDf)) {
   2816                     BCM_IF_ERROR_RETURN
   2817                         (_bcm_lport_profile_field32_modify
   2818                          (unit, LPORT_PROFILE_LPORT_TAB, MY_MODIDf, my_modid));
   2819                 }
   2820             } else
   2821 #endif /* BCM_TRX_SUPPORT */
   2822             {
   2823                 min = soc_mem_index_min(unit, LPORT_TABm);
   2824                 max = soc_mem_index_max(unit, LPORT_TABm);
   2825                 for (i = min; i <= max; i++) {
   2826                     BCM_IF_ERROR_RETURN
   2827                         (READ_LPORT_TABm(unit, MEM_BLOCK_ANY, i,
   2828                                          &lport_profile));
   2829                     if (soc_mem_field_valid(unit, LPORT_TABm,
   2830                                             SRC_SYS_PORT_IDf)) {
   2831                         if (soc_mem_field32_get(unit, LPORT_TABm,
   2832                                                 &lport_profile,
   2833                                                 SRC_SYS_PORT_IDf) !=
   2834                             si->lb_port) {
   2835                             continue;
   2836                         }
   2837                     } else if (soc_mem_field_valid(unit, LPORT_TABm,
   2838                                                    MIM_MC_TERM_ENABLEf)) {
   2839                         if (!soc_mem_field32_get(unit, LPORT_TABm,
   2840                                                  &lport_profile,
   2841                                                  MIM_MC_TERM_ENABLEf)) {
   2842                             continue;
   2843                         }
   2844                     }
   2845                     if (soc_mem_field_valid(unit, LPORT_TABm, MY_MODIDf)) {
   2846                         soc_LPORT_TABm_field32_set(unit, &lport_profile,
   2847                                                    MY_MODIDf, my_modid);
   2848                     }
   2849                     BCM_IF_ERROR_RETURN
   2850                         (WRITE_LPORT_TABm(unit, MEM_BLOCK_ALL, i,
   2851                                           &lport_profile));
   2852                 }
   2853             }
   2854         }
   2855 #endif
   2856         PBMP_ST_ITER(unit, port) {
   2857             BCM_IF_ERROR_RETURN
   2858                 (soc_mem_read(unit, port_tab, MEM_BLOCK_ANY, port, &pte));
   2859             if (soc_mem_field_valid(unit, port_tab, MY_MODIDf)) {
   2860                 soc_mem_field32_set(unit, port_tab, &pte, MY_MODIDf, my_modid);
   2861             }
   2862             BCM_IF_ERROR_RETURN
   2863                 (soc_mem_write(unit, port_tab, MEM_BLOCK_ALL, port, &pte));
   2864 
   2865             BCM_IF_ERROR_RETURN
   2866                 (_bcm_stk_my_modid_set(unit, port, my_modid));
   2867         }
   2868         port = CMIC_PORT(unit);
   2869         BCM_IF_ERROR_RETURN
   2870             (soc_mem_read(unit, port_tab, MEM_BLOCK_ANY, port, &pte));
   2871         if (soc_mem_field_valid(unit, port_tab, MY_MODIDf)) {
   2872             soc_mem_field32_set(unit, port_tab, &pte, MY_MODIDf, my_modid);
   2873         } 
   2874         BCM_IF_ERROR_RETURN
   2875             (soc_mem_write(unit, port_tab, MEM_BLOCK_ALL, port, &pte));
   2876         if (!SOC_IS_TD_TT(unit) && !SOC_IS_KATANAX(unit) &&
   2877             !SOC_IS_TRIUMPH3(unit)) {
   2878             BCM_IF_ERROR_RETURN
   2879                 (soc_mem_read(unit, IPORT_TABLEm, MEM_BLOCK_ANY, port, &pte));
   2880             soc_IPORT_TABLEm_field32_set(unit, &pte, MY_MODIDf, my_modid);
   2881             BCM_IF_ERROR_RETURN
   2882                 (soc_mem_write(unit, IPORT_TABLEm, MEM_BLOCK_ALL, port, &pte));
   2883         }
   2884 
   2885         /* FAE port */
   2886         if (soc_feature(unit, soc_feature_flex_flowtracker_ver_1)) {
   2887             port = SOC_INFO(unit).fae_port;
   2888             BCM_IF_ERROR_RETURN
   2889                 (soc_mem_read(unit, port_tab, MEM_BLOCK_ANY, port, &pte));
   2890             if (soc_mem_field_valid(unit, port_tab, MY_MODIDf)) {
   2891                 soc_mem_field32_set(unit, port_tab, &pte, MY_MODIDf, my_modid);
   2892             }
   2893             BCM_IF_ERROR_RETURN
   2894                 (soc_mem_write(unit, port_tab, MEM_BLOCK_ALL, port, &pte));
   2895         }
   2896 
   2897         /* UPdate the PORT_TABm of cpu_hg_index if relevant */
   2898         cpu_hg_index = SOC_IS_KATANA2(unit) ?
   2899                         SOC_INFO(unit).cpu_hg_pp_port_index :
   2900                         SOC_INFO(unit).cpu_hg_index;
   2901         if (cpu_hg_index != -1) {
   2902             BCM_IF_ERROR_RETURN
   2903                 (soc_mem_read(unit, port_tab, MEM_BLOCK_ANY, cpu_hg_index, &pte));
   2904             if (soc_mem_field_valid(unit, port_tab, MY_MODIDf)) {
   2905                 soc_mem_field32_set(unit, port_tab, &pte, MY_MODIDf, my_modid);
   2906             }
   2907             BCM_IF_ERROR_RETURN
   2908                 (soc_mem_write(unit, port_tab, MEM_BLOCK_ALL, cpu_hg_index, &pte));
   2909         }
   2910 
   2911         /* Mirroring across stack */
   2912         if (soc_feature(unit, soc_feature_src_modid_blk) &&
   2913             !SOC_IS_SHADOW(unit)) {
   2914             soc_field_t field = MY_MODIDf;
   2915 #ifdef BCM_TRIDENT_SUPPORT
   2916             if (SOC_IS_TD_TT(unit) || SOC_IS_KATANAX(unit) ||
   2917                     SOC_IS_TRIUMPH3(unit)) {
   2918                 if(soc_mem_field_valid(unit,EGR_PORTm,MY_MODIDf)) { 
   2919                     PBMP_ALL_ITER(unit, port) {
   2920                         BCM_IF_ERROR_RETURN
   2921                             (soc_mem_field32_modify(unit, EGR_PORTm, port,
   2922                                                     MY_MODIDf, my_modid));
   2923                     }
   2924                     port = SOC_INFO(unit).cpu_hg_index;
   2925                     if (soc_mem_index_max(unit, EGR_PORTm) == port) {
   2926                         BCM_IF_ERROR_RETURN
   2927                             (soc_mem_field32_modify(unit, EGR_PORTm, port,
   2928                                                     MY_MODIDf, my_modid));
   2929                     }
   2930                 }
   2931             } else
   2932 #endif /* BCM_TRIDENT_SUPPORT */
   2933             {
   2934                 soc_reg_t egr_port_reg, iegr_port_reg;
   2935                 egr_port_reg = SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) ||
   2936                     SOC_IS_VALKYRIE2(unit) || SOC_IS_GREYHOUND(unit) ||
   2937                     SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit) ? 
   2938                     EGR_PORT_64r : EGR_PORTr;
   2939                 iegr_port_reg = SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) ||
   2940                     SOC_IS_VALKYRIE2(unit) || SOC_IS_GREYHOUND(unit) ||
   2941                     SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)? 
   2942                     IEGR_PORT_64r : IEGR_PORTr;
   2943                 PBMP_ALL_ITER(unit, port) {
   2944                     BCM_IF_ERROR_RETURN
   2945                         (soc_reg_fields32_modify(unit, egr_port_reg, port, 1,
   2946                                                  &field, (uint32*)&my_modid));
   2947                 }
   2948                 port = CMIC_PORT(unit);
   2949                 BCM_IF_ERROR_RETURN
   2950                     (soc_reg_fields32_modify(unit, iegr_port_reg, port, 1,
   2951                                              &field, (uint32*)&my_modid));
   2952             }
   2953         }
   2954 #if defined(BCM_RAPTOR_SUPPORT)
   2955         if (soc_feature(unit, soc_feature_mac_learn_limit) &&
   2956             SOC_REG_IS_VALID(unit, MAC_LIMIT_CONFIGr)) {
   2957             uint32  limit_config;
   2958             /* Configure the MODID for MAC learn limit */
   2959             BCM_IF_ERROR_RETURN(READ_MAC_LIMIT_CONFIGr(unit, &limit_config));
   2960             soc_reg_field_set(unit, MAC_LIMIT_CONFIGr, &limit_config,
   2961                               MY_MODIDf, my_modid);
   2962             BCM_IF_ERROR_RETURN(WRITE_MAC_LIMIT_CONFIGr(unit, limit_config));
   2963         }
   2964 #endif /* BCM_RAPTOR_SUPPORT */
   2965 #ifdef BCM_KATANA2_SUPPORT
   2966 
   2967         /* If not running in the coe stackig mode, setup the second module
   2968            as the default one to host all pp_ports, else, the user will
   2969            create the necessary modules with separate APIs */
   2970         if (SOC_IS_KATANA2(unit)) {
   2971 
   2972             int my_modid_list[KT2_MAX_MODIDS_PER_TRANSLATION_TABLE] = {0};
   2973             int my_modid_valid[KT2_MAX_MODIDS_PER_TRANSLATION_TABLE] = {0};
   2974             int my_modport_base_ptr[KT2_MAX_MODIDS_PER_TRANSLATION_TABLE] = {0};
   2975 
   2976             BCM_IF_ERROR_RETURN(
   2977                 bcm_kt2_modid_get_all(unit, my_modid_list, my_modid_valid,
   2978                                       my_modport_base_ptr));
   2979 
   2980             /* If 'coe_stacking_mode' is not-enabled, default to setting up
   2981                the modules like usual, wherein the my_mod+1 is reserved for
   2982                pp_ports, else just setup the needed config for 'my_modid' */
   2983             if(!SOC_INFO(unit).coe_stacking_mode) {
   2984 
   2985                 int num_modid = 1;
   2986 
   2987                 /* reserve my_modid+1 for channelized ports.
   2988                 *  so allow upto my_modid = modid_max -1 */
   2989                 if (((soc_feature(unit, soc_feature_linkphy_coe) &&
   2990                      SOC_INFO(unit).linkphy_enabled) ||
   2991                      (soc_feature(unit, soc_feature_subtag_coe) &&
   2992                       SOC_INFO(unit).subtag_enabled)) &&
   2993                       (my_modid == SOC_INFO(unit).modid_max)) {
   2994                     return BCM_E_BADID;
   2995                 }
   2996 
   2997                 /* PP_PORT_GPP_TRANSLATION_x
   2998                 *  4 instances one each for icfg, il2lu, isw2 and ipars stages of ipipe
   2999                 * EGR_PP_PORT_GPP_TRANSLATION_x
   3000                 *  2 instances one each for evlan and ehcpm stages of epipe
   3001                 * If LinkPHY/SubTag CoE is enabled then
   3002                 * all 170 pp_ports cannot be accomodated
   3003                 * insingle modid. We will use 2 mod_ids.
   3004                 * All pp_port 0 to 41 mapped to my_modid
   3005                 * remaining pp_ports 42 to 169 mapped to my_modid+1.
   3006                 * Do this addition of the second mod addition only if
   3007                 * the user is has not enabled the stacking module, in
   3008                 * which case, the needed modules would need to be
   3009                 * created at run time.
   3010                 */
   3011                 my_modid_list[0] = my_modid;
   3012 
   3013                 if (!SOC_IS_METROLITE(unit)) {
   3014                     if ((soc_feature(unit, soc_feature_linkphy_coe) &&
   3015                          SOC_INFO(unit).linkphy_enabled) ||
   3016                         (soc_feature(unit, soc_feature_subtag_coe) &&
   3017                          SOC_INFO(unit).subtag_enabled)) { 
   3018                         my_modid_list[1] = my_modid + 1;
   3019                         my_modid_valid[1] = 1;
   3020                         num_modid = 2;
   3021                     }
   3022                 }
   3023 
   3024                 BCM_IF_ERROR_RETURN(
   3025                     bcm_kt2_modid_set_all(unit, my_modid_list, my_modid_valid,
   3026                                       my_modport_base_ptr));
   3027 
   3028                 if (soc_feature(unit, soc_feature_src_modid_base_index)) {
   3029                     int old_my_modid[2] = {0}, new_my_modid[2] = {0};
   3030                     int old_base_index[2] = {0}, base_index[2] = {0};
   3031                     int old_num_ports[2] = {0}, num_ports[2] = {0};
   3032                     int i, j, k;
   3033                     source_trunk_map_table_entry_t stm_entry;
   3034                     source_trunk_map_modbase_entry_t stm_modbase_entry;
   3035 
   3036                     for (j = 0; j < num_modid; j++) {
   3037                         old_my_modid[j] = SOC_BASE_MODID(unit) + j;
   3038                         new_my_modid[j] = my_modid_list[j];
   3039                     }
   3040 
   3041                     /* For Katana2 when LinkPHY/CoE is enabled then 2 modids are used
   3042                      * my_modid for physical ports and my_modid+1 for subports
   3043                      * When modid is changed, the etries pointed to by base of
   3044                      * source_trunk_map_modbase table in source_trunk_map table need to be
   3045                      * copied to new location appropriately.
   3046                      * When new my_modid == old my_modid+1  then we need to copy the
   3047                      * entries pointed to by old my_modid+1 to new my_modid+1 first
   3048                      * followed by old my_modid to new my_modid
   3049                      */
   3050                     j = ((num_modid > 1) &&
   3051                             (new_my_modid[0] == old_my_modid[1])) ? 1 : 0;
   3052 
   3053                     for (k = 0; k < num_modid; k++) {
   3054                         j = ((num_modid > 1) &&
   3055                             (new_my_modid[0] == old_my_modid[1])) ?
   3056                             (j - k) : (j + k);
   3057 
   3058                         /* Allocate a source modid base index for new my_modid */
   3059                         BCM_IF_ERROR_RETURN(
   3060                                 _bcm_esw_src_modid_base_index_get(unit,
   3061                                            new_my_modid[j], 1, &base_index[j]));
   3062 
   3063                         if (SOC_MODID_ADDRESSABLE(unit, old_my_modid[j]) &&
   3064                             (old_my_modid[j] != new_my_modid[j])) {
   3065                             SOC_IF_ERROR_RETURN(READ_SOURCE_TRUNK_MAP_MODBASEm(unit,
   3066                                     MEM_BLOCK_ANY, old_my_modid[j],
   3067                                     &stm_modbase_entry));
   3068 
   3069                             old_base_index[j] =
   3070                                 soc_SOURCE_TRUNK_MAP_MODBASEm_field32_get(unit,
   3071                                     &stm_modbase_entry, BASEf);
   3072 
   3073                             if (0 != old_base_index[j]) {
   3074                                 /* Transfer port attributes from the SOURCE_TRUNK_MAP
   3075                                  * region of the old my_modid[j] to the SOURCE_TRUNK_MAP
   3076                                  * region of the new my_modid[j].
   3077                                  */
   3078                                 old_num_ports[j] = src_modid_base_index_bk[unit]->
   3079                                                    num_ports[old_my_modid[j]];
   3080                                 num_ports[j] = src_modid_base_index_bk[unit]->
   3081                                                num_ports[new_my_modid[j]];
   3082                                 for (i = 0;
   3083                                     i < old_num_ports[j] && i < num_ports[j]; i++) {
   3084                                     SOC_IF_ERROR_RETURN(
   3085                                         READ_SOURCE_TRUNK_MAP_TABLEm(unit,
   3086                                             MEM_BLOCK_ANY, i + old_base_index[j],
   3087                                             &stm_entry));
   3088                                     SOC_IF_ERROR_RETURN(
   3089                                         WRITE_SOURCE_TRUNK_MAP_TABLEm(unit,
   3090                                             MEM_BLOCK_ALL, i + base_index[j],
   3091                                             &stm_entry));
   3092                                 }
   3093                             }
   3094                         }
   3095                     }
   3096 
   3097                     /* Release old base index */
   3098                     if (new_my_modid[0] != old_my_modid[0]) {
   3099                         if ((num_modid > 1) &&
   3100                             (new_my_modid[0] == old_my_modid[1]) &&
   3101                             (0 != old_base_index[0])) {
   3102                             BCM_IF_ERROR_RETURN(_src_modid_base_index_free(unit,
   3103                                                 old_my_modid[0], old_num_ports[0]));
   3104                         } else if ((num_modid > 1) &&
   3105                             (new_my_modid[1] == old_my_modid[0]) &&
   3106                             (0 != old_base_index[1])) {
   3107                             BCM_IF_ERROR_RETURN(_src_modid_base_index_free(unit,
   3108                                                 old_my_modid[1], old_num_ports[1]));
   3109                         } else {
   3110                             for (j = 0; j < num_modid; j++) {
   3111                                 if (0 != old_base_index[j]) {
   3112                                     BCM_IF_ERROR_RETURN(
   3113                                             _src_modid_base_index_free(unit,
   3114                                                 old_my_modid[j], old_num_ports[j]));
   3115                                 }
   3116                             }
   3117                         }
   3118                     }
   3119                 }
   3120             } else {
   3121 
   3122                 int old_my_modid = 0;
   3123                 int old_base_index = 0, base_index = 0;
   3124                 int old_num_ports = 0, num_ports = 0;
   3125                 int i;
   3126                 source_trunk_map_table_entry_t stm_entry;
   3127                 source_trunk_map_modbase_entry_t stm_modbase_entry;
   3128 
   3129                 /* Allocate a source modid base index for the base modid */
   3130                 BCM_IF_ERROR_RETURN(_bcm_esw_src_modid_base_index_get(unit,
   3131                                     my_modid, 1, &base_index));
   3132 
   3133                 old_my_modid = SOC_BASE_MODID(unit);
   3134                 if (SOC_MODID_ADDRESSABLE(unit, old_my_modid) && 
   3135                         (old_my_modid != my_modid)) {
   3136                     SOC_IF_ERROR_RETURN(READ_SOURCE_TRUNK_MAP_MODBASEm(unit,
   3137                                 MEM_BLOCK_ANY, old_my_modid, &stm_modbase_entry));
   3138                     old_base_index = soc_SOURCE_TRUNK_MAP_MODBASEm_field32_get(unit,
   3139                             &stm_modbase_entry, BASEf);
   3140                     old_num_ports = src_modid_base_index_bk[unit]->num_ports[old_my_modid];
   3141                     if ((0 != old_base_index) || (0 != old_num_ports)) {
   3142                         /* Transfer port attributes from the SOURCE_TRUNK_MAP
   3143                          * region of the old my_modid to the SOURCE_TRUNK_MAP
   3144                          * region of the new my_modid.
   3145                          */
   3146                         num_ports = src_modid_base_index_bk[unit]->
   3147                             num_ports[my_modid];
   3148                         for (i = 0; i < old_num_ports && i < num_ports; i++) {
   3149                             SOC_IF_ERROR_RETURN(READ_SOURCE_TRUNK_MAP_TABLEm(unit,
   3150                                         MEM_BLOCK_ANY, i + old_base_index, &stm_entry));
   3151                             SOC_IF_ERROR_RETURN(WRITE_SOURCE_TRUNK_MAP_TABLEm(unit,
   3152                                         MEM_BLOCK_ALL, i + base_index, &stm_entry));
   3153                         }
   3154 
   3155                         /* Release old base index */
   3156                         BCM_IF_ERROR_RETURN(_src_modid_base_index_free(unit,
   3157                                     old_my_modid, old_num_ports));
   3158                         /* Reset the number of ports */
   3159                         src_modid_base_index_bk[unit]->num_ports[old_my_modid] = 0;
   3160                     }
   3161                 }
   3162 
   3163                 /* Assign the mod id being created to the first location,
   3164                    which is where the default local mod-id lives */
   3165                 my_modid_list[0] = my_modid;
   3166 
   3167                 /* Write this data back to the hardware */
   3168                 BCM_IF_ERROR_RETURN(
   3169                     bcm_kt2_modid_set_all(unit, my_modid_list, my_modid_valid,
   3170                                       my_modport_base_ptr));
   3171             }
   3172         } else
   3173 #endif /* BCM_KATANA2_SUPPORT */
   3174         {
   3175 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_HURRICANE3_SUPPORT)
   3176             if (soc_feature(unit, soc_feature_src_modid_base_index)) {
   3177                 int old_my_modid = 0;
   3178                 int old_base_index = 0, base_index = 0;
   3179                 int old_num_ports = 0, num_ports = 0;
   3180                 int i;
   3181                 source_trunk_map_table_entry_t stm_entry;
   3182                 source_trunk_map_modbase_entry_t stm_modbase_entry;
   3183 
   3184 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   3185                 if (SOC_IS_TD2P_TT2P(unit)) {
   3186                     src_modid_base_index_bk[unit]->num_ports[my_modid] =
   3187                                                 BCM_STK_TD2P_NUM_LPORTS;
   3188                 }
   3189 #if defined(BCM_MONTEREY_SUPPORT)
   3190                 else if (SOC_IS_MONTEREY(unit)) {
   3191                     src_modid_base_index_bk[unit]->num_ports[my_modid] =
   3192                                                 BCM_STK_MONTEREY_NUM_LPORTS;
   3193                 }
   3194 #endif /* BCM_MONTEREY_SUPPORT */
   3195 #if defined(BCM_APACHE_SUPPORT)
   3196                 else if (SOC_IS_APACHE(unit)) {
   3197                     src_modid_base_index_bk[unit]->num_ports[my_modid] =
   3198                                                 BCM_STK_APACHE_NUM_LPORTS;
   3199                 }
   3200 #endif /* BCM_APACHE_SUPPORT */
   3201 #if defined(BCM_TRIDENT3_SUPPORT)
   3202                 else if (SOC_IS_TRIDENT3X(unit)) {
   3203                     if (SOC_IS_TRIDENT3(unit)) {
   3204                         src_modid_base_index_bk[unit]->num_ports[my_modid] =
   3205                             TRIDENT3_DEV_PORTS_PER_DEV;
   3206                     }
   3207 #if defined(BCM_MAVERICK2_SUPPORT)
   3208                     if (SOC_IS_MAVERICK2(unit)) {
   3209                         src_modid_base_index_bk[unit]->num_ports[my_modid] =
   3210                             MAVERICK2_DEV_PORTS_PER_DEV;
   3211                     }
   3212 #endif
   3213 #if defined(BCM_HELIX5_SUPPORT)
   3214                     if (SOC_IS_HELIX5(unit)) {
   3215                         src_modid_base_index_bk[unit]->num_ports[my_modid] =
   3216                             HELIX5_DEV_PORTS_PER_DEV;
   3217                     }
   3218 #endif
   3219                 }
   3220 #endif /* BCM_TRIDENT3_SUPPORT */
   3221 #endif /* BCM_TRIDENT2PLUS_SUPPORT */
   3222 
   3223                 /* Allocate a source modid base index for new my_modid */
   3224                 BCM_IF_ERROR_RETURN(_bcm_esw_src_modid_base_index_get(unit,
   3225                                     my_modid, 1, &base_index));
   3226 
   3227                 old_my_modid = SOC_BASE_MODID(unit);
   3228                 if (SOC_MODID_ADDRESSABLE(unit, old_my_modid) && 
   3229                         (old_my_modid != my_modid)) {
   3230                     SOC_IF_ERROR_RETURN(READ_SOURCE_TRUNK_MAP_MODBASEm(unit,
   3231                                 MEM_BLOCK_ANY, old_my_modid, &stm_modbase_entry));
   3232                     old_base_index = soc_SOURCE_TRUNK_MAP_MODBASEm_field32_get(unit,
   3233                             &stm_modbase_entry, BASEf);
   3234                     old_num_ports = src_modid_base_index_bk[unit]->num_ports[old_my_modid];
   3235                     if ((0 != old_base_index) || (0 != old_num_ports)) {
   3236                         /* Transfer port attributes from the SOURCE_TRUNK_MAP
   3237                          * region of the old my_modid to the SOURCE_TRUNK_MAP
   3238                          * region of the new my_modid.
   3239                          */
   3240                         if ((!SOC_IS_TD2P_TT2P(unit) && !SOC_IS_APACHE(unit) && !SOC_IS_TRIDENT3X(unit))  ||
   3241                             old_base_index != base_index) {
   3242                             /* For TD2P and APACHE
   3243                              * only transfer if the base idx differs
   3244                              */
   3245                             num_ports = src_modid_base_index_bk[unit]->
   3246                                 num_ports[my_modid];
   3247                             for (i=0; i < old_num_ports && i < num_ports; i++) {
   3248                                 SOC_IF_ERROR_RETURN(
   3249                                     READ_SOURCE_TRUNK_MAP_TABLEm(
   3250                                             unit, MEM_BLOCK_ANY,
   3251                                             i + old_base_index, &stm_entry));
   3252                                 SOC_IF_ERROR_RETURN(
   3253                                     WRITE_SOURCE_TRUNK_MAP_TABLEm(
   3254                                                 unit, MEM_BLOCK_ALL,
   3255                                                 i + base_index, &stm_entry));
   3256                             }
   3257                         }
   3258 
   3259                         /* Release old base index */
   3260                         BCM_IF_ERROR_RETURN(
   3261                             _src_modid_base_index_free(
   3262                                 unit, old_my_modid, old_num_ports));
   3263 
   3264                         /* Reset the number of ports */
   3265                         src_modid_base_index_bk[unit]->num_ports[old_my_modid] = 0;
   3266                     }
   3267                 }
   3268             }
   3269 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   3270             if (soc_feature(unit, soc_feature_td2p_multi_modid)) {
   3271                 uint64 mod_64;
   3272 
   3273                 /*
   3274                  * Program my module id in MY_MODID_SET_64 and
   3275                  * MY_MODID_SET_2_64 registers.
   3276                  */
   3277                 COMPILER_64_ZERO(mod_64);
   3278                 BCM_IF_ERROR_RETURN(READ_MY_MODID_SET_64r(unit, &mod_64));
   3279                 soc_reg64_field32_set(unit, MY_MODID_SET_64r, &mod_64,
   3280                         MODID_0_VALIDf, 1);
   3281                 soc_reg64_field32_set(unit, MY_MODID_SET_64r, &mod_64,
   3282                         MODID_0f, my_modid);
   3283                 BCM_IF_ERROR_RETURN(WRITE_MY_MODID_SET_64r(unit, mod_64));
   3284 
   3285                 COMPILER_64_ZERO(mod_64);
   3286                 BCM_IF_ERROR_RETURN(READ_MY_MODID_SET_2_64r(unit, &mod_64));
   3287                 soc_reg64_field32_set(unit, MY_MODID_SET_2_64r, &mod_64,
   3288                         MODID_0_VALIDf, 1);
   3289                 soc_reg64_field32_set(unit, MY_MODID_SET_2_64r, &mod_64,
   3290                         MODID_0f, my_modid);
   3291 
   3292                 BCM_IF_ERROR_RETURN(WRITE_MY_MODID_SET_2_64r(unit, mod_64));
   3293 
   3294                 COMPILER_64_ZERO(mod_64);
   3295                 BCM_IF_ERROR_RETURN(READ_EGR_MY_MODID_SET_64r(unit, &mod_64));
   3296                 soc_reg64_field32_set(unit, EGR_MY_MODID_SET_64r, &mod_64,
   3297                                       MODID_0_VALIDf, 1);
   3298                 soc_reg64_field32_set(unit, EGR_MY_MODID_SET_64r, &mod_64,
   3299                                       MODID_0f, my_modid);
   3300                 BCM_IF_ERROR_RETURN(WRITE_EGR_MY_MODID_SET_64r(unit, mod_64));
   3301 
   3302                 if (SOC_REG_IS_VALID(unit, IARB_MY_MODID_SET_64r)) {
   3303                     COMPILER_64_ZERO(mod_64);
   3304                     BCM_IF_ERROR_RETURN(READ_IARB_MY_MODID_SET_64r(unit, &mod_64));
   3305                     soc_reg64_field32_set(unit, IARB_MY_MODID_SET_64r, &mod_64,
   3306                                           MODID_0_VALIDf, 1);
   3307                     soc_reg64_field32_set(unit, IARB_MY_MODID_SET_64r, &mod_64,
   3308                                           MODID_0f, my_modid);
   3309                     BCM_IF_ERROR_RETURN(WRITE_IARB_MY_MODID_SET_64r(unit, mod_64));
   3310                 }
   3311             }
   3312 #endif /* BCM_TRIDENT2PLUS_SUPPORT */
   3313 #endif /* BCM_TRIDENT_SUPPORT || BCM_HURRICANE3_SUPPORT */
   3314         }
   3315     }
   3316     break;
   3317 #endif /* BCM_FIREBOLT_SUPPORT */
   3318 
   3319 #if defined(BCM_HERCULES_SUPPORT)
   3320     case BCM_FAMILY_HERCULES:
   3321         if (BCM_MODID_INVALID == my_modid) {
   3322             SOC_CONTROL(unit)->info.modid_count = 0;
   3323         } else {
   3324             SOC_CONTROL(unit)->info.modid_count = 1;
   3325         }
   3326         break;
   3327 #endif /* BCM_HERCULES_SUPPORT */
   3328 
   3329     default:
   3330         return BCM_E_UNAVAIL;
   3331     }
   3332 
   3333     SOC_BASE_MODID_SET(unit, my_modid);
   3334     soc_event_generate(unit, SOC_SWITCH_EVENT_MODID_CHANGE, 0,0,0);
   3335 
   3336    /* Base module id set/get macro */
   3337 
   3338     return BCM_E_NONE;
   3339 }
   3340 
   3341 /*
   3342  * Function:
   3343  *      bcm_stk_my_modid_get
   3344  * Purpose:
   3345  *      Get the MY_MODID field
   3346  * Parameters:
   3347  *      unit  - SOC unit#
   3348  *      my_modid - (out)the value
   3349  * Returns:
   3350  *      BCM_E_XXX
   3351  */
   3352 int
   3353 bcm_esw_stk_my_modid_get(int unit, int *my_modid)
   3354 {
   3355     *my_modid = SOC_BASE_MODID(unit);
   3356 
   3357     if (BCM_MODID_INVALID == *my_modid) {
   3358         return BCM_E_UNAVAIL;
   3359     }
   3360 
   3361     return (BCM_E_NONE);
   3362 }
   3363 
   3364 int
   3365 bcm_stk_modport_voq_cosq_profile_get(int unit, bcm_port_t ing_port, 
   3366                                bcm_module_t dest_modid, int *profile_id)
   3367 {
   3368     if (profile_id == NULL) {
   3369         return BCM_E_PARAM;
   3370     }
   3371 
   3372 #if defined(BCM_TRIDENT_SUPPORT)
   3373     if (SOC_IS_TD_TT(unit)) {
   3374         *profile_id = -1;
   3375         BCM_IF_ERROR_RETURN(
   3376                 bcm_td_stk_modport_voq_op(unit, ing_port, dest_modid,
   3377                     profile_id, _BCM_STK_PORT_MODPORT_DMVOQ_GRP_OP_GET));
   3378         return BCM_E_NONE;
   3379     }
   3380 #endif /* BCM_TRIDENT_SUPPORT */
   3381 
   3382     return BCM_E_UNAVAIL;
   3383 }
   3384 
   3385 int
   3386 bcm_stk_modport_voq_cosq_profile_set(int unit, bcm_port_t ing_port, 
   3387                                bcm_module_t dest_modid, int profile_id)
   3388 {
   3389 #if defined(BCM_TRIDENT_SUPPORT)
   3390     if (SOC_IS_TD_TT(unit)) {
   3391         BCM_IF_ERROR_RETURN(
   3392                 bcm_td_stk_modport_voq_op(unit, ing_port, dest_modid,
   3393                     &profile_id, _BCM_STK_PORT_MODPORT_DMVOQ_GRP_OP_SET));
   3394         return BCM_E_NONE;
   3395     }
   3396 #endif /* BCM_TRIDENT_SUPPORT */
   3397 
   3398     return BCM_E_UNAVAIL;
   3399 }
   3400 
   3401 #if defined(BCM_WARM_BOOT_SUPPORT) 
   3402 /*
   3403  * Function:
   3404  *      bcm_esw_reload_stk_my_modid_get
   3405  * Purpose:
   3406  *      Get the MY_MODID field
   3407  * Parameters:
   3408  *      unit  - SOC unit#
   3409  * Returns:
   3410  *      BCM_E_XXX
   3411  * Note:
   3412  *      This routine is being called by _bcm_modules_init(), so it is not
   3413  *      not called by the Stack init routine.
   3414  */
   3415 int
   3416 bcm_esw_reload_stk_my_modid_get(int unit)
   3417 {
   3418     uint32 config;
   3419     int blk, port;
   3420     bcm_module_t my_modid = 0;
   3421     soc_mem_t port_tab = PORT_TABm;
   3422 
   3423     COMPILER_REFERENCE(config);
   3424     COMPILER_REFERENCE(blk);
   3425     COMPILER_REFERENCE(port);
   3426 
   3427     if (SOC_MEM_IS_VALID(unit, ING_DEVICE_PORTm)) {
   3428         port_tab = ING_DEVICE_PORTm;
   3429     }
   3430 
   3431     switch (BCM_CHIP_FAMILY(unit)) {
   3432 
   3433 #if defined(BCM_FIREBOLT_SUPPORT)
   3434     case BCM_FAMILY_FIREBOLT:
   3435     case BCM_FAMILY_BRADLEY:
   3436     case BCM_FAMILY_HUMV:
   3437     case BCM_FAMILY_TRIUMPH:
   3438     case BCM_FAMILY_SCORPION:
   3439     case BCM_FAMILY_CONQUEROR:
   3440     case BCM_FAMILY_TRIUMPH2:
   3441     case BCM_FAMILY_TITAN:
   3442     case BCM_FAMILY_TRIDENT:
   3443     case BCM_FAMILY_KATANA:
   3444         PBMP_PORT_ITER(unit, port) {
   3445             port_tab_entry_t pte;
   3446             BCM_IF_ERROR_RETURN
   3447                 (soc_mem_read(unit, port_tab, MEM_BLOCK_ANY, port, &pte));
   3448             if (soc_mem_field_valid(unit, port_tab, MY_MODIDf)) {
   3449                 my_modid = soc_mem_field32_get(unit, port_tab, &pte, MY_MODIDf);
   3450             }
   3451             break;
   3452         }
   3453 #endif
   3454 #ifdef BCM_KATANA2_SUPPORT
   3455         if (SOC_IS_KATANA2(unit)) {
   3456             int my_modid_list[KT2_MAX_MODIDS_PER_TRANSLATION_TABLE] = {0};
   3457             int my_modid_valid[KT2_MAX_MODIDS_PER_TRANSLATION_TABLE] = {0};
   3458             int my_modport_base_ptr[KT2_MAX_MODIDS_PER_TRANSLATION_TABLE] = {0};
   3459 
   3460             BCM_IF_ERROR_RETURN(
   3461                 bcm_kt2_modid_get_all(unit, my_modid_list, my_modid_valid,
   3462                                       my_modport_base_ptr));
   3463             my_modid = my_modid_list[0];
   3464         }
   3465 #endif
   3466         break;
   3467 
   3468 #if defined(BCM_HERCULES_SUPPORT)
   3469     case BCM_FAMILY_HERCULES:
   3470         if (SOC_CONTROL(unit)->info.modid_count > 0) {
   3471             my_modid = SOC_DEFAULT_DMA_SRCMOD_GET(unit);
   3472         } else {
   3473             return BCM_E_UNAVAIL;
   3474         }
   3475         break;
   3476 #endif /* BCM_HERCULES_SUPPORT */
   3477 
   3478     default:
   3479         return BCM_E_UNAVAIL;
   3480     }
   3481 
   3482     SOC_BASE_MODID_SET(unit, my_modid);    
   3483     SOC_DEFAULT_DMA_SRCMOD_SET(unit, my_modid);
   3484     return BCM_E_NONE;
   3485 }
   3486 #endif /* BCM_WARM_BOOT_SUPPORT */
   3487 
   3488 #if defined(BCM_TRX_SUPPORT)
   3489 STATIC int
   3490 _bcm_stk_modport_profile_init(int unit)
   3491 {
   3492     soc_mem_t mem;
   3493     int entry_words;
   3494     soc_profile_mem_t *profile;
   3495     void *entry;
   3496     uint32 base_index, index;
   3497     int rv, modid_count, port_count, alloc_size, port;
   3498 
   3499     if (modport_profile[unit] == NULL) {
   3500         modport_profile[unit] = sal_alloc(sizeof(soc_profile_mem_t),
   3501                                              "ModPort Profile Mem");
   3502         if (modport_profile[unit] == NULL) {
   3503             return BCM_E_MEMORY;
   3504         }
   3505     } else {
   3506         soc_profile_mem_destroy(unit, modport_profile[unit]);
   3507     }
   3508     profile = modport_profile[unit];
   3509     soc_profile_mem_t_init(profile);
   3510 
   3511     mem = MODPORT_MAPm;
   3512     entry_words = sizeof(modport_map_entry_t) / sizeof(uint32);
   3513 
   3514     BCM_IF_ERROR_RETURN
   3515         (soc_profile_mem_create(unit, &mem, &entry_words, 1, profile));
   3516 
   3517     modid_count = SOC_MODID_MAX(unit) + 1;
   3518 
   3519     if (SOC_WARM_BOOT(unit) || SOC_IS_RCPU_ONLY(unit)) {    /* Warm Boot */
   3520         int     i;
   3521         uint32  val;
   3522 
   3523         /* Gather reference count for modport map profile table */
   3524         PBMP_ALL_ITER(unit, port) {
   3525             SOC_IF_ERROR_RETURN
   3526                 (READ_MODPORT_MAP_SELr(unit, port, &val));
   3527             index = soc_reg_field_get(unit, MODPORT_MAP_SELr, val,
   3528                                       MODPORT_MAP_INDEX_UPPERf);
   3529             index *= modid_count;
   3530             for (i = 0; i < modid_count; i++) {
   3531                 SOC_PROFILE_MEM_REFERENCE(unit, modport_profile[unit],
   3532                                           index + i, 1);
   3533                 SOC_PROFILE_MEM_ENTRIES_PER_SET(unit,
   3534                                                 modport_profile[unit],
   3535                                                 index + i,
   3536                                                 modid_count);
   3537             }
   3538         }
   3539 
   3540         return BCM_E_NONE;
   3541     }
   3542 
   3543     alloc_size = modid_count * entry_words * sizeof(uint32);
   3544     entry = sal_alloc(alloc_size, "modport_map_entry");
   3545     if (entry == NULL) {
   3546         return BCM_E_MEMORY;
   3547     }
   3548     sal_memset(entry, 0, alloc_size);
   3549     rv = soc_profile_mem_add(unit, profile, &entry, modid_count, &base_index);
   3550     sal_free(entry);
   3551     if (BCM_FAILURE(rv)) {
   3552         return rv;
   3553     }
   3554 
   3555     port_count = 0;
   3556     PBMP_ALL_ITER(unit, port) {
   3557         BCM_IF_ERROR_RETURN
   3558             (WRITE_MODPORT_MAP_SELr(unit, port, base_index / modid_count));
   3559         port_count++;
   3560     }
   3561 
   3562     for (index = 0; index < modid_count; index++) {
   3563         SOC_PROFILE_MEM_REFERENCE(unit, profile, base_index + index,
   3564                                   port_count - 1);
   3565     }
   3566 
   3567     return BCM_E_NONE;
   3568 }
   3569 
   3570 STATIC int
   3571 bcmi_trx_stk_port_modport_op(int unit, int op, bcm_port_t ing_port,
   3572                              bcm_module_t dest_modid, bcm_port_t *dest_port,
   3573                              int dest_port_count)
   3574 {
   3575     int rv;
   3576     int modid_count, modid_min, modid_max;
   3577     pbmp_t pbmp, hg_trunk_pbmp, new_pbmp;
   3578     int index;
   3579     int tid;
   3580     bcm_trunk_chip_info_t chip_info;
   3581     bcm_trunk_member_t member;
   3582     int member_count;
   3583     bcm_port_t local_port;
   3584     uint32 base_index, new_base_index;
   3585     soc_profile_mem_t *profile;
   3586     modport_map_entry_t *entry_array;
   3587     void *entries;
   3588     uint32 rval;
   3589     uint8 istrunk[SOC_MAX_NUM_PORTS];
   3590     uint8 dest[SOC_MAX_NUM_PORTS];
   3591     int old_profile_index, new_profile_index;
   3592     bcmi_trx_modport_map_entry_t *trx_entry_array;
   3593     int ref_count;
   3594 
   3595     if (!soc_feature(unit,
   3596                      soc_feature_modport_map_dest_is_hg_port_bitmap)) {
   3597         return BCM_E_UNAVAIL;
   3598     }
   3599 
   3600     if (op <= 0 || op >= _BCM_STK_PORT_MODPORT_OP_COUNT) {
   3601         return BCM_E_PARAM;
   3602     }
   3603 
   3604     if (BCM_GPORT_IS_SET(ing_port)) {
   3605         BCM_IF_ERROR_RETURN(
   3606             bcm_esw_port_local_get(unit, ing_port, &ing_port));
   3607     }
   3608 
   3609     if (!SOC_PORT_VALID(unit, ing_port)) {
   3610         return BCM_E_PORT;
   3611     }
   3612 
   3613     modid_count = SOC_MODID_MAX(unit) + 1;
   3614     if (dest_modid == -1) {
   3615         modid_min = 0;
   3616         modid_max = modid_count - 1;
   3617     } else {
   3618         if (!SOC_MODID_ADDRESSABLE(unit, dest_modid)) {
   3619             return BCM_E_PARAM;
   3620         }
   3621         modid_min = modid_max = dest_modid;
   3622     }
   3623 
   3624     if (dest_port_count > SOC_MAX_NUM_PORTS) {
   3625         return BCM_E_INTERNAL;
   3626     }
   3627 
   3628     sal_memset(istrunk, 0, (sizeof(uint8) * SOC_MAX_NUM_PORTS));
   3629     sal_memset(dest, 0, (sizeof(uint8) * SOC_MAX_NUM_PORTS));
   3630 
   3631     BCM_PBMP_CLEAR(pbmp);
   3632     for (index = 0; index < dest_port_count; index++) {
   3633         if (BCM_GPORT_IS_TRUNK(dest_port[index])) {
   3634             tid = SOC_GPORT_TRUNK_GET(dest_port[index]);
   3635 
   3636             BCM_IF_ERROR_RETURN(
   3637                 bcm_esw_trunk_chip_info_get(unit, &chip_info));
   3638             if (chip_info.trunk_fabric_id_min < 0 ||
   3639                 tid < chip_info.trunk_fabric_id_min ||
   3640                 tid > chip_info.trunk_fabric_id_max) {
   3641                 return BCM_E_PARAM;
   3642             }
   3643 
   3644             /* Get Higig trunk group port bitmap */
   3645             BCM_IF_ERROR_RETURN(
   3646                 bcm_esw_trunk_get(unit, tid, NULL, 1, &member, &member_count));
   3647             if (member_count == 0) {
   3648                 /* No ports have been added to the Higig trunk group */
   3649                 return BCM_E_PARAM;
   3650             }
   3651             BCM_IF_ERROR_RETURN(
   3652                 bcm_esw_port_local_get(unit, member.gport, &local_port));
   3653             BCM_PBMP_PORT_SET(hg_trunk_pbmp, local_port);
   3654             BCM_IF_ERROR_RETURN(
   3655                 bcm_esw_trunk_bitmap_expand(unit, &hg_trunk_pbmp));
   3656             BCM_PBMP_OR(pbmp, hg_trunk_pbmp);
   3657 
   3658             BCM_PBMP_ITER(pbmp, local_port) {
   3659                 istrunk[local_port] = 1;
   3660                 dest[local_port] = tid - chip_info.trunk_fabric_id_min;
   3661             }
   3662         } else {
   3663             if (!SOC_PORT_VALID(unit, dest_port[index])) {
   3664                 return BCM_E_PORT;
   3665             }
   3666 
   3667             if (dest_port[index] == CMIC_PORT(unit) &&
   3668                 BCM_CHIP_FAMILY(unit) == BCM_FAMILY_TRIUMPH) {
   3669                 return BCM_E_PORT;
   3670             }
   3671 
   3672             BCM_PBMP_PORT_ADD(pbmp, dest_port[index]);
   3673             istrunk[dest_port[index]] = 0;
   3674             dest[dest_port[index]] = dest_port[index];
   3675         }
   3676     }
   3677 
   3678     /* Profile style MODPORT MAP bitmap table */
   3679     if (modport_profile[unit] == NULL) {
   3680         _bcm_stk_modport_profile_init(unit);
   3681     }
   3682     profile = modport_profile[unit];
   3683 
   3684     entry_array = sal_alloc(sizeof(modport_map_entry_t) * modid_count,
   3685                             "modport_map_entry");
   3686     if (entry_array == NULL) {
   3687         return BCM_E_MEMORY;
   3688     }
   3689 
   3690     trx_entry_array =
   3691         sal_alloc((sizeof(bcmi_trx_modport_map_entry_t) * modid_count),
   3692                   "trx_modport_map_entry");
   3693     if (trx_entry_array == NULL) {
   3694         sal_free(entry_array);
   3695         return BCM_E_MEMORY;
   3696     }
   3697 
   3698     soc_mem_lock(unit, MODPORT_MAPm);
   3699     rv = READ_MODPORT_MAP_SELr(unit, ing_port, &rval);
   3700     if (BCM_FAILURE(rv)) {
   3701         soc_mem_unlock(unit, MODPORT_MAPm);
   3702         sal_free(entry_array);
   3703         sal_free(trx_entry_array);
   3704         return rv;
   3705     }
   3706 
   3707     old_profile_index = soc_reg_field_get(unit, MODPORT_MAP_SELr, rval,
   3708                                           MODPORT_MAP_INDEX_UPPERf);
   3709     base_index = (modid_count * old_profile_index);
   3710 
   3711     for (index = 0; index < modid_count; index++) {
   3712         sal_memcpy(&entry_array[index],
   3713                    SOC_PROFILE_MEM_ENTRY(unit, profile, void *,
   3714                                          base_index + index),
   3715                    sizeof(modport_map_entry_t));
   3716         sal_memcpy(
   3717             &trx_entry_array[index],
   3718             &TRX_MODPORT_MAP_PROFILE
   3719                  (unit, old_profile_index).entry_array[index],
   3720             sizeof(bcmi_trx_modport_map_entry_t));
   3721     }
   3722     for (index = modid_min; index <= modid_max; index++) {
   3723         switch (op) {
   3724         case _BCM_STK_PORT_MODPORT_OP_SET:
   3725             /* Clear original port bitmap */
   3726             sal_memset(&trx_entry_array[index], 0,
   3727                        (sizeof(bcmi_trx_modport_map_entry_t)));
   3728             /* Set new port bitmap */
   3729             BCM_PBMP_ITER(pbmp, local_port) {
   3730                 if (istrunk[local_port]) {
   3731                     trx_entry_array[index].dest_istrunk[local_port] = 1;
   3732                 }
   3733                 trx_entry_array[index].dest[local_port] =
   3734                     dest[local_port];
   3735             }
   3736             BCM_PBMP_ASSIGN(new_pbmp, pbmp);
   3737             break;
   3738         case _BCM_STK_PORT_MODPORT_OP_ADD:
   3739             /* Set new port bitmap */
   3740             BCM_PBMP_ITER(pbmp, local_port) {
   3741                 if (istrunk[local_port]) {
   3742                     trx_entry_array[index].dest_istrunk[local_port] = 1;
   3743                 }
   3744                 trx_entry_array[index].dest[local_port] =
   3745                     dest[local_port];
   3746             }
   3747             soc_mem_pbmp_field_get(unit, MODPORT_MAPm, &entry_array[index],
   3748                                    HIGIG_PORT_BITMAPf, &new_pbmp);
   3749             BCM_PBMP_OR(new_pbmp, pbmp);
   3750             break;
   3751         case _BCM_STK_PORT_MODPORT_OP_DELETE:
   3752             /* Remove port bitmap */
   3753             BCM_PBMP_ITER(pbmp, local_port) {
   3754                 if (istrunk[local_port]) {
   3755                     trx_entry_array[index].dest_istrunk[local_port] = 0;
   3756                 }
   3757                 trx_entry_array[index].dest[local_port] = 0;
   3758             }
   3759             soc_mem_pbmp_field_get(unit, MODPORT_MAPm, &entry_array[index],
   3760                                    HIGIG_PORT_BITMAPf, &new_pbmp);
   3761             BCM_PBMP_REMOVE(new_pbmp, pbmp);
   3762             break;
   3763         /*default case is must in order to avoid compilatioin error */
   3764         /* coverity[dead_error_begin] */
   3765         default:
   3766             soc_mem_unlock(unit, MODPORT_MAPm);
   3767             sal_free(entry_array);
   3768             sal_free(trx_entry_array);
   3769             return BCM_E_INTERNAL;
   3770         }
   3771         soc_mem_pbmp_field_set(unit, MODPORT_MAPm, &entry_array[index],
   3772                                HIGIG_PORT_BITMAPf, &new_pbmp);
   3773     }
   3774     entries = entry_array;
   3775     rv = soc_profile_mem_add(unit, profile, &entries, modid_count,
   3776                              &new_base_index);
   3777     if (BCM_SUCCESS(rv)) {
   3778         new_profile_index = (new_base_index / modid_count);
   3779         soc_reg_field_set(unit, MODPORT_MAP_SELr, &rval,
   3780                           MODPORT_MAP_INDEX_UPPERf,
   3781                           new_profile_index);
   3782         rv = WRITE_MODPORT_MAP_SELr(unit, ing_port, rval);
   3783     }
   3784     if (BCM_SUCCESS(rv)) {
   3785         sal_memcpy(
   3786             TRX_MODPORT_MAP_PROFILE
   3787                 (unit, new_profile_index).entry_array,
   3788             trx_entry_array,
   3789             (sizeof(bcmi_trx_modport_map_entry_t) * modid_count));
   3790         TRX_MODPORT_MAP_PROFILE(unit, new_profile_index).ref_count++;
   3791         rv = soc_profile_mem_delete(unit, profile, base_index);
   3792         if (BCM_SUCCESS(rv)) {
   3793             if (TRX_MODPORT_MAP_PROFILE
   3794                     (unit, old_profile_index).ref_count >= 1) {
   3795                 TRX_MODPORT_MAP_PROFILE(unit,
   3796                                         old_profile_index).ref_count--;
   3797                 ref_count =
   3798                     TRX_MODPORT_MAP_PROFILE
   3799                         (unit, old_profile_index).ref_count;
   3800                 /* Clear old profile when ref_count = 0 */
   3801                 if (ref_count == 0) {
   3802                     sal_memset(
   3803                         TRX_MODPORT_MAP_PROFILE
   3804                             (unit, old_profile_index).entry_array,
   3805                         0,
   3806                         (sizeof(bcmi_trx_modport_map_entry_t) *
   3807                         modid_count));
   3808                 }
   3809             }
   3810         }
   3811     }
   3812     soc_mem_unlock(unit, MODPORT_MAPm);
   3813     sal_free(entry_array);
   3814     sal_free(trx_entry_array);
   3815 
   3816     return rv;
   3817 }
   3818 
   3819 STATIC int
   3820 bcmi_trx_stk_port_modport_get(int unit, bcm_port_t ing_port,
   3821                               bcm_module_t dest_modid, int dest_port_max,
   3822                               bcm_port_t *dest_port_array,
   3823                               int *dest_port_count)
   3824 {
   3825     int modid_count, base_index;
   3826     soc_profile_mem_t *profile;
   3827     modport_map_entry_t *entry_p;
   3828     pbmp_t pbmp;
   3829     uint32 rval;
   3830     int count, port;
   3831     bcm_trunk_chip_info_t chip_info;
   3832     bcm_trunk_t tid = -1;
   3833     int profile_index = 0;
   3834     bcmi_trx_modport_map_entry_t *trx_entry_p = NULL;
   3835     int istrunk, dest;
   3836 
   3837     if (!soc_feature(unit,
   3838                      soc_feature_modport_map_dest_is_hg_port_bitmap)) {
   3839         return BCM_E_UNAVAIL;
   3840     }
   3841 
   3842     if (BCM_GPORT_IS_SET(ing_port)) {
   3843         BCM_IF_ERROR_RETURN(
   3844             bcm_esw_port_local_get(unit, ing_port, &ing_port));
   3845     }
   3846     if (!SOC_PORT_VALID(unit, ing_port)) {
   3847         return BCM_E_PORT;
   3848     }
   3849     if (!SOC_MODID_ADDRESSABLE(unit, dest_modid)) {
   3850         return BCM_E_PARAM;
   3851     }
   3852     if (dest_port_max < 0 ||
   3853         ((dest_port_max > 0) && (dest_port_array == NULL)) ||
   3854         dest_port_count == NULL) {
   3855         return BCM_E_PARAM;
   3856     }
   3857 
   3858     modid_count = SOC_MODID_MAX(unit) + 1;
   3859 
   3860     if (modport_profile[unit] == NULL) {
   3861         *dest_port_count = 0;
   3862         return BCM_E_NOT_FOUND;
   3863     }
   3864 
   3865     profile = modport_profile[unit];
   3866 
   3867     BCM_IF_ERROR_RETURN(READ_MODPORT_MAP_SELr(unit, ing_port, &rval));
   3868     profile_index = soc_reg_field_get(unit, MODPORT_MAP_SELr, rval,
   3869                                       MODPORT_MAP_INDEX_UPPERf);
   3870     base_index = (modid_count * profile_index);
   3871     entry_p = SOC_PROFILE_MEM_ENTRY(unit, profile, modport_map_entry_t *,
   3872                                     base_index + dest_modid);
   3873     trx_entry_p = &TRX_MODPORT_MAP_PROFILE
   3874                       (unit, profile_index).entry_array[dest_modid];
   3875 
   3876     soc_mem_pbmp_field_get(unit, MODPORT_MAPm, entry_p,
   3877                            HIGIG_PORT_BITMAPf, &pbmp);
   3878     count = 0;
   3879     BCM_PBMP_ITER(pbmp, port) {
   3880         if (dest_port_max > count) {
   3881             istrunk = trx_entry_p->dest_istrunk[port];
   3882             dest = trx_entry_p->dest[port];
   3883             if (istrunk) {
   3884                 BCM_IF_ERROR_RETURN(
   3885                     bcm_esw_trunk_chip_info_get(unit, &chip_info));
   3886                 tid = dest + chip_info.trunk_fabric_id_min;
   3887                 BCM_GPORT_TRUNK_SET(dest_port_array[count], tid);
   3888             } else {
   3889                 dest_port_array[count] = dest;
   3890             }
   3891         }
   3892         if ((dest_port_max != 0) &&
   3893             (count == dest_port_max)) {
   3894             break;
   3895         }
   3896         count++;
   3897     }
   3898     *dest_port_count = count;
   3899 
   3900     return *dest_port_count ? BCM_E_NONE : BCM_E_NOT_FOUND;
   3901 }
   3902 #endif /* BCM_TRX_SUPPORT */
   3903 
   3904 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT)
   3905 
   3906 STATIC int
   3907 _bcm_stk_port_modport_op(int unit, int op, bcm_port_t ing_port,
   3908                          bcm_module_t dest_modid, bcm_port_t *dest_port,
   3909                          int dest_port_count)
   3910 {
   3911     int    modid_count, modid_min, modid_max;
   3912     pbmp_t pbmp, hg_trunk_pbmp, hg_pbmp;
   3913     int    index;
   3914     int    tid;
   3915     bcm_trunk_chip_info_t chip_info;
   3916     bcm_trunk_member_t member;
   3917     int member_count;
   3918     bcm_port_t local_port;
   3919     modport_map_entry_t entry;
   3920     int    rv;
   3921     uint32 base_index;
   3922     uint32 hg_pbmp32, new_hg_pbmp32;
   3923 #if defined(BCM_TRX_SUPPORT)
   3924     pbmp_t new_pbmp;
   3925     soc_profile_mem_t *profile;
   3926     modport_map_entry_t *entry_array;
   3927     void  *entries;
   3928     uint32 rval;
   3929     uint32 new_base_index;
   3930 #endif /* BCM_TRX_SUPPORT */
   3931 
   3932 #if defined(BCM_TRX_SUPPORT)
   3933     if (soc_feature(unit, soc_feature_modport_map_dest_is_hg_port_bitmap)) {
   3934         return bcmi_trx_stk_port_modport_op(unit, op, ing_port, dest_modid,
   3935                                             dest_port, dest_port_count);
   3936     }
   3937 #endif /* BCM_TRX_SUPPORT */
   3938 
   3939     if (op <= 0 || op >= _BCM_STK_PORT_MODPORT_OP_COUNT) {
   3940         return BCM_E_PARAM;
   3941     }
   3942 
   3943     if (BCM_GPORT_IS_SET(ing_port)) {
   3944         BCM_IF_ERROR_RETURN(
   3945             bcm_esw_port_local_get(unit, ing_port, &ing_port));
   3946     }
   3947 
   3948     if (!SOC_PORT_VALID(unit, ing_port)) {
   3949         return BCM_E_PORT;
   3950     }
   3951 
   3952     modid_count = SOC_MODID_MAX(unit) + 1;
   3953     if (dest_modid == -1) {
   3954         modid_min = 0;
   3955         modid_max = modid_count - 1;
   3956     } else {
   3957         if (!SOC_MODID_ADDRESSABLE(unit, dest_modid)) {
   3958             return BCM_E_PARAM;
   3959         }
   3960         modid_min = modid_max = dest_modid;
   3961     }
   3962 
   3963     if (dest_port_count > SOC_MAX_NUM_PORTS) {
   3964         return BCM_E_INTERNAL;
   3965     }
   3966 
   3967     BCM_PBMP_CLEAR(pbmp);
   3968     for (index = 0; index < dest_port_count; index++) {
   3969 
   3970         if (BCM_GPORT_IS_TRUNK(dest_port[index])) {
   3971             tid = SOC_GPORT_TRUNK_GET(dest_port[index]);
   3972 
   3973             BCM_IF_ERROR_RETURN(bcm_esw_trunk_chip_info_get(unit, &chip_info));
   3974             if (chip_info.trunk_fabric_id_min < 0 || 
   3975                     tid < chip_info.trunk_fabric_id_min || 
   3976                     tid > chip_info.trunk_fabric_id_max) { 
   3977                 return BCM_E_PARAM;
   3978             }
   3979 
   3980             /* Get Higig trunk group port bitmap */
   3981             BCM_IF_ERROR_RETURN(bcm_esw_trunk_get(unit, tid, NULL,
   3982                         1, &member, &member_count));
   3983             if (member_count == 0) {
   3984                 /* No ports have been added to the Higig trunk group */
   3985                 return BCM_E_PARAM;
   3986             }
   3987             BCM_IF_ERROR_RETURN(bcm_esw_port_local_get(unit,
   3988                         member.gport, &local_port));
   3989             BCM_PBMP_PORT_SET(hg_trunk_pbmp, local_port);
   3990             BCM_IF_ERROR_RETURN
   3991                 (bcm_esw_trunk_bitmap_expand(unit, &hg_trunk_pbmp));
   3992             BCM_PBMP_OR(pbmp, hg_trunk_pbmp);
   3993 
   3994         } else {
   3995             if (!SOC_PORT_VALID(unit, dest_port[index])) {
   3996                 return BCM_E_PORT;
   3997             }
   3998 
   3999             if (dest_port[index] == CMIC_PORT(unit) &&
   4000                     BCM_CHIP_FAMILY(unit) == BCM_FAMILY_TRIUMPH) {
   4001                 return BCM_E_PORT;
   4002             }
   4003 
   4004             BCM_PBMP_PORT_ADD(pbmp, dest_port[index]);
   4005         }
   4006     }
   4007 
   4008 #if defined(BCM_TRX_SUPPORT)
   4009 
   4010     if (SOC_IS_TR_VL(unit)) {
   4011         /* Profile style MODPORT MAP bitmap table */
   4012         if (modport_profile[unit] == NULL) {
   4013             _bcm_stk_modport_profile_init(unit);
   4014         }
   4015         profile = modport_profile[unit];
   4016 
   4017         if (SOC_IS_TRIUMPH(unit) || SOC_IS_VALKYRIE(unit) ||
   4018             SOC_IS_ENDURO(unit) || SOC_IS_HURRICANE(unit) ||
   4019             SOC_IS_HURRICANE2(unit)) {
   4020             BCM_IF_ERROR_RETURN
   4021                 (soc_xgs3_bitmap_to_higig_bitmap(unit, pbmp, &hg_pbmp));
   4022             BCM_PBMP_ASSIGN(pbmp, hg_pbmp);
   4023         }
   4024 
   4025         entry_array = sal_alloc(sizeof(modport_map_entry_t) * modid_count,
   4026                                 "modport_map_entry");
   4027         if (entry_array == NULL) {
   4028             return BCM_E_MEMORY;
   4029         }
   4030 
   4031         soc_mem_lock(unit, MODPORT_MAPm);
   4032         rv = READ_MODPORT_MAP_SELr(unit, ing_port, &rval);
   4033         if (BCM_FAILURE(rv)) {
   4034             soc_mem_unlock(unit, MODPORT_MAPm);
   4035             sal_free(entry_array);
   4036             return rv;
   4037         }
   4038         base_index = modid_count *
   4039                      soc_reg_field_get(unit, MODPORT_MAP_SELr, rval,
   4040                                        MODPORT_MAP_INDEX_UPPERf);
   4041         for (index = 0; index < modid_count; index++) {
   4042             sal_memcpy(&entry_array[index],
   4043                        SOC_PROFILE_MEM_ENTRY(unit, profile, void *,
   4044                                              base_index + index),
   4045                        sizeof(modport_map_entry_t));
   4046         }
   4047         for (index = modid_min; index <= modid_max; index++) {
   4048             switch (op) {
   4049             case _BCM_STK_PORT_MODPORT_OP_SET:
   4050                 BCM_PBMP_ASSIGN(new_pbmp, pbmp);
   4051                 break;
   4052             case _BCM_STK_PORT_MODPORT_OP_ADD:
   4053                 soc_mem_pbmp_field_get(unit, MODPORT_MAPm, &entry_array[index],
   4054                                        HIGIG_PORT_BITMAPf, &new_pbmp);
   4055                 BCM_PBMP_OR(new_pbmp, pbmp);
   4056                 break;
   4057             case _BCM_STK_PORT_MODPORT_OP_DELETE:
   4058                 soc_mem_pbmp_field_get(unit, MODPORT_MAPm, &entry_array[index],
   4059                                        HIGIG_PORT_BITMAPf, &new_pbmp);
   4060                 BCM_PBMP_REMOVE(new_pbmp, pbmp);
   4061                 break;
   4062             /*default case is must in order to avoid compilatioin error */
   4063             /* coverity[dead_error_begin] */
   4064             default:
   4065                 soc_mem_unlock(unit, MODPORT_MAPm);
   4066                 sal_free(entry_array);
   4067                 return BCM_E_INTERNAL;
   4068             }
   4069             soc_mem_pbmp_field_set(unit, MODPORT_MAPm, &entry_array[index],
   4070                                    HIGIG_PORT_BITMAPf, &new_pbmp);
   4071         }
   4072         entries = entry_array;
   4073         rv = soc_profile_mem_add(unit, profile, &entries, modid_count,
   4074                                  &new_base_index);
   4075         if (BCM_SUCCESS(rv)) {
   4076             soc_reg_field_set(unit, MODPORT_MAP_SELr, &rval,
   4077                               MODPORT_MAP_INDEX_UPPERf,
   4078                               new_base_index / modid_count);
   4079             rv = WRITE_MODPORT_MAP_SELr(unit, ing_port, rval);
   4080         }
   4081         if (BCM_SUCCESS(rv)) {
   4082             rv = soc_profile_mem_delete(unit, profile, base_index);
   4083         }
   4084         soc_mem_unlock(unit, MODPORT_MAPm);
   4085         sal_free(entry_array);
   4086     } else
   4087 #endif /* BCM_TRX_SUPPORT */
   4088 
   4089     if (SOC_IS_HBX(unit)) {
   4090         /* Per port style MODPORT MAP bitmap table */
   4091         BCM_IF_ERROR_RETURN
   4092             (soc_xgs3_bitmap_to_higig_bitmap(unit, pbmp, &hg_pbmp));
   4093         hg_pbmp32 = SOC_PBMP_WORD_GET(hg_pbmp, 0);
   4094         base_index = ing_port * modid_count;
   4095 
   4096         rv = BCM_E_NONE;
   4097         soc_mem_lock(unit, MODPORT_MAPm);
   4098         for (index = modid_min; index <= modid_max; index++) {
   4099             rv = READ_MODPORT_MAPm(unit, MEM_BLOCK_ANY, base_index + index,
   4100                                    &entry);
   4101             if (BCM_FAILURE(rv)) {
   4102                 soc_mem_unlock(unit, MODPORT_MAPm);
   4103                 return rv;
   4104             }
   4105             switch (op) {
   4106             case _BCM_STK_PORT_MODPORT_OP_SET:
   4107                 new_hg_pbmp32 = hg_pbmp32;
   4108                 break;
   4109             case _BCM_STK_PORT_MODPORT_OP_ADD:
   4110                 new_hg_pbmp32 =
   4111                     soc_mem_field32_get(unit, MODPORT_MAPm, &entry,
   4112                                         HIGIG_PORT_BITMAPf);
   4113                 new_hg_pbmp32 |= hg_pbmp32;
   4114                     break;
   4115             case _BCM_STK_PORT_MODPORT_OP_DELETE:
   4116                 new_hg_pbmp32 =
   4117                     soc_mem_field32_get(unit, MODPORT_MAPm, &entry,
   4118                                         HIGIG_PORT_BITMAPf);
   4119                 new_hg_pbmp32 &= ~hg_pbmp32;
   4120                 break;
   4121             /*default case is must in order to avoid compilatioin error */
   4122             /* coverity[dead_error_begin] */ 
   4123             default:
   4124                 soc_mem_unlock(unit, MODPORT_MAPm);
   4125                 return BCM_E_INTERNAL;
   4126             }
   4127             soc_mem_field32_set(unit, MODPORT_MAPm, &entry,
   4128                                 HIGIG_PORT_BITMAPf, new_hg_pbmp32);
   4129             rv = WRITE_MODPORT_MAPm(unit, MEM_BLOCK_ANY, base_index + index,
   4130                                     &entry);
   4131         }
   4132         soc_mem_unlock(unit, MODPORT_MAPm);
   4133 
   4134     } else {
   4135         rv = BCM_E_UNAVAIL;
   4136     }
   4137 
   4138     return rv;
   4139 }
   4140 
   4141 STATIC int
   4142 _bcm_stk_port_modport_get(int unit, bcm_port_t ing_port,
   4143                           bcm_module_t dest_modid, int dest_port_max,
   4144                           bcm_port_t *dest_port_array,
   4145                           int *dest_port_count)
   4146 {
   4147     uint32 hg_pbmp;
   4148     modport_map_entry_t entry;
   4149     int modid_count, base_index;
   4150 #if defined(BCM_TRX_SUPPORT)
   4151     soc_profile_mem_t *profile;
   4152     modport_map_entry_t *entry_p;
   4153     pbmp_t pbmp;
   4154     uint32 rval;
   4155     int count, port;
   4156 #endif /* BCM_TRX_SUPPORT */
   4157 
   4158 #if defined(BCM_TRX_SUPPORT)
   4159     if (soc_feature(unit, soc_feature_modport_map_dest_is_hg_port_bitmap)) {
   4160         return bcmi_trx_stk_port_modport_get(unit, ing_port, dest_modid,
   4161                                              dest_port_max, dest_port_array,
   4162                                              dest_port_count);
   4163     }
   4164 #endif /* BCM_TRX_SUPPORT */
   4165 
   4166     if (BCM_GPORT_IS_SET(ing_port)) {
   4167         BCM_IF_ERROR_RETURN(
   4168             bcm_esw_port_local_get(unit, ing_port, &ing_port));
   4169     }
   4170     if (!SOC_PORT_VALID(unit, ing_port)) {
   4171         return BCM_E_PORT;
   4172     }
   4173     if (!SOC_MODID_ADDRESSABLE(unit, dest_modid)) {
   4174         return BCM_E_PARAM;
   4175     }
   4176     if (dest_port_max < 0 ||
   4177         ((dest_port_max > 0) && (dest_port_array == NULL)) ||
   4178         dest_port_count == NULL) {
   4179         return BCM_E_PARAM;
   4180     }
   4181 
   4182     modid_count = SOC_MODID_MAX(unit) + 1;
   4183 
   4184 #if defined(BCM_TRX_SUPPORT)
   4185 
   4186     if (SOC_IS_TR_VL(unit)) {
   4187         if (modport_profile[unit] == NULL) {
   4188             *dest_port_count = 0;
   4189             return BCM_E_NOT_FOUND;
   4190         }
   4191 
   4192         profile = modport_profile[unit];
   4193 
   4194         BCM_IF_ERROR_RETURN(READ_MODPORT_MAP_SELr(unit, ing_port, &rval));
   4195         base_index = modid_count *
   4196                      soc_reg_field_get(unit, MODPORT_MAP_SELr, rval,
   4197                                        MODPORT_MAP_INDEX_UPPERf);
   4198         entry_p = SOC_PROFILE_MEM_ENTRY(unit, profile, modport_map_entry_t *,
   4199                                         base_index + dest_modid);
   4200         if (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) ||
   4201             SOC_IS_VALKYRIE2(unit)) {
   4202             soc_mem_pbmp_field_get(unit, MODPORT_MAPm, entry_p,
   4203                                    HIGIG_PORT_BITMAPf, &pbmp);
   4204             count = 0;
   4205             BCM_PBMP_ITER(pbmp, port) {
   4206                 if (dest_port_max > count) {
   4207                     dest_port_array[count] = port;
   4208                 }
   4209                 if ((dest_port_max != 0) &&
   4210                     (count == dest_port_max)) {
   4211                     break;
   4212                 }
   4213                 count++;
   4214             }
   4215             *dest_port_count = count;
   4216         } else {
   4217             hg_pbmp = soc_mem_field32_get(unit, MODPORT_MAPm, entry_p,
   4218                                           HIGIG_PORT_BITMAPf);
   4219             BCM_IF_ERROR_RETURN
   4220                 (soc_xgs3_higig_bitmap_to_port_all(unit, hg_pbmp,
   4221                                                    dest_port_max,
   4222                                                    dest_port_array,
   4223                                                    dest_port_count));
   4224         }
   4225     } else
   4226 #endif /* BCM_TRX_SUPPORT */
   4227 
   4228     if (SOC_IS_HBX(unit)) {
   4229         base_index = ing_port * modid_count;
   4230         BCM_IF_ERROR_RETURN
   4231             (READ_MODPORT_MAPm(unit, MEM_BLOCK_ANY, base_index + dest_modid,
   4232                                &entry));
   4233         hg_pbmp = soc_mem_field32_get(unit, MODPORT_MAPm, &entry,
   4234                                       HIGIG_PORT_BITMAPf);
   4235         BCM_IF_ERROR_RETURN
   4236             (soc_xgs3_higig_bitmap_to_port_all(unit, hg_pbmp, dest_port_max,
   4237                                                dest_port_array,
   4238                                                dest_port_count));
   4239     } else {
   4240         return BCM_E_UNAVAIL;
   4241     }
   4242 
   4243     return *dest_port_count ? BCM_E_NONE : BCM_E_NOT_FOUND;
   4244 }
   4245 #endif /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */
   4246 
   4247 #ifdef BCM_TRIUMPH_SUPPORT
   4248 /*
   4249  * Function:
   4250  *      _bcm_esw_tr_trunk_override_ucast_set
   4251  * Purpose:
   4252  *      Use the memory profile mechanish to set/clear
   4253  *      HiGig Trunk Override bit.
   4254  * Parameters:
   4255  *      unit - SOC unit
   4256  *      port - Ingress Port
   4257  *      tgid - Trunk ID
   4258  *      modid - Module ID  
   4259  *      enable - HighGig Trunk Override set/clear flag.
   4260  * Returns:
   4261  *      BCM_E_XXX
   4262  */
   4263 int
   4264 _bcm_esw_tr_trunk_override_ucast_set(int unit, bcm_port_t port,
   4265                                bcm_trunk_t hgtid, int modid, int enable)
   4266 {
   4267     int i, rv = BCM_E_NONE;
   4268     soc_profile_mem_t *profile;
   4269     modport_map_entry_t *modport_entry;
   4270     uint32 profile_index_old, profile_index_new, rval, hgo_bitmap, hgo_bit;
   4271     int modid_count;
   4272     uint32 base_index_old, base_index_new;
   4273 #if defined(BCM_TRX_SUPPORT)
   4274     bcmi_trx_modport_map_entry_t *trx_entry_array = NULL;
   4275     int ref_count;
   4276     int dest_is_hg_pbmp = 0;
   4277 #endif /* BCM_TRX_SUPPORT */
   4278 
   4279     if (modport_profile[unit] == NULL) {
   4280         _bcm_stk_modport_profile_init(unit);
   4281     }
   4282     profile = modport_profile[unit];
   4283 
   4284     modid_count = SOC_MODID_MAX(unit) + 1;
   4285     modport_entry = sal_alloc(sizeof(modport_map_entry_t) * modid_count, "modport_map_entry");
   4286     if (modport_entry == NULL) {
   4287         return BCM_E_MEMORY;
   4288     }
   4289 
   4290 #if defined(BCM_TRX_SUPPORT)
   4291     if (soc_feature(unit, soc_feature_modport_map_dest_is_hg_port_bitmap)) {
   4292         trx_entry_array =
   4293             sal_alloc((sizeof(bcmi_trx_modport_map_entry_t) * modid_count),
   4294                       "trx_modport_map_entry");
   4295         if (trx_entry_array == NULL) {
   4296             sal_free(modport_entry);
   4297             return BCM_E_MEMORY;
   4298         }
   4299         dest_is_hg_pbmp = 1;
   4300     }
   4301 #endif /* BCM_TRX_SUPPORT */
   4302 
   4303     soc_mem_lock(unit, MODPORT_MAPm);
   4304 
   4305     rv = READ_MODPORT_MAP_SELr(unit, port, &rval);
   4306     if (BCM_FAILURE(rv)) {
   4307         soc_mem_unlock(unit, MODPORT_MAPm);
   4308         sal_free(modport_entry);
   4309 #if defined(BCM_TRX_SUPPORT)
   4310         if (dest_is_hg_pbmp) {
   4311             sal_free(trx_entry_array);
   4312         }
   4313 #endif /* BCM_TRX_SUPPORT */
   4314         return rv;
   4315     }
   4316 
   4317     profile_index_old = soc_reg_field_get(unit, MODPORT_MAP_SELr, rval,
   4318                                           MODPORT_MAP_INDEX_UPPERf);
   4319     base_index_old = modid_count * profile_index_old;
   4320     for (i = 0; i < modid_count; i++) {
   4321         sal_memcpy(&modport_entry[i],
   4322                    SOC_PROFILE_MEM_ENTRY(unit, profile, void *,
   4323                                          base_index_old + i),
   4324                    sizeof(modport_map_entry_t));
   4325 #if defined(BCM_TRX_SUPPORT)
   4326         if (dest_is_hg_pbmp) {
   4327             sal_memcpy(&trx_entry_array[i],
   4328                        &TRX_MODPORT_MAP_PROFILE
   4329                            (unit, profile_index_old).entry_array[i],
   4330                        sizeof(bcmi_trx_modport_map_entry_t));
   4331         }
   4332 #endif /* BCM_TRX_SUPPORT */
   4333     }
   4334 
   4335     hgo_bitmap = soc_MODPORT_MAPm_field32_get(unit, &modport_entry[modid], HIGIG_TRUNK_OVERRIDEf);
   4336     hgo_bit = 1 << hgtid;
   4337     if (enable) {
   4338         hgo_bitmap |= hgo_bit;
   4339     } else {
   4340         hgo_bitmap &= ~hgo_bit;
   4341     }
   4342     soc_MODPORT_MAPm_field32_set(unit, &modport_entry[modid],
   4343                                  HIGIG_TRUNK_OVERRIDEf,
   4344                                  hgo_bitmap);
   4345 
   4346     rv = soc_profile_mem_add(unit, profile,
   4347                              (void *)&modport_entry, modid_count,
   4348                              &base_index_new);
   4349     if (BCM_SUCCESS(rv)) {
   4350         profile_index_new = (base_index_new / modid_count);
   4351         soc_reg_field_set(unit, MODPORT_MAP_SELr, &rval,
   4352                           MODPORT_MAP_INDEX_UPPERf,
   4353                           profile_index_new);
   4354         rv = WRITE_MODPORT_MAP_SELr(unit, port, rval);
   4355     }
   4356     if (BCM_SUCCESS(rv)) {
   4357 #if defined(BCM_TRX_SUPPORT)
   4358         if (dest_is_hg_pbmp) {
   4359             sal_memcpy(
   4360                 TRX_MODPORT_MAP_PROFILE
   4361                     (unit, profile_index_new).entry_array,
   4362                 trx_entry_array,
   4363                 (sizeof(bcmi_trx_modport_map_entry_t) * modid_count));
   4364             TRX_MODPORT_MAP_PROFILE(unit, profile_index_new).ref_count++;
   4365         }
   4366 #endif /* BCM_TRX_SUPPORT */
   4367         rv = soc_profile_mem_delete(unit, profile, base_index_old);
   4368 #if defined(BCM_TRX_SUPPORT)
   4369         if (dest_is_hg_pbmp) {
   4370             if (BCM_SUCCESS(rv)) {
   4371                 if (TRX_MODPORT_MAP_PROFILE
   4372                         (unit, profile_index_old).ref_count >= 1) {
   4373                     TRX_MODPORT_MAP_PROFILE(unit,
   4374                                             profile_index_old).ref_count--;
   4375                     ref_count =
   4376                         TRX_MODPORT_MAP_PROFILE
   4377                             (unit, profile_index_old).ref_count;
   4378                     /* Clear old profile when ref_count = 0 */
   4379                     if (ref_count == 0) {
   4380                         sal_memset(
   4381                             TRX_MODPORT_MAP_PROFILE
   4382                                 (unit, profile_index_old).entry_array,
   4383                             0,
   4384                             (sizeof(bcmi_trx_modport_map_entry_t) *
   4385                             modid_count));
   4386                     }
   4387                 }
   4388             }
   4389         }
   4390     }
   4391 #endif /* BCM_TRX_SUPPORT */
   4392     soc_mem_unlock(unit, MODPORT_MAPm);
   4393     sal_free(modport_entry);
   4394 #if defined(BCM_TRX_SUPPORT)
   4395     if (dest_is_hg_pbmp) {
   4396         sal_free(trx_entry_array);
   4397     }
   4398 #endif /* BCM_TRX_SUPPORT */
   4399 
   4400     return rv;
   4401 }
   4402 
   4403 /*
   4404  * Function:
   4405  *      _bcm_esw_tr_trunk_override_ucast_get
   4406  * Purpose:
   4407  *      Use the memory profile mechanish to get
   4408  *      HiGig Trunk Override bit.
   4409  * Parameters:
   4410  *      unit - SOC unit
   4411  *      port - Ingress Port
   4412  *      tgid - Trunk ID
   4413  *      modid - Module ID  
   4414  *      enable - HighGig Trunk Override set/clear flag.
   4415  * Returns:
   4416  *      BCM_E_XXX
   4417  */
   4418 int
   4419 _bcm_esw_tr_trunk_override_ucast_get(int unit, bcm_port_t port, 
   4420                                  bcm_trunk_t hgtid, int modid, int *enable) 
   4421 {
   4422     int rv = BCM_E_NONE;
   4423     soc_profile_mem_t *profile;
   4424     modport_map_entry_t *modport_entry;
   4425     uint32 profile_index, rval, hgo_bitmap, hgo_bit;
   4426     int modid_count;
   4427 
   4428     if (modport_profile[unit] == NULL) {
   4429         return BCM_E_NOT_FOUND;
   4430     }
   4431 
   4432     profile = modport_profile[unit];
   4433     modid_count = SOC_MODID_MAX(unit) + 1;
   4434     modport_entry = sal_alloc(sizeof(modport_map_entry_t), "modport_map_entry");
   4435     if (modport_entry == NULL) {
   4436         return BCM_E_MEMORY;
   4437     }
   4438 
   4439     rv = READ_MODPORT_MAP_SELr(unit, port, &rval);
   4440     if (BCM_FAILURE(rv)) {
   4441         soc_mem_unlock(unit, MODPORT_MAPm);
   4442         sal_free(modport_entry);
   4443         return rv;
   4444     }
   4445 
   4446     profile_index = modid_count * 
   4447                     soc_reg_field_get(unit, MODPORT_MAP_SELr, rval,
   4448                                            MODPORT_MAP_INDEX_UPPERf);
   4449 
   4450     sal_memcpy(modport_entry, SOC_PROFILE_MEM_ENTRY(unit, profile, void *,
   4451                        profile_index + modid), sizeof(modport_map_entry_t));
   4452 
   4453     hgo_bitmap = soc_MODPORT_MAPm_field32_get(unit, modport_entry,
   4454                                         HIGIG_TRUNK_OVERRIDEf);
   4455     hgo_bit = 1 << hgtid;
   4456     *enable = (hgo_bitmap & hgo_bit) ? 1 : 0;
   4457 
   4458     sal_free(modport_entry);
   4459   
   4460     return rv;
   4461 }
   4462 #endif /* BCM_TRIUMPH_SUPPORT */
   4463 
   4464 
   4465 /*
   4466  * Function:
   4467  *      bcm_stk_modport_set
   4468  * Purpose:
   4469  *      Set the port in MODPORT entry for modid
   4470  * Parameters:
   4471  *      unit  - SOC unit#
   4472  *      modid - module id
   4473  *      port - port number
   4474  * Returns:
   4475  *      BCM_E_XXX
   4476  * Note:
   4477  *      Supported by all devices except Strata
   4478  */
   4479 
   4480 int
   4481 bcm_esw_stk_modport_set(int unit, int modid, bcm_port_t port)
   4482 {
   4483     BCM_STK_API_TH3_SUPPORT_CHECK(unit);
   4484 
   4485     LOG_INFO(BSL_LS_BCM_STK,
   4486              (BSL_META_U(unit,
   4487                          "STK %d: modport set: modid %d to port %d\n"),
   4488               unit,
   4489               modid, port));
   4490 
   4491     if (!SOC_MODID_ADDRESSABLE(unit, modid)) {
   4492         return BCM_E_PARAM;
   4493     }
   4494     if (BCM_GPORT_IS_SET(port) && !BCM_GPORT_IS_TRUNK(port)) {
   4495         BCM_IF_ERROR_RETURN(
   4496             bcm_esw_port_local_get(unit, port, &port));
   4497     }
   4498 
   4499     switch (BCM_CHIP_FAMILY(unit)) {
   4500 
   4501 #if defined(BCM_FIREBOLT_SUPPORT)
   4502     case BCM_FAMILY_FIREBOLT:
   4503         {
   4504             modport_map_entry_t uc;
   4505             uint32 hg_pbm;
   4506             int rv;
   4507 
   4508             if (!SOC_PORT_VALID(unit, port)) {
   4509                 return BCM_E_PORT;
   4510             }
   4511 
   4512             /* Convert port to HG bitmap for FBX devices other than Raven */
   4513             /* For Raven, use the absolute bitmap */
   4514             if (SOC_IS_RAVEN(unit)) {
   4515                 if (IS_ST_PORT(unit, port) || IS_CPU_PORT(unit, port)) {
   4516                     hg_pbm = 1 << port;
   4517                     rv = BCM_E_NONE;
   4518                 } else {
   4519                     rv = BCM_E_PORT;
   4520                 }
   4521             } else if (SOC_IS_HAWKEYE(unit)) {
   4522                 return BCM_E_UNAVAIL;
   4523             } else {
   4524                 rv = soc_xgs3_port_to_higig_bitmap(unit, port, &hg_pbm);
   4525             }
   4526             if (rv != BCM_E_NONE) {
   4527                 return BCM_E_PORT;
   4528             }
   4529 
   4530             soc_mem_lock(unit, MODPORT_MAPm);
   4531             rv = READ_MODPORT_MAPm(unit, MEM_BLOCK_ANY, modid, &uc);
   4532             if (rv >= 0) {
   4533                 soc_MODPORT_MAPm_field32_set(unit, &uc, HIGIG_PORT_BITMAPf,
   4534                                              hg_pbm);
   4535                 rv = WRITE_MODPORT_MAPm(unit, MEM_BLOCK_ALL, modid, &uc);
   4536             }
   4537             soc_mem_unlock(unit, MODPORT_MAPm);
   4538             return rv;
   4539         }
   4540 #endif /* BCM_FIREBOLT_SUPPORT */
   4541 
   4542 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT)
   4543     case BCM_FAMILY_BRADLEY:
   4544     case BCM_FAMILY_HUMV:
   4545     case BCM_FAMILY_SCORPION:
   4546     case BCM_FAMILY_CONQUEROR:
   4547     case BCM_FAMILY_TRIUMPH:
   4548     case BCM_FAMILY_TRIUMPH2:
   4549         {
   4550             bcm_port_t ing_port;
   4551             PBMP_ALL_ITER(unit, ing_port) {
   4552                 BCM_IF_ERROR_RETURN
   4553                     (_bcm_stk_port_modport_op(unit,
   4554                                               _BCM_STK_PORT_MODPORT_OP_SET,
   4555                                               ing_port, modid, &port, 1));
   4556             }
   4557             break;
   4558         }
   4559 #endif /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */
   4560 
   4561 #ifdef BCM_TRIDENT_SUPPORT
   4562     case BCM_FAMILY_TITAN:
   4563     case BCM_FAMILY_TRIDENT:
   4564     case BCM_FAMILY_KATANA:
   4565         {
   4566             bcm_port_t ing_port;
   4567             bcm_pbmp_t all_pbmp;
   4568 
   4569             BCM_PBMP_CLEAR(all_pbmp);
   4570             BCM_PBMP_ASSIGN(all_pbmp, PBMP_ALL(unit));
   4571 
   4572 #if defined(BCM_KATANA2_SUPPORT)
   4573             if (soc_feature(unit, soc_feature_linkphy_coe) ||
   4574                 soc_feature(unit, soc_feature_subtag_coe)) {
   4575                 _bcm_kt2_subport_pbmp_update(unit, &all_pbmp);
   4576             }
   4577             if (SOC_IS_KATANA2(unit)) {
   4578                 BCM_IF_ERROR_RETURN(_bcm_kt2_flexio_pbmp_update(unit,
   4579                                                                 &all_pbmp));
   4580             }
   4581 #endif
   4582             PBMP_ITER(all_pbmp, ing_port) {
   4583                 BCM_IF_ERROR_RETURN(bcm_td_stk_port_modport_op(unit,
   4584                                             _BCM_STK_PORT_MODPORT_OP_SET,
   4585                                             ing_port, modid, &port, 1));
   4586             }
   4587             break;
   4588         }
   4589 #endif /* BCM_TRIDENT_SUPPORT */
   4590 
   4591 #if defined(BCM_XGS_FABRIC_SUPPORT)
   4592     case BCM_FAMILY_HERCULES:
   4593     case BCM_FAMILY_HERCULES15:
   4594         {
   4595             int ing_port;
   4596             bcm_pbmp_t pbmp;
   4597 
   4598             if (!SOC_PORT_VALID(unit, port)) {
   4599                 BCM_PBMP_CLEAR(pbmp);
   4600             } else {
   4601                 BCM_PBMP_PORT_SET(pbmp, port);
   4602             }
   4603 
   4604             PBMP_HG_ITER(unit, ing_port) {
   4605                 BCM_IF_ERROR_RETURN(bcm_esw_stk_ucbitmap_set(unit, ing_port,
   4606                                                              modid, pbmp));
   4607             }
   4608 
   4609             return BCM_E_NONE;
   4610         }
   4611 #endif
   4612 
   4613     default:
   4614         return BCM_E_UNAVAIL;
   4615     }
   4616 
   4617     return BCM_E_NONE;
   4618 }
   4619 
   4620 /*
   4621  * Function:
   4622  *      bcm_stk_modport_get_all
   4623  * Purpose:
   4624  *      Get all ports in MODPORT entry for modid
   4625  * Parameters:
   4626  *      unit     - (IN) Device Number
   4627  *      modid      - (IN) module id
   4628  *      port_max   - (IN) Maximum number of ports in array
   4629  *      port_array - (OUT) Array of ports
   4630  *      port_count - (OUT) Number of ports returned in array
   4631  * Returns:
   4632  *      BCM_E_XXX
   4633  * Note:
   4634  *      Supported by all devices except Strata and Hawkeye
   4635  */
   4636 int
   4637 bcm_esw_stk_modport_get_all(int unit,
   4638                             int modid,
   4639                             int port_max,
   4640                             bcm_port_t *port_array,
   4641                             int *port_count)
   4642 {
   4643     int         tmp_port, mymodid;
   4644     int         count, isGport;
   4645     _bcm_gport_dest_t   gport_st;
   4646 
   4647     BCM_STK_API_TH3_SUPPORT_CHECK(unit);
   4648 
   4649     if (!SOC_MODID_ADDRESSABLE(unit, modid)) {
   4650         return BCM_E_PARAM;
   4651     }
   4652 
   4653     if (port_max < 0 && port_array == NULL) {
   4654         return BCM_E_PARAM;
   4655     }
   4656 
   4657     count = 0;
   4658     BCM_IF_ERROR_RETURN(
   4659         bcm_esw_switch_control_get(unit, bcmSwitchUseGport, &isGport));
   4660     /* return code intentionaly ignored to support devices where mymodid */
   4661     /* was not assigned */
   4662     (void) bcm_esw_stk_my_modid_get(unit, &mymodid);
   4663 
   4664     switch (BCM_CHIP_FAMILY(unit)) {
   4665 
   4666 #if defined(BCM_FIREBOLT_SUPPORT)
   4667     case BCM_FAMILY_FIREBOLT:
   4668         {
   4669             modport_map_entry_t uc;
   4670             int rv;
   4671             int hg_reg;
   4672 
   4673             SOC_IF_ERROR_RETURN
   4674                 (READ_MODPORT_MAPm(unit, MEM_BLOCK_ANY, modid, &uc));
   4675             hg_reg = soc_MODPORT_MAPm_field32_get(unit, &uc,
   4676                                                   HIGIG_PORT_BITMAPf);
   4677 
   4678             /* For Raven, hg_reg directly corresponds to the physical port */
   4679             if (SOC_IS_RAVEN(unit)) {
   4680                 int port;
   4681 
   4682                 port = 0;
   4683                 while (hg_reg != 0) {
   4684                     if (hg_reg & 1) {
   4685                         if (count < port_max) {
   4686                             tmp_port = port; 
   4687                             if (TRUE == isGport) {
   4688                                 if (BCM_MODID_INVALID == mymodid) {
   4689                                     gport_st.gport_type = _SHR_GPORT_TYPE_DEVPORT;
   4690                                 } else {
   4691                                     gport_st.gport_type = _SHR_GPORT_TYPE_MODPORT;
   4692                                     gport_st.modid = mymodid;
   4693                                 }
   4694                                 gport_st.port = tmp_port;
   4695                                 BCM_IF_ERROR_RETURN(
   4696                                 _bcm_esw_gport_construct(unit, &gport_st, 
   4697                                                          &tmp_port));
   4698                             }
   4699                             port_array[count] = tmp_port;
   4700                         }
   4701                         count++;
   4702                         if ((port_max != 0) &&
   4703                             (port_max == count)) {
   4704                             break;
   4705                         }
   4706                     }
   4707                     port++;
   4708                     hg_reg >>= 1;
   4709                 }
   4710 
   4711                 if (port_count) {
   4712                     *port_count = count;
   4713                 }
   4714 
   4715                 return (count > 0) ? BCM_E_NONE : BCM_E_NOT_FOUND;
   4716 
   4717             } else if (SOC_IS_HAWKEYE(unit)) {
   4718                 rv = BCM_E_UNAVAIL;
   4719             } else {
   4720                 rv = soc_xgs3_higig_bitmap_to_port_all(unit,
   4721                                                        hg_reg,
   4722                                                        port_max,
   4723                                                        port_array,
   4724                                                        &count);
   4725                 if (BCM_SUCCESS(rv) && TRUE == isGport) {
   4726                     int i;
   4727 
   4728                     for (i = 0; i < count; i++) {
   4729                         tmp_port = port_array[i];
   4730                         if (BCM_MODID_INVALID == mymodid) {
   4731                             gport_st.gport_type = _SHR_GPORT_TYPE_DEVPORT;
   4732                         } else {
   4733                             gport_st.gport_type = _SHR_GPORT_TYPE_MODPORT;
   4734                             gport_st.modid = mymodid;
   4735                         } 
   4736                         gport_st.port = tmp_port;
   4737                         BCM_IF_ERROR_RETURN(
   4738                             _bcm_esw_gport_construct(unit, &gport_st, 
   4739                                                      &tmp_port));
   4740                         port_array[i] = tmp_port;
   4741                     }
   4742                 }
   4743                 
   4744                 if (port_count) {
   4745                     *port_count = count;
   4746                 }
   4747             }
   4748 
   4749             return rv;
   4750         }
   4751 #endif /* BCM_FIREBOLT_SUPPORT */
   4752 
   4753 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT)
   4754     case BCM_FAMILY_BRADLEY:
   4755     case BCM_FAMILY_HUMV:
   4756     case BCM_FAMILY_SCORPION:
   4757     case BCM_FAMILY_CONQUEROR:
   4758     case BCM_FAMILY_TRIUMPH:
   4759     case BCM_FAMILY_TRIUMPH2:
   4760     case BCM_FAMILY_TITAN:
   4761     case BCM_FAMILY_TRIDENT:
   4762     case BCM_FAMILY_KATANA:
   4763         {
   4764             bcm_port_t ing_port;
   4765             int count, rv;
   4766             bcm_pbmp_t all_pbmp;
   4767 
   4768             BCM_PBMP_CLEAR(all_pbmp);
   4769             BCM_PBMP_ASSIGN(all_pbmp, PBMP_ALL(unit));
   4770 
   4771 #if defined(BCM_KATANA2_SUPPORT)
   4772             if (soc_feature(unit, soc_feature_linkphy_coe) ||
   4773                 soc_feature(unit, soc_feature_subtag_coe)) {
   4774                 _bcm_kt2_subport_pbmp_update(unit, &all_pbmp);
   4775             }
   4776             if (SOC_IS_KATANA2(unit)) {
   4777                 BCM_IF_ERROR_RETURN(_bcm_kt2_flexio_pbmp_update(unit,
   4778                                                                 &all_pbmp));
   4779             }
   4780 #endif
   4781 
   4782             PBMP_ITER(all_pbmp, ing_port) {
   4783 #ifdef BCM_TRIDENT_SUPPORT
   4784                 if ((BCM_CHIP_FAMILY(unit) == BCM_FAMILY_TRIDENT) ||
   4785                      (BCM_CHIP_FAMILY(unit) == BCM_FAMILY_KATANA) ||
   4786                      (BCM_CHIP_FAMILY(unit) == BCM_FAMILY_TITAN))  {
   4787                     rv = bcm_td_stk_port_modport_get(unit, ing_port, modid,
   4788                             port_max, port_array, &count);
   4789                 } else
   4790 #endif /* BCM_TRIDENT_SUPPORT */
   4791                 {
   4792                     rv =_bcm_stk_port_modport_get(unit, ing_port, modid,
   4793                             port_max, port_array, &count);
   4794                 }
   4795                 if (BCM_FAILURE(rv) && rv != BCM_E_NOT_FOUND) {
   4796                     return rv;
   4797                 }
   4798                 if ((port_max != 0) &&
   4799                     (port_max < count)) {
   4800                     count = port_max;
   4801                 }
   4802                 if (port_count) {
   4803                     *port_count = count;
   4804                 }
   4805                 if ((TRUE == isGport) && (port_array != NULL)) {
   4806                     int i;
   4807 
   4808                     for (i = 0; i < count; i++) {
   4809                         if (BCM_GPORT_IS_TRUNK(port_array[i])) {
   4810                             continue;
   4811                         }
   4812                         tmp_port = port_array[i];
   4813                         if (BCM_MODID_INVALID == mymodid) {
   4814                             gport_st.gport_type = _SHR_GPORT_TYPE_DEVPORT;
   4815                         } else {
   4816                             gport_st.gport_type = _SHR_GPORT_TYPE_MODPORT;
   4817                             gport_st.modid = mymodid;
   4818                         } 
   4819                         gport_st.port = tmp_port;
   4820                         BCM_IF_ERROR_RETURN(
   4821                             _bcm_esw_gport_construct(unit, &gport_st, 
   4822                                                      &tmp_port));
   4823                         port_array[i] = tmp_port;
   4824                     }
   4825                 }
   4826 
   4827                 return rv;
   4828             }
   4829             break;
   4830         }
   4831 #endif /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */
   4832 
   4833 #if defined(BCM_XGS_FABRIC_SUPPORT)
   4834     case BCM_FAMILY_HERCULES:
   4835     case BCM_FAMILY_HERCULES15:
   4836         {
   4837             int ing_port;
   4838             bcm_pbmp_t pbmp;
   4839 
   4840             /*
   4841              * Iterate through the ingress ports.
   4842              * Find the first ingress port with a non-null bitmap
   4843              * for the modid; return the first port in that bitmap.
   4844              */
   4845 
   4846             PBMP_HG_ITER(unit, ing_port) {
   4847                 BCM_IF_ERROR_RETURN(bcm_esw_stk_ucbitmap_get(unit, ing_port,
   4848                                                              modid, &pbmp));
   4849                 if (BCM_PBMP_NOT_NULL(pbmp)) {
   4850                     bcm_port_t port;
   4851 
   4852                     BCM_PBMP_ITER(pbmp, port) {
   4853                         if (count < port_max) {
   4854                             tmp_port = port; 
   4855                             if (TRUE == isGport) {
   4856                                 if (BCM_MODID_INVALID == mymodid) {
   4857                                     gport_st.gport_type = _SHR_GPORT_TYPE_DEVPORT;
   4858                                 } else {
   4859                                     gport_st.gport_type = _SHR_GPORT_TYPE_MODPORT;
   4860                                     gport_st.modid = mymodid;
   4861                                 }
   4862                                 gport_st.port = tmp_port;
   4863                                 BCM_IF_ERROR_RETURN(
   4864                                     _bcm_esw_gport_construct(unit, &gport_st, 
   4865                                                              &tmp_port));
   4866                             }
   4867                             port_array[count] = tmp_port;
   4868                         }
   4869                         if ((port_max != 0) &&
   4870                             (port_max == count)) {
   4871                             break;
   4872                         }
   4873                         count++;
   4874                     }
   4875                     break;
   4876                 }
   4877             }
   4878 
   4879             if (port_count) {
   4880                 *port_count = count;
   4881             }
   4882 
   4883             return (count > 0) ? BCM_E_NONE : BCM_E_NOT_FOUND;
   4884         }
   4885 #endif
   4886 
   4887     default:
   4888         return BCM_E_UNAVAIL;
   4889     }
   4890 
   4891     return BCM_E_NONE;
   4892 }
   4893 
   4894 /*
   4895  * Function:
   4896  *      bcm_stk_modport_get
   4897  * Purpose:
   4898  *      Get the port in MODPORT entry for modid
   4899  * Parameters:
   4900  *      unit  - SOC unit#
   4901  *      modid - module id
   4902  *      port  - (OUT) port number
   4903  * Returns:
   4904  *      BCM_E_XXX
   4905  * Note:
   4906  *      Supported by all devices except Strata
   4907  */
   4908 
   4909 int
   4910 bcm_esw_stk_modport_get(int unit, int modid, bcm_port_t *port)
   4911 {
   4912     BCM_STK_API_TH3_SUPPORT_CHECK(unit);
   4913 
   4914     if (port == NULL) {
   4915         return BCM_E_PARAM;
   4916     }
   4917 
   4918     *port = -1;
   4919     return bcm_esw_stk_modport_get_all(unit, modid, 1, port, NULL);
   4920 }
   4921 
   4922 
   4923 /*
   4924  * Function:
   4925  *      bcm_stk_modport_clear
   4926  * Purpose:
   4927  *      Clear entry in MODPORT table
   4928  * Parameters:
   4929  *      unit  - SOC unit#
   4930  *      modid - module id
   4931  * Returns:
   4932  *      BCM_E_XXX
   4933  * Note:
   4934  *      Supported by all devices except Strata
   4935  */
   4936 
   4937 int
   4938 bcm_esw_stk_modport_clear(int unit, int modid)
   4939 {
   4940     bcm_pbmp_t pbmp;
   4941     int port;
   4942     int rv;
   4943     int use_modport_set;
   4944     bcm_pbmp_t all_pbmp;
   4945 
   4946     BCM_STK_API_TH3_SUPPORT_CHECK(unit);
   4947 
   4948     LOG_VERBOSE(BSL_LS_BCM_STK,
   4949                 (BSL_META_U(unit,
   4950                             "STK %d: Clearing mod port info of modid %d.\n"),
   4951                  unit, modid));
   4952 
   4953     if (!SOC_MODID_ADDRESSABLE(unit, modid)) {
   4954         return BCM_E_PARAM;
   4955     }
   4956 
   4957     /* First try to clear the modport bitmap, if available */
   4958 
   4959     rv = BCM_E_INTERNAL;
   4960     use_modport_set = FALSE;
   4961     BCM_PBMP_CLEAR(pbmp);
   4962 
   4963     BCM_PBMP_CLEAR(all_pbmp);
   4964     BCM_PBMP_ASSIGN(all_pbmp, PBMP_ALL(unit));
   4965 
   4966 #if defined(BCM_KATANA2_SUPPORT)
   4967     if (soc_feature(unit, soc_feature_linkphy_coe) ||
   4968         soc_feature(unit, soc_feature_subtag_coe)) {
   4969         _bcm_kt2_subport_pbmp_update(unit, &all_pbmp);
   4970     }
   4971     if (SOC_IS_KATANA2(unit)) {
   4972         BCM_IF_ERROR_RETURN(_bcm_kt2_flexio_pbmp_update(unit,
   4973                                                         &all_pbmp));
   4974     }
   4975 #endif
   4976 
   4977     /* Go though all ports, because on different devices, some or all
   4978        of their ports may have a modport map. We'll be conservative
   4979        and clear everything; this will catch cases like having stack
   4980        ports with modport map settings that get converted into
   4981        non-stack ports still getting those modport maps cleared. */
   4982     PBMP_ITER(all_pbmp, port) {
   4983         rv = bcm_esw_stk_ucbitmap_set(unit, port, modid, pbmp);
   4984         if (rv == BCM_E_NONE) {
   4985             /* Cleared the modport map so modport_set not needed,
   4986                keep going */
   4987         } else if (rv == BCM_E_UNAVAIL) {
   4988             /* Do need modport_set, stop */
   4989             use_modport_set = TRUE;
   4990             break;
   4991         } else if (rv == BCM_E_PORT) {
   4992             /* no modmap for this port, ignore error and keep going */
   4993         } else {
   4994             /* some other error, stop, do not use modport_set */
   4995             break;
   4996         }
   4997     }
   4998 
   4999     /* Set the modport to a stack port, if available. This should only
   5000        happen on XGS switch devices that only have one stack port and
   5001        do not have a modport bitmap. */
   5002 
   5003     if (use_modport_set) {
   5004         port = IPIC_PORT(unit);
   5005         if (port < 0) {
   5006             port = SOC_PORT_MIN(unit, st);
   5007             if (port < 0) {
   5008                 /* just clear the modport if a stack port cannot be
   5009                    found */
   5010                 port = 0;
   5011             }
   5012         }
   5013         rv = bcm_esw_stk_modport_set(unit, modid, port);
   5014     }
   5015 
   5016     return rv;
   5017 }
   5018 
   5019 /*
   5020  * Function:
   5021  *      bcm_stk_modport_clear_all
   5022  * Purpose:
   5023  *      Clear all entries in MODPORT table
   5024  * Parameters:
   5025  *      unit  - SOC unit#
   5026  * Returns:
   5027  *      BCM_E_XXX
   5028  * Note:
   5029  *      Supported by all devices except Strata
   5030  */
   5031 
   5032 int
   5033 bcm_esw_stk_modport_clear_all(int unit)
   5034 {
   5035     if (!SOC_UNIT_VALID(unit)) {
   5036         return BCM_E_UNIT;
   5037     }
   5038 
   5039     BCM_STK_API_TH3_SUPPORT_CHECK(unit);
   5040 
   5041     LOG_VERBOSE(BSL_LS_BCM_STK,
   5042                 (BSL_META_U(unit,
   5043                             "STK %d: Clearing all mod port info.\n"),
   5044                  unit));
   5045 
   5046     switch (BCM_CHIP_FAMILY(unit)) {
   5047 #if defined(BCM_FIREBOLT_SUPPORT) || defined(BCM_XGS_FABRIC_SUPPORT)
   5048     case BCM_FAMILY_FIREBOLT:
   5049     case BCM_FAMILY_HERCULES15:
   5050     case BCM_FAMILY_BRADLEY:
   5051     case BCM_FAMILY_HUMV:
   5052     case BCM_FAMILY_TRIUMPH:
   5053     case BCM_FAMILY_SCORPION:
   5054     case BCM_FAMILY_CONQUEROR:
   5055     case BCM_FAMILY_TRIUMPH2:
   5056     case BCM_FAMILY_TITAN:
   5057     case BCM_FAMILY_TRIDENT:
   5058     case BCM_FAMILY_KATANA:
   5059     {
   5060         int i;
   5061 
   5062         for ( i = 0; i <= SOC_MODID_MAX(unit); i++) {
   5063             bcm_esw_stk_modport_clear(unit, i);
   5064         }
   5065         break;
   5066     }
   5067 #endif
   5068 
   5069     default:
   5070         return BCM_E_UNAVAIL;
   5071     }
   5072 
   5073     return BCM_E_NONE;
   5074 }
   5075 
   5076 /*
   5077  * Function:
   5078  *      bcm_esw_stk_modport_add
   5079  * Purpose:
   5080  *      Adds a HG port given a destination modid
   5081  * Parameters:
   5082  *      unit   -  SOC unit#
   5083  *      modid  -  module id
   5084  *      port   -  egress HG port
   5085  * Returns:
   5086  *      BCM_E_XXX
   5087  */
   5088 int
   5089 bcm_esw_stk_modport_add(int unit, int modid, bcm_port_t port)
   5090 {
   5091     int rv = BCM_E_UNAVAIL;
   5092 
   5093     BCM_STK_API_TH3_SUPPORT_CHECK(unit);
   5094 
   5095     LOG_INFO(BSL_LS_BCM_STK,
   5096              (BSL_META_U(unit,
   5097                          "STK %d: modport add: modid %d to port %d\n"),
   5098               unit,
   5099               modid, port));
   5100 
   5101     if (!SOC_MODID_ADDRESSABLE(unit, modid)) {
   5102         return BCM_E_PARAM;
   5103     }
   5104     if (BCM_GPORT_IS_SET(port) && !BCM_GPORT_IS_TRUNK(port)) {
   5105         BCM_IF_ERROR_RETURN(
   5106             bcm_esw_port_local_get(unit, port, &port));
   5107     }
   5108 
   5109     switch (BCM_CHIP_FAMILY(unit)) {
   5110 
   5111 #if defined(BCM_FIREBOLT_SUPPORT)
   5112     case BCM_FAMILY_FIREBOLT:
   5113         {
   5114             modport_map_entry_t uc;
   5115             uint32 hg_pbm = 0, modport_pbm = 0;
   5116 
   5117             if (!SOC_PORT_VALID(unit, port)) {
   5118                 return BCM_E_PORT;
   5119             }
   5120 
   5121             /* Convert port to HG bitmap */
   5122 
   5123             if (SOC_IS_RAVEN(unit)) {
   5124                 if (IS_ST_PORT(unit, port) || IS_CPU_PORT(unit, port)) {
   5125                     hg_pbm = 1 << port;
   5126                     rv = BCM_E_NONE;
   5127                 } else {
   5128                     rv = BCM_E_PORT;
   5129                 }
   5130             } else if (SOC_IS_HAWKEYE(unit)) {
   5131                 return BCM_E_UNAVAIL;
   5132             } else {
   5133                 rv = soc_xgs3_port_to_higig_bitmap(unit, port, &hg_pbm);
   5134             }
   5135             if (rv != BCM_E_NONE) {
   5136                 return BCM_E_PORT;
   5137             }
   5138 
   5139             soc_mem_lock(unit, MODPORT_MAPm);
   5140             rv = READ_MODPORT_MAPm(unit, MEM_BLOCK_ANY, modid, &uc);
   5141             if (rv >= 0) {
   5142                 modport_pbm = soc_MODPORT_MAPm_field32_get(unit, &uc,
   5143                                                            HIGIG_PORT_BITMAPf);
   5144                 if (modport_pbm & hg_pbm) {
   5145                     soc_mem_unlock(unit, MODPORT_MAPm);
   5146                     return BCM_E_NONE;
   5147                 }
   5148 
   5149                 modport_pbm |= hg_pbm;
   5150                 soc_MODPORT_MAPm_field32_set(unit, &uc, HIGIG_PORT_BITMAPf,
   5151                                              modport_pbm);
   5152                 rv = WRITE_MODPORT_MAPm(unit, MEM_BLOCK_ALL, modid, &uc);
   5153             }
   5154             soc_mem_unlock(unit, MODPORT_MAPm);
   5155             break;
   5156         }
   5157 #endif /* BCM_FIREBOLT_SUPPORT */
   5158 
   5159 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT)
   5160     case BCM_FAMILY_BRADLEY:
   5161     case BCM_FAMILY_HUMV:
   5162     case BCM_FAMILY_SCORPION:
   5163     case BCM_FAMILY_CONQUEROR:
   5164     case BCM_FAMILY_TRIUMPH:
   5165     case BCM_FAMILY_TRIUMPH2:
   5166         {
   5167             bcm_port_t ing_port;
   5168             PBMP_ALL_ITER(unit, ing_port) {
   5169                 BCM_IF_ERROR_RETURN
   5170                     (_bcm_stk_port_modport_op(unit,
   5171                                               _BCM_STK_PORT_MODPORT_OP_ADD,
   5172                                               ing_port, modid, &port, 1));
   5173             }
   5174             rv = BCM_E_NONE;
   5175             break;
   5176         }
   5177 #if defined(BCM_TRIDENT_SUPPORT)
   5178     case BCM_FAMILY_TITAN:
   5179     case BCM_FAMILY_TRIDENT:
   5180     case BCM_FAMILY_KATANA:
   5181         {
   5182             bcm_port_t ing_port;
   5183             bcm_pbmp_t all_pbmp;
   5184 
   5185             BCM_PBMP_CLEAR(all_pbmp);
   5186             BCM_PBMP_ASSIGN(all_pbmp, PBMP_ALL(unit));
   5187 
   5188 #if defined(BCM_KATANA2_SUPPORT)
   5189             if (soc_feature(unit, soc_feature_linkphy_coe) ||
   5190                 soc_feature(unit, soc_feature_subtag_coe)) {
   5191                 _bcm_kt2_subport_pbmp_update(unit, &all_pbmp);
   5192             }
   5193             if (SOC_IS_KATANA2(unit)) {
   5194                 BCM_IF_ERROR_RETURN(_bcm_kt2_flexio_pbmp_update(unit,
   5195                                                                 &all_pbmp));
   5196             }
   5197 #endif
   5198 
   5199             PBMP_ITER(all_pbmp, ing_port) {
   5200                 BCM_IF_ERROR_RETURN
   5201                     (bcm_td_stk_port_modport_op(unit,
   5202                                               _BCM_STK_PORT_MODPORT_OP_ADD,
   5203                                               ing_port, modid, &port, 1));
   5204             }
   5205             rv = BCM_E_NONE;
   5206             break;
   5207         }
   5208 #endif /* BCM_TRIDENT_SUPPORT */
   5209 #endif /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */
   5210 
   5211     default:
   5212         break;
   5213     }
   5214 
   5215     return rv;
   5216 }
   5217 
   5218 /*
   5219  * Function:
   5220  *      bcm_esw_stk_modport_delete
   5221  * Purpose:
   5222  *      Removes a HG (egress) port for given a destination modid
   5223  * Parameters:
   5224  *      unit   -  SOC unit#
   5225  *      modid  -  module id
   5226  *      port   -  egress HG port
   5227  * Returns:
   5228  *      BCM_E_XXX
   5229  */
   5230 int
   5231 bcm_esw_stk_modport_delete(int unit, int modid, bcm_port_t port)
   5232 {
   5233     int rv = BCM_E_UNAVAIL;
   5234 
   5235     BCM_STK_API_TH3_SUPPORT_CHECK(unit);
   5236 
   5237     LOG_INFO(BSL_LS_BCM_STK,
   5238              (BSL_META_U(unit,
   5239                          "STK %d: modport delete: modid %d to port %d\n"),
   5240               unit,
   5241               modid, port));
   5242 
   5243     if (!SOC_MODID_ADDRESSABLE(unit, modid)) {
   5244         return BCM_E_PARAM;
   5245     }
   5246     if (BCM_GPORT_IS_SET(port) && !BCM_GPORT_IS_TRUNK(port)) {
   5247         BCM_IF_ERROR_RETURN(
   5248             bcm_esw_port_local_get(unit, port, &port));
   5249     }
   5250 
   5251     switch (BCM_CHIP_FAMILY(unit)) {
   5252 
   5253 #if defined(BCM_FIREBOLT_SUPPORT)
   5254     case BCM_FAMILY_FIREBOLT:
   5255         {
   5256             modport_map_entry_t uc;
   5257             uint32 modport_pbm = 0, hg_pbm = 0;
   5258 
   5259             if (!SOC_PORT_VALID(unit, port)) {
   5260                 return BCM_E_PORT;
   5261             }
   5262 
   5263             /* Convert port to HG bitmap */
   5264             if (SOC_IS_RAVEN(unit)) {
   5265                 if (IS_ST_PORT(unit, port) || IS_CPU_PORT(unit, port)) {
   5266                     hg_pbm = 1 << port;
   5267                     rv = BCM_E_NONE;
   5268                 } else {
   5269                     rv = BCM_E_PORT;
   5270                 }
   5271             } else if (SOC_IS_HAWKEYE(unit)) {
   5272                 return BCM_E_UNAVAIL;
   5273             } else {
   5274                 rv = soc_xgs3_port_to_higig_bitmap(unit, port, &hg_pbm);
   5275             }
   5276             if (rv != BCM_E_NONE) {
   5277                 return BCM_E_PORT;
   5278             }
   5279 
   5280             soc_mem_lock(unit, MODPORT_MAPm);
   5281             rv = READ_MODPORT_MAPm(unit, MEM_BLOCK_ANY, modid, &uc);
   5282             if (rv >= 0) {
   5283                 modport_pbm = soc_MODPORT_MAPm_field32_get(unit, &uc,
   5284                                                       HIGIG_PORT_BITMAPf);
   5285                 if (!(modport_pbm & hg_pbm)) {
   5286                     soc_mem_unlock(unit, MODPORT_MAPm);
   5287                     return BCM_E_NOT_FOUND;
   5288                 }
   5289 
   5290                 modport_pbm &= ~hg_pbm;
   5291                 soc_MODPORT_MAPm_field32_set(unit, &uc, HIGIG_PORT_BITMAPf,
   5292                                              modport_pbm);
   5293                 rv = WRITE_MODPORT_MAPm(unit, MEM_BLOCK_ALL, modid, &uc);
   5294             }
   5295             soc_mem_unlock(unit, MODPORT_MAPm);
   5296             break;
   5297         }
   5298 #endif /* BCM_FIREBOLT_SUPPORT */
   5299 
   5300 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT)
   5301     case BCM_FAMILY_BRADLEY:
   5302     case BCM_FAMILY_HUMV:
   5303     case BCM_FAMILY_SCORPION:
   5304     case BCM_FAMILY_CONQUEROR:
   5305     case BCM_FAMILY_TRIUMPH:
   5306     case BCM_FAMILY_TRIUMPH2:
   5307         {
   5308             bcm_port_t ing_port;
   5309             PBMP_ALL_ITER(unit, ing_port) {
   5310                 BCM_IF_ERROR_RETURN
   5311                     (_bcm_stk_port_modport_op(unit,
   5312                                               _BCM_STK_PORT_MODPORT_OP_DELETE,
   5313                                               ing_port, modid, &port, 1));
   5314             }
   5315             rv = BCM_E_NONE;
   5316             break;
   5317         }
   5318 #if defined(BCM_TRIDENT_SUPPORT)
   5319     case BCM_FAMILY_TITAN:
   5320     case BCM_FAMILY_TRIDENT:
   5321     case BCM_FAMILY_KATANA:
   5322         {
   5323             bcm_port_t ing_port;
   5324             bcm_pbmp_t all_pbmp;
   5325 
   5326             BCM_PBMP_CLEAR(all_pbmp);
   5327             BCM_PBMP_ASSIGN(all_pbmp, PBMP_ALL(unit));
   5328 
   5329 #if defined(BCM_KATANA2_SUPPORT)
   5330             if (soc_feature(unit, soc_feature_linkphy_coe) ||
   5331                 soc_feature(unit, soc_feature_subtag_coe)) {
   5332                 _bcm_kt2_subport_pbmp_update(unit, &all_pbmp);
   5333             }
   5334             if (SOC_IS_KATANA2(unit)) {
   5335                 BCM_IF_ERROR_RETURN(_bcm_kt2_flexio_pbmp_update(unit,
   5336                                                                 &all_pbmp));
   5337             }
   5338 #endif
   5339             PBMP_ITER(all_pbmp, ing_port) {
   5340                 BCM_IF_ERROR_RETURN
   5341                     (bcm_td_stk_port_modport_op(unit,
   5342                                               _BCM_STK_PORT_MODPORT_OP_DELETE,
   5343                                               ing_port, modid, &port, 1));
   5344             }
   5345             rv = BCM_E_NONE;
   5346             break;
   5347         }
   5348 #endif /* BCM_TRIDENT_SUPPORT */
   5349 #endif /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */
   5350 
   5351     default:
   5352         break;
   5353     }
   5354 
   5355     return rv;
   5356 }
   5357 
   5358 /*
   5359  * Function:
   5360  *      bcm_esw_stk_port_modport_set
   5361  * Purpose:
   5362  *      Set a destination path for a given destination module of the ingress
   5363  *      port.
   5364  * Parameters:
   5365  *      unit       - (IN) Device number
   5366  *      ing_port   - (IN) Ingress port
   5367  *      dest_modid - (IN) Destination module id
   5368  *      dest_port  - (IN) Destination port
   5369  * Returns:
   5370  *      BCM_E_XXX
   5371  */
   5372 int
   5373 bcm_esw_stk_port_modport_set(int unit, bcm_port_t ing_port,
   5374                              bcm_module_t dest_modid, bcm_port_t dest_port)
   5375 {
   5376     BCM_STK_API_TH3_SUPPORT_CHECK(unit);
   5377 
   5378 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT)
   5379     LOG_INFO(BSL_LS_BCM_STK,
   5380              (BSL_META_U(unit,
   5381                          "STK %d: port modport set: ing port %d modid %d to port %d\n"),
   5382               unit, ing_port, dest_modid, dest_port));
   5383 
   5384 #ifdef BCM_TRIDENT_SUPPORT
   5385     if (soc_feature(unit, soc_feature_modport_map_dest_is_port_or_trunk)) {
   5386         return bcm_td_stk_port_modport_op(unit, _BCM_STK_PORT_MODPORT_OP_SET,
   5387                 ing_port, dest_modid, &dest_port, 1);
   5388     } else
   5389 #endif /* BCM_TRIDENT_SUPPORT */
   5390     {
   5391         return _bcm_stk_port_modport_op(unit, _BCM_STK_PORT_MODPORT_OP_SET,
   5392                 ing_port, dest_modid, &dest_port, 1);
   5393     }
   5394 #else /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */
   5395     return BCM_E_UNAVAIL;
   5396 #endif /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */
   5397 }
   5398 
   5399 /*
   5400  * Function:
   5401  *      bcm_esw_stk_port_modport_get
   5402  * Purpose:
   5403  *      Get a destination path for a given destination module of the ingress
   5404  *      port.
   5405  * Parameters:
   5406  *      unit       - (IN) Device number
   5407  *      ing_port   - (IN) Ingress port
   5408  *      dest_modid - (IN) Destination module id
   5409  *      dest_port  - (OUT) Destination port
   5410  * Returns:
   5411  *      BCM_E_XXX
   5412  */
   5413 int
   5414 bcm_esw_stk_port_modport_get(int unit, bcm_port_t ing_port,
   5415                              bcm_module_t dest_modid, bcm_port_t *dest_port)
   5416 {
   5417 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT)
   5418     int dest_port_count;
   5419 #endif /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */
   5420 
   5421     BCM_STK_API_TH3_SUPPORT_CHECK(unit);
   5422 
   5423 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT)
   5424 #ifdef BCM_TRIDENT_SUPPORT
   5425     if (soc_feature(unit, soc_feature_modport_map_dest_is_port_or_trunk)) {
   5426         return bcm_td_stk_port_modport_get(unit, ing_port, dest_modid, 1, dest_port,
   5427                 &dest_port_count);
   5428     } else
   5429 #endif /* BCM_TRIDENT_SUPPORT */
   5430     {
   5431         return _bcm_stk_port_modport_get(unit, ing_port, dest_modid, 1, dest_port,
   5432                 &dest_port_count);
   5433     }
   5434 #else /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */
   5435     return BCM_E_UNAVAIL;
   5436 #endif /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */
   5437 }
   5438 
   5439 /*
   5440  * Function:
   5441  *      bcm_esw_stk_port_modport_get_all
   5442  * Purpose:
   5443  *      Get all destination paths for a given destination module of the
   5444  *      ingress port.
   5445  * Parameters:
   5446  *      unit            - (IN) Device number
   5447  *      ing_port        - (IN) Ingress port
   5448  *      dest_modid      - (IN) Destination module id
   5449  *      dest_port_max   - (IN) Maximum number of ports in array
   5450  *      dest_port_array - (OUT) Array of ports
   5451  *      dest_port_count - (OUT) Number of ports returned in array
   5452  * Returns:
   5453  *      BCM_E_XXX
   5454  */
   5455 int
   5456 bcm_esw_stk_port_modport_get_all(int unit, bcm_port_t ing_port,
   5457                                  bcm_module_t dest_modid, int dest_port_max,
   5458                                  bcm_port_t *dest_port_array,
   5459                                  int *dest_port_count)
   5460 {
   5461     BCM_STK_API_TH3_SUPPORT_CHECK(unit);
   5462 
   5463 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT)
   5464 #ifdef BCM_TRIDENT_SUPPORT
   5465     if (soc_feature(unit, soc_feature_modport_map_dest_is_port_or_trunk)) {
   5466         return bcm_td_stk_port_modport_get(unit, ing_port, dest_modid, dest_port_max,
   5467                 dest_port_array, dest_port_count);
   5468     } else
   5469 #endif /* BCM_TRIDENT_SUPPORT */
   5470     {
   5471         return _bcm_stk_port_modport_get(unit, ing_port, dest_modid, dest_port_max,
   5472                 dest_port_array, dest_port_count);
   5473     }
   5474 #else /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */
   5475     return BCM_E_UNAVAIL;
   5476 #endif /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */
   5477 }
   5478 
   5479 /*
   5480  * Function:
   5481  *      bcm_esw_stk_port_modport_clear
   5482  * Purpose:
   5483  *      Clear all destination paths for a given destination module of the
   5484  *      ingress port.
   5485  * Parameters:
   5486  *      unit       - (IN) Device number
   5487  *      ing_port   - (IN) Ingress port
   5488  *      dest_modid - (IN) Destination module id
   5489  * Returns:
   5490  *      BCM_E_XXX
   5491  */
   5492 int
   5493 bcm_esw_stk_port_modport_clear(int unit, bcm_port_t ing_port,
   5494                                bcm_module_t dest_modid)
   5495 {
   5496     BCM_STK_API_TH3_SUPPORT_CHECK(unit);
   5497 
   5498 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT)
   5499     LOG_INFO(BSL_LS_BCM_STK,
   5500              (BSL_META_U(unit,
   5501                          "STK %d: port modport clear: ing port %d modid %d\n"),
   5502               unit, ing_port, dest_modid));
   5503 
   5504 #ifdef BCM_TRIDENT_SUPPORT
   5505     if (soc_feature(unit, soc_feature_modport_map_dest_is_port_or_trunk)) {
   5506         return bcm_td_stk_port_modport_op(unit, _BCM_STK_PORT_MODPORT_OP_SET,
   5507                 ing_port, dest_modid, NULL, 0);
   5508     } else
   5509 #endif /* BCM_TRIDENT_SUPPORT */
   5510     {
   5511         return _bcm_stk_port_modport_op(unit, _BCM_STK_PORT_MODPORT_OP_SET,
   5512                 ing_port, dest_modid, NULL, 0);
   5513     }
   5514 #else /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */
   5515     return BCM_E_UNAVAIL;
   5516 #endif /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */
   5517 }
   5518 
   5519 /*
   5520  * Function:
   5521  *      bcm_esw_stk_port_modport_clear_all
   5522  * Purpose:
   5523  *      Clear destination paths for all destination modules of the ingress
   5524  *      port.
   5525  * Parameters:
   5526  *      unit       - (IN) Device number
   5527  *      ing_port   - (IN) Ingress port
   5528  * Returns:
   5529  *      BCM_E_XXX
   5530  */
   5531 int
   5532 bcm_esw_stk_port_modport_clear_all(int unit, bcm_port_t ing_port)
   5533 {
   5534     BCM_STK_API_TH3_SUPPORT_CHECK(unit);
   5535 
   5536 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT)
   5537     LOG_INFO(BSL_LS_BCM_STK,
   5538              (BSL_META_U(unit,
   5539                          "STK %d: port modport clear all: ing port %d\n"),
   5540               unit, ing_port));
   5541 
   5542 #ifdef BCM_TRIDENT_SUPPORT
   5543     if (soc_feature(unit, soc_feature_modport_map_dest_is_port_or_trunk)) {
   5544         return bcm_td_stk_port_modport_op(unit, _BCM_STK_PORT_MODPORT_OP_SET,
   5545                 ing_port, -1, NULL, 0);
   5546     } else
   5547 #endif /* BCM_TRIDENT_SUPPORT */
   5548     {
   5549         return _bcm_stk_port_modport_op(unit, _BCM_STK_PORT_MODPORT_OP_SET,
   5550                 ing_port, -1, NULL, 0);
   5551     }
   5552 #else /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */
   5553     return BCM_E_UNAVAIL;
   5554 #endif /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */
   5555 }
   5556 
   5557 /*
   5558  * Function:
   5559  *      bcm_esw_stk_port_modport_add
   5560  * Purpose:
   5561  *      Add one path for a given destination module of the ingress port.
   5562  * Parameters:
   5563  *      unit       - (IN) Device number
   5564  *      ing_port   - (IN) Ingress port
   5565  *      dest_modid - (IN) Destination module id
   5566  *      dest_port  - (IN) Destination port
   5567  * Returns:
   5568  *      BCM_E_XXX
   5569  */
   5570 int
   5571 bcm_esw_stk_port_modport_add(int unit, bcm_port_t ing_port,
   5572                              bcm_module_t dest_modid, bcm_port_t dest_port)
   5573 {
   5574     BCM_STK_API_TH3_SUPPORT_CHECK(unit);
   5575 
   5576 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT)
   5577     LOG_INFO(BSL_LS_BCM_STK,
   5578              (BSL_META_U(unit,
   5579                          "STK %d: port modport add: ing port %d modid %d to port %d\n"),
   5580               unit, ing_port, dest_modid, dest_port));
   5581 
   5582 #ifdef BCM_TRIDENT_SUPPORT
   5583     if (soc_feature(unit, soc_feature_modport_map_dest_is_port_or_trunk)) {
   5584         return bcm_td_stk_port_modport_op(unit, _BCM_STK_PORT_MODPORT_OP_ADD,
   5585                 ing_port, dest_modid, &dest_port, 1);
   5586     } else
   5587 #endif /* BCM_TRIDENT_SUPPORT */
   5588     {
   5589         return _bcm_stk_port_modport_op(unit, _BCM_STK_PORT_MODPORT_OP_ADD,
   5590                 ing_port, dest_modid, &dest_port, 1);
   5591     }
   5592 #else /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */
   5593     return BCM_E_UNAVAIL;
   5594 #endif /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */
   5595 }
   5596 
   5597 /*
   5598  * Function:
   5599  *      bcm_esw_stk_port_modport_delete
   5600  * Purpose:
   5601  *      Delete one path for a given destination module of the ingress port.
   5602  * Parameters:
   5603  *      unit       - (IN) Device number
   5604  *      ing_port   - (IN) Ingress port
   5605  *      dest_modid - (IN) Destination module id
   5606  *      dest_port  - (IN) Destination port
   5607  * Returns:
   5608  *      BCM_E_XXX
   5609  */
   5610 int
   5611 bcm_esw_stk_port_modport_delete(int unit, bcm_port_t ing_port,
   5612                                 bcm_module_t dest_modid, bcm_port_t dest_port)
   5613 {
   5614     BCM_STK_API_TH3_SUPPORT_CHECK(unit);
   5615 
   5616 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT)
   5617     LOG_INFO(BSL_LS_BCM_STK,
   5618              (BSL_META_U(unit,
   5619                          "STK %d: port modport delete: ing port %d modid %d to port %d\n"),
   5620               unit, ing_port, dest_modid, dest_port));
   5621 
   5622 #ifdef BCM_TRIDENT_SUPPORT
   5623     if (soc_feature(unit, soc_feature_modport_map_dest_is_port_or_trunk)) {
   5624         return bcm_td_stk_port_modport_op(unit, _BCM_STK_PORT_MODPORT_OP_DELETE,
   5625                 ing_port, dest_modid, &dest_port, 1);
   5626     } else
   5627 #endif /* BCM_TRIDENT_SUPPORT */
   5628     {
   5629         return _bcm_stk_port_modport_op(unit, _BCM_STK_PORT_MODPORT_OP_DELETE,
   5630                 ing_port, dest_modid, &dest_port, 1);
   5631     }
   5632 #else /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */
   5633     return BCM_E_UNAVAIL;
   5634 #endif /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */
   5635 }
   5636 
   5637 #ifdef _BCM_STK_FLAGS_GET
   5638 
   5639 /****************************************************************
   5640  *
   5641  * Get port's stack flags, per device type
   5642  */
   5643 
   5644 STATIC int
   5645 _esw_stk_flags_get(int unit, bcm_port_t port, uint32 *flags)
   5646 {
   5647     if (!SOC_IS_STACK_PORT(unit, port)) {
   5648         *flags = BCM_STK_NONE;
   5649         return BCM_E_NONE;
   5650     }
   5651     *flags = BCM_STK_ENABLE;
   5652 
   5653     if (SOC_IS_INACTIVE_STACK_PORT(unit, port)) {
   5654         *flags |= BCM_STK_INACTIVE;
   5655     }
   5656 
   5657     return BCM_E_NONE;
   5658 }
   5659 
   5660 #endif /* _BCM_STK_FLAGS_GET */
   5661 
   5662 #if defined(BCM_HERCULES_SUPPORT)
   5663 /*
   5664  * Set the unicast forwarding port bitmap
   5665  */
   5666 STATIC int
   5667 _bcm5675_stk_ucbitmap_set(int unit, bcm_port_t port, int modid, pbmp_t pbmp)
   5668 {
   5669     mem_uc_entry_t      uc;
   5670     int                 blk;
   5671     int                 rv;
   5672 
   5673     if (IS_CPU_PORT(unit, port)) {
   5674         return BCM_E_PORT;
   5675     }
   5676     blk = SOC_PORT_BLOCK(unit, port);
   5677     soc_mem_lock(unit, MEM_UCm);
   5678     rv = READ_MEM_UCm(unit, blk, modid, &uc);
   5679     if (rv >= 0) {
   5680         soc_MEM_UCm_field32_set(unit, &uc, UCBITMAPf,
   5681                     SOC_PBMP_WORD_GET(pbmp, 0));
   5682 
   5683         rv = WRITE_MEM_UCm(unit, blk, modid, &uc);
   5684     }
   5685     soc_mem_unlock(unit, MEM_UCm);
   5686     return rv;
   5687 }
   5688 
   5689 STATIC int
   5690 _bcm567x_stk_ucbitmap_get(int unit, bcm_port_t port, int modid, pbmp_t *pbmp)
   5691 {
   5692     mem_uc_entry_t  uc;
   5693     int             blk;
   5694 
   5695     if (port < 0) {
   5696         port = SOC_PORT(unit, hg, 0);
   5697     }
   5698     blk = SOC_PORT_BLOCK(unit, port);
   5699     SOC_IF_ERROR_RETURN(READ_MEM_UCm(unit, blk, modid, &uc));
   5700     SOC_PBMP_CLEAR(*pbmp);
   5701     SOC_PBMP_WORD_SET(*pbmp, 0,
   5702                       soc_MEM_UCm_field32_get(unit, &uc, UCBITMAPf));
   5703 
   5704     return BCM_E_NONE;
   5705 }
   5706 
   5707 STATIC int
   5708 _bcm567x_stk_ucbitmap_del(int unit, bcm_port_t port, int modid, bcm_pbmp_t pbmp)
   5709 {
   5710     mem_uc_entry_t  uc;
   5711     int             blk;
   5712     int             rv;
   5713     uint32          fval;
   5714 
   5715     /* Clear UCbitmap for port & MH.DST_MODID */
   5716     blk = SOC_PORT_BLOCK(unit, port);
   5717     soc_mem_lock(unit, MEM_UCm);
   5718     rv = READ_MEM_UCm(unit, blk, modid, &uc);
   5719     if (rv >= 0) {
   5720         soc_MEM_UCm_field_get(unit, &uc, UCBITMAPf, &fval);
   5721         fval &= ~SOC_PBMP_WORD_GET(pbmp, 0);
   5722         soc_MEM_UCm_field_set(unit, &uc, UCBITMAPf, &fval);
   5723         rv = WRITE_MEM_UCm(unit, blk, modid, &uc);
   5724     }
   5725     soc_mem_unlock(unit, MEM_UCm);
   5726     return rv;
   5727 }
   5728 
   5729 #endif  /* BCM_XGS12_FABRIC_SUPPORT */
   5730 
   5731 #if defined(BCM_FIREBOLT_SUPPORT)
   5732 STATIC int
   5733 _bcm56504_stk_ucbitmap_set(int unit, int modid, pbmp_t pbmp)
   5734 {
   5735     modport_map_entry_t uc;
   5736     int rv;
   5737     uint32 map;
   5738     int offset;
   5739     pbmp_t non_stk_port;
   5740 
   5741     /* Check that port pbmp has only stack ports */
   5742     SOC_PBMP_ASSIGN(non_stk_port, pbmp);
   5743     SOC_PBMP_REMOVE(non_stk_port, PBMP_ST_ALL(unit));
   5744     if (SOC_PBMP_NOT_NULL(non_stk_port)) {
   5745         return BCM_E_PORT;
   5746     }
   5747 
   5748     offset = SOC_IS_RAPTOR(unit) ? 1 : SOC_HG_OFFSET(unit);
   5749     map = SOC_PBMP_WORD_GET(pbmp, 0) >> offset;
   5750     soc_mem_lock(unit, MODPORT_MAPm);
   5751     rv = READ_MODPORT_MAPm(unit, MEM_BLOCK_ANY, modid, &uc);
   5752     if (rv >= 0) {
   5753         soc_MODPORT_MAPm_field32_set(unit, &uc, HIGIG_PORT_BITMAPf,
   5754                                      map);
   5755         rv = WRITE_MODPORT_MAPm(unit, MEM_BLOCK_ALL, modid, &uc);
   5756     }
   5757     soc_mem_unlock(unit, MODPORT_MAPm);
   5758     return rv;
   5759 }
   5760 
   5761 STATIC int
   5762 _bcm56504_stk_ucbitmap_get(int unit, int modid, pbmp_t *pbmp)
   5763 {
   5764     modport_map_entry_t uc;
   5765     uint32 map;
   5766     int offset;
   5767 
   5768     offset = SOC_IS_RAPTOR(unit) ? 1 : SOC_HG_OFFSET(unit);
   5769     SOC_IF_ERROR_RETURN
   5770         (READ_MODPORT_MAPm(unit, MEM_BLOCK_ANY, modid, &uc));
   5771     map = soc_MODPORT_MAPm_field32_get(unit, &uc, HIGIG_PORT_BITMAPf);
   5772     SOC_PBMP_CLEAR(*pbmp);
   5773     SOC_PBMP_WORD_SET(*pbmp, 0, (map << offset));
   5774 
   5775     return BCM_E_NONE;
   5776 }
   5777 
   5778 STATIC int
   5779 _bcm56504_stk_ucbitmap_del(int unit, int modid, bcm_pbmp_t pbmp)
   5780 {
   5781     modport_map_entry_t uc;
   5782     int rv;
   5783     uint32 fval;
   5784     uint32 map;
   5785     int offset;
   5786     pbmp_t non_stk_port;
   5787 
   5788     /* Check that port pbmp has only stack ports */
   5789     SOC_PBMP_ASSIGN(non_stk_port, pbmp);
   5790     SOC_PBMP_REMOVE(non_stk_port, PBMP_ST_ALL(unit));
   5791     if (SOC_PBMP_NOT_NULL(non_stk_port)) {
   5792         return BCM_E_PORT;
   5793     }
   5794 
   5795     offset = SOC_IS_RAPTOR(unit) ? 1 : SOC_HG_OFFSET(unit);
   5796 
   5797     /* Convert port to HG bitmap */
   5798     map = SOC_PBMP_WORD_GET(pbmp, 0) >> offset;
   5799     soc_mem_lock(unit, MODPORT_MAPm);
   5800     rv = READ_MODPORT_MAPm(unit, MEM_BLOCK_ANY, modid, &uc);
   5801     if (rv >= 0) {
   5802         fval = soc_MODPORT_MAPm_field32_get(unit, &uc, HIGIG_PORT_BITMAPf);
   5803         fval &= ~map;
   5804         soc_MODPORT_MAPm_field32_set(unit, &uc, HIGIG_PORT_BITMAPf, fval);
   5805         rv = WRITE_MODPORT_MAPm(unit, MEM_BLOCK_ALL, modid, &uc);
   5806     }
   5807     soc_mem_unlock(unit, MODPORT_MAPm);
   5808     return rv;
   5809 }
   5810 #endif /* BCM_FIREBOLT_SUPPORT */
   5811 
   5812 /*
   5813  * Function:
   5814  *      bcm_stk_ucbitmap_set
   5815  * Purpose:
   5816  *      Set the unicast forwarding port bitmap
   5817  * Parameters:
   5818  *      unit  - SOC unit#
   5819  *      port - ingress port number
   5820  *      modid - destination module ID index (from HiGig mod header)
   5821  *      pbmp - forwarding port bitmap
   5822  * Returns:
   5823  *      BCM_E_XXX
   5824  * Note:
   5825  *      Fabric only
   5826  */
   5827 int
   5828 bcm_esw_stk_ucbitmap_set(int unit, bcm_port_t port, int modid, pbmp_t pbmp)
   5829 {
   5830     BCM_STK_API_TH3_SUPPORT_CHECK(unit);
   5831 
   5832     if (BCM_GPORT_IS_SET(port)) {
   5833         BCM_IF_ERROR_RETURN(
   5834             bcm_esw_port_local_get(unit, port, &port));
   5835     }
   5836 
   5837 #ifdef  BCM_HERCULES_SUPPORT
   5838     if (SOC_IS_HERCULES15(unit)) {
   5839         return _bcm5675_stk_ucbitmap_set(unit, port, modid, pbmp);
   5840     }
   5841 #endif  /* BCM_XGS12_FABRIC_SUPPORT */
   5842 
   5843 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT)
   5844     if (SOC_IS_HBX(unit) || SOC_IS_TR_VL(unit)) {
   5845         bcm_port_t dest_port, dest_port_array[96]={0};
   5846         int count;
   5847 
   5848         if (!SOC_MODID_ADDRESSABLE(unit, modid)) {
   5849             return BCM_E_PARAM;
   5850         }
   5851 
   5852         count = 0;
   5853         BCM_PBMP_ITER(pbmp, dest_port) {
   5854             if (count >= 96) {
   5855                 return BCM_E_RESOURCE;
   5856             }
   5857             dest_port_array[count] = dest_port;
   5858             count++;
   5859         }
   5860 #ifdef BCM_TRIDENT_SUPPORT
   5861         if (soc_feature(unit, soc_feature_modport_map_dest_is_port_or_trunk)) {
   5862             return bcm_td_stk_port_modport_op(unit,
   5863                     _BCM_STK_PORT_MODPORT_OP_SET,
   5864                     port, modid, dest_port_array, count);
   5865         } else
   5866 #endif /* BCM_TRIDENT_SUPPORT */
   5867         {
   5868             return _bcm_stk_port_modport_op(unit,
   5869                     _BCM_STK_PORT_MODPORT_OP_SET,
   5870                     port, modid, dest_port_array, count);
   5871         }
   5872     }
   5873 #endif  /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */
   5874 
   5875 #ifdef  BCM_FIREBOLT_SUPPORT
   5876     if (SOC_IS_FBX(unit)) {
   5877         COMPILER_REFERENCE(port);
   5878         return _bcm56504_stk_ucbitmap_set(unit, modid, pbmp);
   5879     }
   5880 #endif  /* BCM_FIREBOLT_SUPPORT */
   5881 
   5882     return BCM_E_UNAVAIL;
   5883 }
   5884 
   5885 /*
   5886  * Function:
   5887  *      bcm_stk_ucbitmap_get
   5888  * Purpose:
   5889  *      Get the unicast forwarding port bitmap
   5890  * Parameters:
   5891  *      unit  - SOC unit#
   5892  *      port - ingress port number
   5893  *      modid - destination module ID index (from HiGig mod header)
   5894  *      pbmp - (out)forwarding port bitmap
   5895  * Returns:
   5896  *      BCM_E_XXX
   5897  * Note:
   5898  *      Fabric only
   5899  */
   5900 int
   5901 bcm_esw_stk_ucbitmap_get(int unit, bcm_port_t port, int modid, pbmp_t *pbmp)
   5902 {
   5903     BCM_STK_API_TH3_SUPPORT_CHECK(unit);
   5904 
   5905     if (BCM_GPORT_IS_SET(port)) {
   5906         BCM_IF_ERROR_RETURN(
   5907             bcm_esw_port_local_get(unit, port, &port));
   5908     }
   5909 
   5910 #ifdef  BCM_XGS12_FABRIC_SUPPORT
   5911     if (SOC_IS_XGS12_FABRIC(unit)) {
   5912         return _bcm567x_stk_ucbitmap_get(unit, port, modid, pbmp);
   5913     }
   5914 #endif  /* BCM_XGS12_FABRIC_SUPPORT */
   5915 
   5916 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT)
   5917     if (SOC_IS_HBX(unit) || SOC_IS_TR_VL(unit)) {
   5918         bcm_port_t dest_port_array[96];
   5919         int count, index, rv;
   5920 
   5921         if (!SOC_MODID_ADDRESSABLE(unit, modid)) {
   5922             return BCM_E_PARAM;
   5923         }
   5924 
   5925 #ifdef BCM_TRIDENT_SUPPORT
   5926         if (soc_feature(unit, soc_feature_modport_map_dest_is_port_or_trunk)) {
   5927             rv = bcm_td_stk_port_modport_get(unit, port, modid, 96,
   5928                     dest_port_array, &count);
   5929         } else
   5930 #endif /* BCM_TRIDENT_SUPPORT */
   5931         {
   5932             rv =_bcm_stk_port_modport_get(unit, port, modid, 96,
   5933                     dest_port_array, &count);
   5934         }
   5935         if (rv == BCM_E_NOT_FOUND) {
   5936             BCM_PBMP_CLEAR(*pbmp);
   5937             return BCM_E_NONE;
   5938         } else if (BCM_FAILURE(rv)) {
   5939             return rv;
   5940         }
   5941         BCM_PBMP_CLEAR(*pbmp);
   5942         for (index = 0; index < count; index++) {
   5943             BCM_PBMP_PORT_ADD(*pbmp, dest_port_array[index]);
   5944         }
   5945         return BCM_E_NONE;
   5946     }
   5947 #endif  /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */
   5948 
   5949 #ifdef  BCM_FIREBOLT_SUPPORT
   5950     if (SOC_IS_FBX(unit)) {
   5951         COMPILER_REFERENCE(port);
   5952         return _bcm56504_stk_ucbitmap_get(unit, modid, pbmp);
   5953     }
   5954 #endif  /* BCM_FIREBOLT_SUPPORT */
   5955 
   5956     return BCM_E_UNAVAIL;
   5957 }
   5958 
   5959 /*
   5960  * Function:
   5961  *      bcm_stk_ucbitmap_del
   5962  * Purpose:
   5963  *      Remove a group of ports from a Unicast (UC) table entry for
   5964  *      a given ingress port.
   5965  * Parameters:
   5966  *      unit  - SOC unit#
   5967  *      port  - ingress port number
   5968  *      modid - destination module ID index (in HiGig mod header)
   5969  *      pbmp  - forwarding port bitmap
   5970  * Returns:
   5971  *      BCM_E_XXX
   5972  * Note:
   5973  *      Fabric only
   5974  */
   5975 int
   5976 bcm_esw_stk_ucbitmap_del(int unit, bcm_port_t port, int modid, bcm_pbmp_t pbmp)
   5977 {
   5978     BCM_STK_API_TH3_SUPPORT_CHECK(unit);
   5979 
   5980     if (BCM_GPORT_IS_SET(port)) {
   5981         BCM_IF_ERROR_RETURN(
   5982             bcm_esw_port_local_get(unit, port, &port));
   5983     }
   5984 
   5985 #ifdef  BCM_XGS12_FABRIC_SUPPORT
   5986     if (SOC_IS_XGS12_FABRIC(unit)) {
   5987         return _bcm567x_stk_ucbitmap_del(unit, port, modid, pbmp);
   5988     }
   5989 #endif  /* BCM_XGS12_FABRIC_SUPPORT */
   5990 
   5991 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT)
   5992     if (SOC_IS_HBX(unit) || SOC_IS_TR_VL(unit)) {
   5993         bcm_port_t dest_port, dest_port_array[96]={0};
   5994         int count;
   5995 
   5996         if (!SOC_MODID_ADDRESSABLE(unit, modid)) {
   5997             return BCM_E_PARAM;
   5998         }
   5999 
   6000         count = 0;
   6001         BCM_PBMP_ITER(pbmp, dest_port) {
   6002             if (count >= 96) {
   6003                 return BCM_E_RESOURCE;
   6004             }
   6005             dest_port_array[count] = dest_port;
   6006             count++;
   6007         }
   6008 #ifdef BCM_TRIDENT_SUPPORT
   6009         if (soc_feature(unit, soc_feature_modport_map_dest_is_port_or_trunk)) {
   6010             return bcm_td_stk_port_modport_op(unit,
   6011                     _BCM_STK_PORT_MODPORT_OP_DELETE,
   6012                     port, modid, dest_port_array, count);
   6013         } else
   6014 #endif /* BCM_TRIDENT_SUPPORT */
   6015         {
   6016             return _bcm_stk_port_modport_op(unit,
   6017                     _BCM_STK_PORT_MODPORT_OP_DELETE,
   6018                     port, modid, dest_port_array, count);
   6019         }
   6020     }
   6021 #endif  /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */
   6022 
   6023 #ifdef  BCM_FIREBOLT_SUPPORT
   6024     if (SOC_IS_FBX(unit)) {
   6025         COMPILER_REFERENCE(port);
   6026         return _bcm56504_stk_ucbitmap_del(unit, modid, pbmp);
   6027     }
   6028 #endif  /* BCM_FIREBOLT_SUPPORT */
   6029 
   6030     return BCM_E_UNAVAIL;
   6031 }
   6032 #if defined(BCM_METROLITE_SUPPORT)
   6033 /* Function:
   6034  *     _bcm_metrolite_stk_fmod_lmod_mapping_set
   6035  * Purpose:
   6036  *     Similar function as bcm_esw_stk_fmod_lmod_mapping_set, 
   6037  *     but Metrolite has different register formats for 
   6038  *     ING_MODMAP_CTRL and EGR_MODMAP_CTRL 
   6039  */
   6040 int 
   6041 _bcm_metrolite_stk_fmod_lmod_mapping_set(int unit, bcm_port_t port,
   6042                          bcm_module_t fmod, bcm_module_t lmod) {
   6043     uint32 reg32, oreg32;
   6044     int rv;
   6045 
   6046     if ((rv = READ_ING_MODMAP_CTRLr(unit, port, &oreg32)) >= 0) {
   6047          reg32 = oreg32;
   6048          soc_reg_field_set(unit, ING_MODMAP_CTRLr, &reg32,
   6049                            MODULEID_OFFSETf, (fmod - lmod));
   6050          if (reg32 != oreg32) {
   6051              rv = WRITE_ING_MODMAP_CTRLr(unit, port, reg32);
   6052              if (rv >= 0) {
   6053                  /*ING and EGR Registers will be sync. No need to
   6054                    check again if value changed. */
   6055                  rv = READ_EGR_MODMAP_CTRLr(unit, port, &reg32);
   6056                  if (rv < 0) {
   6057                      ESW_STK_UNLOCK;
   6058                      return rv;
   6059                  }
   6060                  soc_reg_field_set(unit, EGR_MODMAP_CTRLr, &reg32,
   6061                                    MODULEID_OFFSETf, (fmod - lmod));
   6062                  rv = WRITE_EGR_MODMAP_CTRLr(unit, port, reg32);
   6063             }
   6064         }
   6065         mod_map_data[unit]->l_modid[port] = lmod;
   6066     }
   6067 #ifdef BCM_WARM_BOOT_SUPPORT
   6068     SOC_CONTROL_LOCK(unit);
   6069     SOC_CONTROL(unit)->scache_dirty = 1;
   6070     SOC_CONTROL_UNLOCK(unit);
   6071 #endif
   6072 
   6073     return rv;
   6074 }
   6075 #endif
   6076 /*
   6077  * Function:
   6078  *      bcm_stk_fmod_lmod_mapping_set
   6079  * Purpose:
   6080  *      Set up mapping of (FMODID, FPORT) <--> (LMODID, LPORT) on
   6081  *      a fabric port.  Assigns base FMODID and LMODID to devices
   6082  *      in the legacy domain attached to a fabric port. When fmod is
   6083  *      -1, l_modid state is populated with "lmod" value that is
   6084  *      passed (if it is valid)
   6085  * Parameters:
   6086  *      unit - StrataSwitch PCI device unit number (driver internal).
   6087  *      port - StrataSwitch port number
   6088  *      fmod - Fabric Module Identifier
   6089  *      lmod - Local Module Identifier
   6090  *      enable - modmap enable = 1, disable = 0
   6091  * Returns:
   6092  *      BCM_E_NONE - Success.
   6093  *      BCM_E_XXX - Failure.
   6094  * Notes:
   6095  *      Fabric only (BCM5675).
   6096  *      The fmod assignment will be
   6097  *      Switch-1   LMODID = lmod     FMODID = fmod
   6098  *      Switch-2   LMODID = lmod + 1 FMODID = fmod + 1
   6099  *      Switch-3   LMODID = lmod + 2 FMODID = fmod + 2
   6100  *      Switch-4   LMODID = lmod + 3 FMODID = fmod + 3
   6101  *      and so on.
   6102  */
   6103 
   6104 int
   6105 bcm_esw_stk_fmod_lmod_mapping_set(int unit, bcm_port_t port,
   6106                     bcm_module_t fmod, bcm_module_t lmod)
   6107 {
   6108 #if defined(LOCAL_MODMAP_SUPPORT)
   6109     uint32  reg32, oreg32;
   6110     int     rv = BCM_E_UNAVAIL;
   6111 
   6112     BCM_MODMAP_FEATURE_CHECK(unit, bcm_stk_fmod_lmod_mapping_set);
   6113     LMOD_RANGE_CHECK(lmod);
   6114     MOD_MAP_DATA_CHECK(unit);
   6115     if (SOC_WARM_BOOT(unit) || fmod == -1) {
   6116         ESW_STK_LOCK;
   6117         mod_map_data[unit]->l_modid[port] = lmod;
   6118         ESW_STK_UNLOCK;
   6119         return BCM_E_NONE;
   6120     }
   6121 
   6122     FMOD_RANGE_CHECK(fmod);
   6123     FMOD_LMOD_CHECK(fmod, lmod);
   6124 
   6125     if (BCM_GPORT_IS_SET(port)) {
   6126         BCM_IF_ERROR_RETURN(
   6127             bcm_esw_port_local_get(unit, port, &port));
   6128     }
   6129 
   6130     ESW_STK_LOCK;
   6131 #if defined(BCM_METROLITE_SUPPORT) 
   6132     if (SOC_IS_METROLITE(unit)) {
   6133         /* Metrolite supports only 64 MODIDs. Jira SDK-82046 */ 
   6134         if ((fmod - lmod) > 63) {
   6135             ESW_STK_UNLOCK;
   6136             return BCM_E_PARAM;
   6137         }
   6138         rv = _bcm_metrolite_stk_fmod_lmod_mapping_set(unit, port, fmod, lmod);
   6139         ESW_STK_UNLOCK;
   6140         return rv;
   6141     }
   6142 #endif
   6143 
   6144 #if defined(BCM_BRADLEY_SUPPORT) || defined(BCM_TRIUMPH_SUPPORT)
   6145     if (SOC_IS_HBX(unit) || SOC_IS_TR_VL(unit)) {
   6146         if ((rv = READ_ING_MODMAP_CTRLr(unit, port, &oreg32)) >= 0) {
   6147             reg32 = oreg32;
   6148             soc_reg_field_set(unit, ING_MODMAP_CTRLr, &reg32,
   6149                               MODULEID_OFFSETf, (fmod - lmod));
   6150             if (reg32 != oreg32) {
   6151                 rv = WRITE_ING_MODMAP_CTRLr(unit, port, reg32);
   6152                 if (rv >= 0) {
   6153                     /* We must keep the ingress and egress copies in sync */
   6154                     rv = WRITE_EGR_MODMAP_CTRLr(unit, port, reg32);
   6155                 }
   6156             }
   6157             mod_map_data[unit]->l_modid[port] = lmod;
   6158         }
   6159 
   6160         
   6161 
   6162     } else
   6163 #endif /* BCM_BRADLEY_SUPPORT || BCM_TRIUMPH_SUPPORT */
   6164     {
   6165 #if defined(BCM_HERCULES_SUPPORT)
   6166         if ((rv = READ_MODMAP_CTRLr(unit, port, &oreg32)) >= 0) {
   6167             reg32 = oreg32;
   6168             soc_reg_field_set(unit, MODMAP_CTRLr, &reg32,
   6169                               MODULE_ID_OFFSETf, (fmod - lmod));
   6170             if (reg32 != oreg32) {
   6171                 rv = WRITE_MODMAP_CTRLr(unit, port, reg32);
   6172             }
   6173             mod_map_data[unit]->l_modid[port] = lmod;
   6174         }
   6175 #endif
   6176     }
   6177     ESW_STK_UNLOCK;
   6178 
   6179 #ifdef BCM_WARM_BOOT_SUPPORT
   6180     SOC_CONTROL_LOCK(unit);
   6181     SOC_CONTROL(unit)->scache_dirty = 1;
   6182     SOC_CONTROL_UNLOCK(unit);
   6183 #endif
   6184 
   6185     return(rv);
   6186 #else
   6187     return BCM_E_UNAVAIL;
   6188 #endif  /* MODMAP_SUPPORT */
   6189 }
   6190 
   6191 /*
   6192  * Function:
   6193  *      bcm_stk_fmod_lmod_mapping_get
   6194  * Purpose:
   6195  *      Get the (FMODID, LMODID) associated with a fabric port.
   6196  *      Gets the base FMODID and LMODID assigned to the devices
   6197  *      in the legacy domain attached to this fabric port.
   6198  * Parameters:
   6199  *      unit - StrataSwitch PCI device unit number (driver internal).
   6200  *      port - StrataSwitch port number
   6201  *      fmod - (OUT) Fabric Module Identifier
   6202  *      lmod - (OUT)Local Module Identifier
   6203  * Returns:
   6204  *      BCM_E_NONE - Success.
   6205  *      BCM_E_XXX - Failure.
   6206  * Notes:
   6207  *      Fabric only (BCM5675)
   6208  */
   6209 
   6210 int
   6211 bcm_esw_stk_fmod_lmod_mapping_get(int unit, bcm_port_t port,
   6212                     bcm_module_t *fmod, bcm_module_t *lmod)
   6213 {
   6214 #if defined(LOCAL_MODMAP_SUPPORT)
   6215     uint32  oreg32;
   6216 
   6217     BCM_MODMAP_FEATURE_CHECK(unit, bcm_stk_fmod_lmod_mapping_get);
   6218     MOD_MAP_DATA_CHECK(unit);
   6219 
   6220     if (BCM_GPORT_IS_SET(port)) {
   6221         BCM_IF_ERROR_RETURN(
   6222             bcm_esw_port_local_get(unit, port, &port));
   6223     }
   6224 
   6225 #if defined(BCM_BRADLEY_SUPPORT) || defined(BCM_TRIUMPH_SUPPORT)
   6226     if (SOC_IS_HBX(unit) || SOC_IS_TR_VL(unit)) {
   6227         SOC_IF_ERROR_RETURN(READ_ING_MODMAP_CTRLr(unit, port, &oreg32));
   6228         *fmod = soc_reg_field_get(unit, ING_MODMAP_CTRLr, oreg32,
   6229                                   MODULEID_OFFSETf);
   6230     } else
   6231 #endif /* BCM_BRADLEY_SUPPORT || BCM_TRIUMPH_SUPPORT */
   6232     {
   6233 #if defined(BCM_HERCULES_SUPPORT)
   6234         SOC_IF_ERROR_RETURN(READ_MODMAP_CTRLr(unit, port, &oreg32));
   6235         *fmod = soc_reg_field_get(unit, MODMAP_CTRLr, oreg32,
   6236                                   MODULE_ID_OFFSETf);
   6237 #else
   6238 		return BCM_E_UNAVAIL;
   6239 #endif
   6240     }
   6241 
   6242     *lmod = mod_map_data[unit]->l_modid[port];
   6243     *fmod += *lmod;
   6244 
   6245     return(BCM_E_NONE);
   6246 #else
   6247     return BCM_E_UNAVAIL;
   6248 #endif  /* BCM_MODMAP_SUPPORT */
   6249 }
   6250 
   6251 #ifdef BCM_BRADLEY_SUPPORT
   6252 int
   6253 _bcm_stk_fmod_smod_mapping_group_set(int unit, int group,
   6254                       bcm_module_t fmod, bcm_module_t smod,
   6255                       bcm_port_t sport, uint32 nports)
   6256 {
   6257     int rv=BCM_E_NONE;
   6258     ing_mod_map_table_entry_t  immap;
   6259     egr_mod_map_table_entry_t  emmap;
   6260     int         i, found, group_offset_ing, group_offset_egr;
   6261     uint32      fval;
   6262     uint32      thresh;
   6263     soc_field_t tf[] = {THRESH_Af, THRESH_Bf, THRESH_Cf, INVALIDf};
   6264     soc_field_t pf[] = {PORTOFF_Af, PORTOFF_Bf, PORTOFF_Cf, PORTOFF_Df};
   6265     soc_field_t mf[] = {MOD_Af, MOD_Bf, MOD_Cf, MOD_Df, INVALIDf};
   6266 
   6267     /* Note: Parameter checks were performed before calling this function */
   6268     if (group == 1) {
   6269         group_offset_ing = soc_mem_index_count(unit, ING_MOD_MAP_TABLEm) / 2;
   6270         group_offset_egr = soc_mem_index_count(unit, EGR_MOD_MAP_TABLEm) / 2;
   6271     } else { /* group == 0 */
   6272         group_offset_ing = 0;
   6273         group_offset_egr = 0;
   6274     }
   6275 
   6276     if (nports != 0) {
   6277         SPORT_RANGE_CHECK((sport + nports - 1));
   6278 
   6279         sal_memset(&emmap, 0, sizeof(emmap));
   6280         soc_EGR_MOD_MAP_TABLEm_field_set(unit, &emmap,
   6281 				      PORT_OFFSETf, (uint32 *)&sport);
   6282         soc_EGR_MOD_MAP_TABLEm_field_set(unit, &emmap,
   6283 				      MODIDf, (uint32 *)&smod);
   6284         thresh = sport + nports - 1;
   6285 
   6286         ESW_STK_LOCK;
   6287 
   6288         if ((rv = READ_ING_MOD_MAP_TABLEm(unit, SOC_BLOCK_ANY,
   6289                                smod + group_offset_ing, &immap)) >= 0) {
   6290             found = 0;
   6291             for(i = 0; mf[i] != INVALIDf; i++) {
   6292                 soc_ING_MOD_MAP_TABLEm_field_get(unit, &immap, mf[i], &fval);
   6293                 if (fval == 0) {
   6294                     if (fmod==0) {
   6295                         mod_map_data[unit]->fmod0[group] = smod+1;
   6296                         break;  /* Found a slot for fmod 0 */
   6297                     }
   6298                     if ((mod_map_data[unit]->fmod0[group]) &&
   6299                         ((mod_map_data[unit]->fmod0[group] == (smod+1))) &&
   6300                         !(found)) {
   6301                         found=1; /* This is fmod 0 */
   6302                     } else {
   6303                         break;  /* Found a slot */
   6304                     }
   6305                 }
   6306             }
   6307 
   6308             if (mf[i] != INVALIDf) {
   6309                 for(; i > 0; i--) {
   6310                     soc_ING_MOD_MAP_TABLEm_field_get(
   6311                                     unit, &immap, tf[i - 1], &fval);
   6312                     /* THRESH_A < THRESH_B < THRESH_C */
   6313                     if (fval > thresh) {
   6314                         if (tf[i] != INVALIDf) {
   6315                             soc_ING_MOD_MAP_TABLEm_field_set(
   6316                                             unit, &immap, tf[i], &fval);
   6317                         } else {
   6318                             mod_map_data[unit]->thresh_d[smod] = fval;
   6319                         }
   6320                         soc_ING_MOD_MAP_TABLEm_field_get(
   6321                                         unit, &immap, pf[i - 1], &fval);
   6322                         soc_ING_MOD_MAP_TABLEm_field_set(
   6323                                         unit, &immap, pf[i], &fval);
   6324                         soc_ING_MOD_MAP_TABLEm_field_get(
   6325                                         unit, &immap, mf[i - 1], &fval);
   6326                         soc_ING_MOD_MAP_TABLEm_field_set(
   6327                                         unit, &immap, mf[i], &fval);
   6328                     } else {
   6329                         break;
   6330                     }
   6331                 }
   6332 
   6333                 if (tf[i] != INVALIDf) {
   6334                     soc_ING_MOD_MAP_TABLEm_field_set(
   6335                                     unit, &immap, tf[i], &thresh);
   6336                 } else {
   6337                     mod_map_data[unit]->thresh_d[smod] = thresh;
   6338                 }
   6339                 soc_ING_MOD_MAP_TABLEm_field_set(unit, &immap,
   6340                                                  pf[i], (uint32 *)&sport);
   6341                 soc_ING_MOD_MAP_TABLEm_field_set(unit, &immap,
   6342                                                  mf[i], (uint32 *)&fmod);
   6343                 rv = WRITE_EGR_MOD_MAP_TABLEm(unit, SOC_BLOCK_ALL,
   6344                                               fmod + group_offset_egr, &emmap);
   6345                 if (rv >= 0) {
   6346                     rv = WRITE_ING_MOD_MAP_TABLEm(unit, SOC_BLOCK_ALL,
   6347                                        smod + group_offset_ing, &immap);
   6348                 }
   6349             } else {
   6350                 rv = BCM_E_PARAM;
   6351             }
   6352         }
   6353         ESW_STK_UNLOCK;
   6354     } else {  /* This is actually a delete */
   6355         ESW_STK_LOCK;
   6356         if ((rv = READ_EGR_MOD_MAP_TABLEm(unit, SOC_BLOCK_ANY,
   6357                                    fmod + group_offset_egr, &emmap)) >= 0) {
   6358             bcm_port_t o_sport = -1;
   6359             bcm_module_t o_smod = -1;
   6360             int j;
   6361 
   6362             soc_EGR_MOD_MAP_TABLEm_field_get(unit, &emmap,
   6363                                              PORT_OFFSETf, (uint32 *)&o_sport);
   6364             soc_EGR_MOD_MAP_TABLEm_field_get(unit, &emmap,
   6365                                              MODIDf, (uint32 *)&o_smod);
   6366             sal_memset(&emmap, 0, sizeof(emmap));
   6367             if ((o_sport == sport) && (o_smod == smod)) {
   6368                 if ((rv = READ_ING_MOD_MAP_TABLEm(unit, SOC_BLOCK_ANY,
   6369                                    smod + group_offset_ing, &immap)) >= 0) {
   6370                     for(i = 0; mf[i] != INVALIDf; i++) {
   6371                         soc_ING_MOD_MAP_TABLEm_field_get(unit, &immap, mf[i], &fval);
   6372                         soc_ING_MOD_MAP_TABLEm_field_get(unit, &immap, pf[i], &thresh);
   6373                         if ((fval == (uint32)fmod) && (thresh == (uint32)sport)) {
   6374                             if (tf[i] == INVALIDf) {
   6375                                 mod_map_data[unit]->thresh_d[smod] = 0;
   6376                                 fval = 0;
   6377                                 soc_ING_MOD_MAP_TABLEm_field_set(unit, &immap, mf[i], &fval);
   6378                                 soc_ING_MOD_MAP_TABLEm_field_set(unit, &immap, pf[i], &fval);
   6379                             } else {
   6380                                 for (j = i; mf[j+1] != INVALIDf; j++) {
   6381                                     soc_ING_MOD_MAP_TABLEm_field_get(unit, &immap, pf[j+1], &fval);
   6382                                     soc_ING_MOD_MAP_TABLEm_field_set(unit, &immap, pf[j], &fval);
   6383                                     soc_ING_MOD_MAP_TABLEm_field_get(unit, &immap,mf[j+1], &fval);
   6384                                     soc_ING_MOD_MAP_TABLEm_field_set(unit, &immap, mf[j], &fval);
   6385                                     if (tf[j+1] != INVALIDf) {
   6386                                         soc_ING_MOD_MAP_TABLEm_field_get(unit, &immap, tf[j+1], &fval);
   6387                                         soc_ING_MOD_MAP_TABLEm_field_set(unit, &immap, tf[j], &fval);
   6388                                     }
   6389                                 }
   6390                                 fval = 0;
   6391                                 soc_ING_MOD_MAP_TABLEm_field_set(unit, &immap, pf[j], &fval);
   6392                                 soc_ING_MOD_MAP_TABLEm_field_set(unit, &immap, mf[j], &fval);
   6393                                 soc_ING_MOD_MAP_TABLEm_field_set(unit, &immap, tf[j-1], &fval);
   6394                             }
   6395                             break;
   6396                         }
   6397                     }
   6398                     if (mf[i] == INVALIDf) {
   6399                         rv = BCM_E_INTERNAL;
   6400                     } else {
   6401                         rv = WRITE_EGR_MOD_MAP_TABLEm(unit, SOC_BLOCK_ALL,
   6402                                            fmod + group_offset_egr, &emmap);
   6403                         if (rv >= 0) {
   6404                             rv = WRITE_ING_MOD_MAP_TABLEm(unit, SOC_BLOCK_ALL,
   6405                                            smod + group_offset_ing, &immap);
   6406                         }
   6407 
   6408                         if (fmod==0) {
   6409                             mod_map_data[unit]->fmod0[group] = 0;
   6410                         }
   6411                     }
   6412                 }
   6413             } else {
   6414                 rv = BCM_E_PARAM;
   6415             }
   6416         }
   6417         ESW_STK_UNLOCK;
   6418     }
   6419 
   6420     return(rv);
   6421 }
   6422 #endif /* BCM_BRADLEY_SUPPORT */
   6423 
   6424 /*
   6425  * Function:
   6426  *      bcm_stk_fmod_smod_mapping_set
   6427  * Purpose:
   6428  *      Set up mapping of (FMODID, FPORT) <--> (SMODID, SPORT) on fabric
   6429  * Parameters:
   6430  *      unit - StrataSwitch PCI device unit number (driver internal).
   6431  *      port - StrataSwitch port number (-1 = All ports)
   6432  *      fmod - Fabric Module Identifier
   6433  *      smod - Switch Module Identifier
   6434  *      sport - Switch Module Base Port
   6435  *      nports - Number of ports on switch device with fmod.
   6436  *               (0 to remove previously added entry).
   6437  * Returns:
   6438  *      BCM_E_NONE - Success.
   6439  *      BCM_E_XXX - Failure.
   6440  * Notes:
   6441  *      Fabric only (BCM5675)
   6442  */
   6443 
   6444 int
   6445 bcm_esw_stk_fmod_smod_mapping_set(int unit, bcm_port_t port,
   6446                       bcm_module_t fmod, bcm_module_t smod,
   6447                       bcm_port_t sport, uint32 nports)
   6448 {
   6449 #if defined(LOCAL_MODMAP_SUPPORT)
   6450     int rv=BCM_E_NONE;
   6451 #if defined(BCM_HERCULES_SUPPORT)
   6452     mem_ing_modmap_entry_t  immap;
   6453     mem_egr_modmap_entry_t  emmap;
   6454     int         bk=-1, blk;
   6455     int         i, found;
   6456     uint32      fval;
   6457     uint32      thresh;
   6458     soc_field_t tf[] = {THRESH_Af, THRESH_Bf, THRESH_Cf, INVALIDf};
   6459     soc_field_t pf[] = {PORTOFF_Af, PORTOFF_Bf, PORTOFF_Cf, PORTOFF_Df};
   6460     soc_field_t mf[] = {MOD_Af, MOD_Bf, MOD_Cf, MOD_Df, INVALIDf};
   6461 #endif
   6462 
   6463     BCM_MODMAP_FEATURE_CHECK(unit, bcm_stk_fmod_smod_mapping_set);
   6464 
   6465     LOG_VERBOSE(BSL_LS_BCM_STK,
   6466                 (BSL_META_U(unit,
   6467                             "STK unit %d port %d: Mapping fmod %d to smod %d sport %d "
   6468                              "for %d ports\n"), unit, port, fmod, smod, sport, nports));
   6469 
   6470     FMOD_RANGE_CHECK(fmod);
   6471     SMOD_RANGE_CHECK(smod);
   6472     MOD_MAP_DATA_CHECK(unit);
   6473 
   6474     if (BCM_GPORT_IS_SET(port)) {
   6475         BCM_IF_ERROR_RETURN(
   6476             bcm_esw_port_local_get(unit, port, &port));
   6477     }
   6478 
   6479     if (port >= 0) {
   6480         if (!IS_HG_PORT(unit, port)) {
   6481             return BCM_E_PARAM;
   6482         }
   6483 #if defined(BCM_HERCULES_SUPPORT)
   6484         bk = SOC_PORT_BLOCK(unit, port);
   6485 #endif
   6486     }
   6487 
   6488 #if defined(BCM_BRADLEY_SUPPORT) || defined(BCM_TRIUMPH_SUPPORT)
   6489     if (SOC_IS_HBX(unit) || SOC_IS_TR_VL(unit)) {
   6490         int group;
   6491 
   6492         /* After range checks, proceed */
   6493         if (port >= 0) {
   6494             /* Determine group offsets for the tables */
   6495             BCM_IF_ERROR_RETURN
   6496                 (bcm_esw_stk_port_modmap_group_get(unit, port, &group));
   6497             if ((group < 0) || (group > _XGS3_MODMAP_GROUPS_MAX)) {
   6498                 return BCM_E_PARAM;
   6499             }
   6500             return _bcm_stk_fmod_smod_mapping_group_set(unit, group, fmod,
   6501                                                         smod, sport, nports);
   6502         } else {
   6503             for (group = 0; group <= _XGS3_MODMAP_GROUPS_MAX; group++) {
   6504                 rv = _bcm_stk_fmod_smod_mapping_group_set(unit, group, fmod,
   6505                                                           smod, sport, nports);
   6506                 if (rv < 0) {
   6507                     break;
   6508                 }
   6509             }
   6510             return rv;
   6511         }
   6512     }
   6513 #endif /* BCM_BRADLEY_SUPPORT || BCM_TRIUMPH_SUPPORT */
   6514 #if defined(BCM_HERCULES_SUPPORT)
   6515     if (nports != 0) {
   6516         SPORT_RANGE_CHECK((sport + nports - 1));
   6517 
   6518         sal_memset(&emmap, 0, sizeof(emmap));
   6519         soc_MEM_EGR_MODMAPm_field_set(unit, &emmap,
   6520 				      PORT_OFFf, (uint32 *)&sport);
   6521         soc_MEM_EGR_MODMAPm_field_set(unit, &emmap,
   6522 				      MODf, (uint32 *)&smod);
   6523         thresh = sport + nports - 1;
   6524 
   6525         ESW_STK_LOCK;
   6526         SOC_MEM_BLOCK_ITER(unit, MEM_ING_MODMAPm, blk) {
   6527             if ((port >= 0) && (bk != blk)) {
   6528                 continue;
   6529             }
   6530 
   6531             if ((rv = READ_MEM_ING_MODMAPm(unit, blk, smod, &immap)) >= 0) {
   6532 
   6533                 found = 0;
   6534                 for(i = 0; mf[i] != INVALIDf; i++) {
   6535                     int p;
   6536                     soc_MEM_ING_MODMAPm_field_get(unit, &immap, mf[i], &fval);
   6537                     p = SOC_BLOCK_PORT(unit, blk);
   6538                     if (fval == 0) {
   6539                         if (fmod==0) {
   6540                             mod_map_data[unit]->fmod0[p] = smod+1;
   6541                             break;  /* Found a slot for fmod 0 */
   6542                         }
   6543                         if ((mod_map_data[unit]->fmod0[p]) &&
   6544                                 ((mod_map_data[unit]->fmod0[p] == (smod+1))) &&
   6545                                 !(found)) {
   6546                             found=1; /* This is fmod 0 */
   6547                         } else {
   6548                             break;  /* Found a slot */
   6549                         }
   6550                     }
   6551                 }
   6552 
   6553                 if (mf[i] != INVALIDf) {
   6554                     for(; i > 0; i--) {
   6555                         soc_MEM_ING_MODMAPm_field_get(
   6556                                     unit, &immap, tf[i - 1], &fval);
   6557                         /* THRESH_A < THRESH_B < THRESH_C */
   6558                         if (fval > thresh) {
   6559                             if (tf[i] != INVALIDf) {
   6560                                 soc_MEM_ING_MODMAPm_field_set(
   6561                                         unit, &immap, tf[i], &fval);
   6562                             } else {
   6563                                 mod_map_data[unit]->thresh_d[smod] = fval;
   6564                             }
   6565                             soc_MEM_ING_MODMAPm_field_get(
   6566                                     unit, &immap, pf[i - 1], &fval);
   6567                             soc_MEM_ING_MODMAPm_field_set(
   6568                                     unit, &immap, pf[i], &fval);
   6569                             soc_MEM_ING_MODMAPm_field_get(
   6570                                     unit, &immap, mf[i - 1], &fval);
   6571                             soc_MEM_ING_MODMAPm_field_set(
   6572                                     unit, &immap, mf[i], &fval);
   6573                         } else {
   6574                             break;
   6575                         }
   6576                     }
   6577 
   6578                     if (tf[i] != INVALIDf) {
   6579                         soc_MEM_ING_MODMAPm_field_set(unit, &immap, tf[i], &thresh);
   6580                     } else {
   6581                         mod_map_data[unit]->thresh_d[smod] = thresh;
   6582                     }
   6583                     soc_MEM_ING_MODMAPm_field_set(unit, &immap,
   6584 						  pf[i], (uint32 *)&sport);
   6585                     soc_MEM_ING_MODMAPm_field_set(unit, &immap,
   6586 						  mf[i], (uint32 *)&fmod);
   6587                     if ((rv = WRITE_MEM_EGR_MODMAPm(unit, blk, fmod, &emmap)) < 0) {
   6588                         break;
   6589                     }
   6590                     if ((rv = WRITE_MEM_ING_MODMAPm(unit, blk, smod, &immap)) < 0) {
   6591                         break;
   6592                     }
   6593                 } else {
   6594                     rv = BCM_E_PARAM;
   6595                 }
   6596             }
   6597         }
   6598         ESW_STK_UNLOCK;
   6599     } else {  /* This is actually a delete */
   6600         ESW_STK_LOCK;
   6601         SOC_MEM_BLOCK_ITER(unit, MEM_ING_MODMAPm, blk) {
   6602             if ((port >= 0) && (bk != blk)) {
   6603                 continue;
   6604             }
   6605 
   6606             if ((rv = READ_MEM_EGR_MODMAPm(unit, blk, fmod, &emmap)) >= 0) {
   6607                 bcm_port_t o_sport = -1;
   6608                 bcm_module_t o_smod = -1;
   6609                 int j, p;
   6610 
   6611                 soc_MEM_EGR_MODMAPm_field_get(unit, &emmap,
   6612 					      PORT_OFFf, (uint32 *)&o_sport);
   6613                 soc_MEM_EGR_MODMAPm_field_get(unit, &emmap,
   6614 					      MODf, (uint32 *)&o_smod);
   6615                 sal_memset(&emmap, 0, sizeof(emmap));
   6616                 if ((o_sport == sport) && (o_smod == smod)) {
   6617                     if ((rv = READ_MEM_ING_MODMAPm(unit, blk, smod, &immap)) >= 0) {
   6618                         for(i = 0; mf[i] != INVALIDf; i++) {
   6619                             soc_MEM_ING_MODMAPm_field_get(unit, &immap, mf[i], &fval);
   6620                             soc_MEM_ING_MODMAPm_field_get(unit, &immap, pf[i], &thresh);
   6621                             if ((fval == (uint32)fmod) && (thresh == (uint32)sport)) {
   6622                                 if (tf[i] == INVALIDf) {
   6623                                   mod_map_data[unit]->thresh_d[smod] = 0;
   6624                                   fval = 0;
   6625                                   soc_MEM_ING_MODMAPm_field_set(unit, &immap, mf[i], &fval);
   6626                                   soc_MEM_ING_MODMAPm_field_set(unit, &immap, pf[i], &fval);
   6627                                 } else {
   6628                                   for (j = i; mf[j+1] != INVALIDf; j++) {
   6629                                        soc_MEM_ING_MODMAPm_field_get(unit, &immap, pf[j+1], &fval);
   6630                                        soc_MEM_ING_MODMAPm_field_set(unit, &immap, pf[j], &fval);
   6631                                        soc_MEM_ING_MODMAPm_field_get(unit, &immap,mf[j+1], &fval);
   6632                                        soc_MEM_ING_MODMAPm_field_set(unit, &immap, mf[j], &fval);
   6633                                        if (tf[j+1] != INVALIDf) {
   6634                                            soc_MEM_ING_MODMAPm_field_get(unit, &immap, tf[j+1], &fval);
   6635                                            soc_MEM_ING_MODMAPm_field_set(unit, &immap, tf[j], &fval);
   6636                                        }
   6637                                   }
   6638                                   fval = 0;
   6639                                   soc_MEM_ING_MODMAPm_field_set(unit, &immap, pf[j], &fval);
   6640                                   soc_MEM_ING_MODMAPm_field_set(unit, &immap, mf[j], &fval);
   6641                                   soc_MEM_ING_MODMAPm_field_set(unit, &immap, tf[j-1], &fval);
   6642                                 }
   6643                                 break;
   6644                             }
   6645                         }
   6646                         if (mf[i] == INVALIDf) {
   6647                             rv = BCM_E_INTERNAL;
   6648                             break;
   6649                         }
   6650 
   6651                         if ((rv = WRITE_MEM_EGR_MODMAPm(unit, blk, fmod, &emmap)) < 0) {
   6652                              break;
   6653                         }
   6654                         if ((rv = WRITE_MEM_ING_MODMAPm(unit, blk, smod, &immap)) < 0) {
   6655                              break;
   6656                         }
   6657 
   6658                         if (fmod==0) {
   6659                             p = SOC_BLOCK_PORT(unit, blk);
   6660                             mod_map_data[unit]->fmod0[p] = 0;
   6661                         }
   6662                     }
   6663                 } else {
   6664                       rv = BCM_E_PARAM;
   6665                 }
   6666             }
   6667         }
   6668         ESW_STK_UNLOCK;
   6669     }
   6670 #endif /*BCM_HERCULES_SUPPORT */
   6671 
   6672 #ifdef BCM_WARM_BOOT_SUPPORT
   6673     SOC_CONTROL_LOCK(unit);
   6674     SOC_CONTROL(unit)->scache_dirty = 1;
   6675     SOC_CONTROL_UNLOCK(unit);
   6676 #endif
   6677 
   6678     return(rv);
   6679 #else
   6680     return BCM_E_UNAVAIL;
   6681 #endif  /* MODMAP_SUPPORT */
   6682 }
   6683 
   6684 #ifdef BCM_BRADLEY_SUPPORT
   6685 int
   6686 _bcm_stk_fmod_smod_mapping_group_get(int unit, bcm_port_t port,
   6687                       bcm_module_t fmod, bcm_module_t *smod,
   6688                       bcm_port_t *sport, uint32 *nports)
   6689 {
   6690     int rv;
   6691     ing_mod_map_table_entry_t  immap;
   6692     egr_mod_map_table_entry_t  emmap;
   6693     uint32      fval;
   6694     uint32      sp_val;
   6695     int         i, group, group_offset_ing, group_offset_egr;
   6696     soc_field_t tf[] = {THRESH_Af, THRESH_Bf, THRESH_Cf, INVALIDf};
   6697     soc_field_t pf[] = {PORTOFF_Af, PORTOFF_Bf, PORTOFF_Cf, PORTOFF_Df};
   6698     soc_field_t mf[] = {MOD_Af, MOD_Bf, MOD_Cf, MOD_Df, INVALIDf};
   6699 
   6700     /* Determine group offsets for the tables */
   6701     BCM_IF_ERROR_RETURN
   6702         (bcm_esw_stk_port_modmap_group_get(unit, port, &group));
   6703 
   6704     if (group != 0) {
   6705         group_offset_ing = soc_mem_index_count(unit, ING_MOD_MAP_TABLEm) / 2;
   6706         group_offset_egr = soc_mem_index_count(unit, EGR_MOD_MAP_TABLEm) / 2;
   6707     } else {
   6708         group_offset_ing = 0;
   6709         group_offset_egr = 0;
   6710     }
   6711 
   6712     ESW_STK_LOCK;
   6713     if ((rv = READ_EGR_MOD_MAP_TABLEm(unit, SOC_BLOCK_ANY,
   6714                                       fmod + group_offset_egr, &emmap)) >= 0) {
   6715         soc_EGR_MOD_MAP_TABLEm_field_get(unit, &emmap,
   6716                                          PORT_OFFSETf, (uint32 *)sport);
   6717         soc_EGR_MOD_MAP_TABLEm_field_get(unit, &emmap,
   6718                                          MODIDf, (uint32 *)smod);
   6719         if ((rv = READ_ING_MOD_MAP_TABLEm(unit, SOC_BLOCK_ANY,
   6720                                *smod + group_offset_ing, &immap)) >= 0) {
   6721             for(i = 0; mf[i] != INVALIDf; i++) {
   6722                 soc_ING_MOD_MAP_TABLEm_field_get(unit, &immap, mf[i], &fval);
   6723                 soc_ING_MOD_MAP_TABLEm_field_get(unit, &immap, pf[i], &sp_val);
   6724                 if ((fval == (uint32)fmod) && ((uint32)*sport == sp_val)) {
   6725                     if (tf[i] != INVALIDf) {
   6726                         soc_ING_MOD_MAP_TABLEm_field_get(
   6727                                     unit, &immap, tf[i], &fval);
   6728                     } else {
   6729                         fval = mod_map_data[unit]->thresh_d[*smod];
   6730                     }
   6731                     *nports = fval - sp_val + 1;
   6732                     break; /* Found */
   6733                 }
   6734             }
   6735             if (mf[i] == INVALIDf ||
   6736                ((fmod==0) && (mod_map_data[unit]->fmod0[group] != (*smod+1)))) {
   6737                 rv = BCM_E_NOT_FOUND;
   6738             }
   6739         }
   6740     }
   6741     ESW_STK_UNLOCK;
   6742 
   6743     return(rv);
   6744 }
   6745 #endif /* BCM_BRADLEY_SUPPORT */
   6746 
   6747 /*
   6748  * Function:
   6749  *      bcm_stk_fmod_smod_mapping_get
   6750  * Purpose:
   6751  *      Get the (SMODID, BASE_SPORT) and num ports associated with
   6752  *      switch device with fmod
   6753  * Parameters:
   6754  *      unit - StrataSwitch PCI device unit number (driver internal).
   6755  *      port - StrataSwitch port number
   6756  *      fmod - Fabric Module Identifier
   6757  *      smod - (OUT) Switch Module Identifier
   6758  *      sport - (OUT) Switch Module Base Port
   6759  *      nports - (OUT) Number of ports on switch device with fmod.
   6760  * Returns:
   6761  *      BCM_E_NONE - Success.
   6762  *      BCM_E_XXX - Failure.
   6763  * Notes:
   6764  *      Fabric only (BCM5675)
   6765  */
   6766 
   6767 int
   6768 bcm_esw_stk_fmod_smod_mapping_get(int unit, bcm_port_t port,
   6769                       bcm_module_t fmod, bcm_module_t *smod,
   6770                       bcm_port_t *sport, uint32 *nports)
   6771 {
   6772 #if defined(LOCAL_MODMAP_SUPPORT)
   6773     int rv = BCM_E_UNAVAIL;
   6774 #if defined(BCM_HERCULES_SUPPORT)
   6775     mem_ing_modmap_entry_t  immap;
   6776     mem_egr_modmap_entry_t  emmap;
   6777     uint32      fval;
   6778     uint32      sp_val;
   6779     int         blk;
   6780     int         p;
   6781     int         i;
   6782     soc_field_t tf[] = {THRESH_Af, THRESH_Bf, THRESH_Cf, INVALIDf};
   6783     soc_field_t pf[] = {PORTOFF_Af, PORTOFF_Bf, PORTOFF_Cf, PORTOFF_Df};
   6784     soc_field_t mf[] = {MOD_Af, MOD_Bf, MOD_Cf, MOD_Df, INVALIDf};
   6785 #endif
   6786     BCM_MODMAP_FEATURE_CHECK(unit, bcm_stk_fmod_smod_mapping_get);
   6787 
   6788     if (BCM_GPORT_IS_SET(port)) {
   6789         BCM_IF_ERROR_RETURN(
   6790             bcm_esw_port_local_get(unit, port, &port));
   6791     }
   6792 
   6793     if (!IS_HG_PORT(unit, port)) {
   6794         return BCM_E_PARAM;
   6795     }
   6796 
   6797 #if defined(BCM_BRADLEY_SUPPORT) || defined(BCM_TRIUMPH_SUPPORT)
   6798     if (SOC_IS_HBX(unit) || SOC_IS_TR_VL(unit)) {
   6799         /* After range checks, proceed */
   6800         return _bcm_stk_fmod_smod_mapping_group_get(unit, port, fmod, smod,
   6801                                                     sport, nports);
   6802     }
   6803 #endif /* BCM_BRADLEY_SUPPORT || BCM_TRIUMPH_SUPPORT */
   6804 
   6805 #if defined(BCM_HERCULES_SUPPORT)
   6806     blk = SOC_PORT_BLOCK(unit, port);
   6807 
   6808     ESW_STK_LOCK;
   6809     if ((rv = READ_MEM_EGR_MODMAPm(unit, blk, fmod, &emmap)) >= 0) {
   6810         soc_MEM_EGR_MODMAPm_field_get(unit, &emmap,
   6811 				      PORT_OFFf, (uint32 *)sport);
   6812         soc_MEM_EGR_MODMAPm_field_get(unit, &emmap,
   6813 				      MODf, (uint32 *)smod);
   6814         if ((rv = READ_MEM_ING_MODMAPm(unit, blk, *smod, &immap)) >= 0) {
   6815             for(i = 0; mf[i] != INVALIDf; i++) {
   6816                 soc_MEM_ING_MODMAPm_field_get(unit, &immap, mf[i], &fval);
   6817                 soc_MEM_ING_MODMAPm_field_get(unit, &immap, pf[i], &sp_val);
   6818                 if ((fval == (uint32)fmod) && ((uint32)*sport == sp_val)) {
   6819                     if (tf[i] != INVALIDf) {
   6820                         soc_MEM_ING_MODMAPm_field_get(
   6821                                     unit, &immap, tf[i], &fval);
   6822                     } else {
   6823                         fval = mod_map_data[unit]->thresh_d[*smod];
   6824                     }
   6825                     *nports = fval - sp_val + 1;
   6826                     break; /* Found */
   6827                 }
   6828             }
   6829             p = SOC_BLOCK_PORT(unit, blk);
   6830             if (mf[i] == INVALIDf ||
   6831                ((fmod==0) && (mod_map_data[unit]->fmod0[p] != (*smod+1)))) {
   6832                 rv = BCM_E_NOT_FOUND;
   6833             }
   6834         }
   6835     }
   6836     ESW_STK_UNLOCK;
   6837 #endif /* BCM_HERCULES_SUPPORT */
   6838     return(rv);
   6839 #else
   6840     return BCM_E_UNAVAIL;
   6841 #endif  /* MODMAP_SUPPORT */
   6842 }
   6843 #if defined(BCM_METROLITE_SUPPORT)
   6844 /* 
   6845  * Function:
   6846  *     _bcm_metrolite_stk_port_modmap_group_set
   6847  * Purpose:
   6848  *     similar to bcm_stk_port_modmap_group_set, 
   6849  *     but metrolite has different register formats for 
   6850  *     ING_MODMAP_CTRL and EGR_MODMAP_CTRL
   6851  */
   6852 int
   6853 _bcm_metrolite_stk_port_modmap_group_set(int unit, bcm_port_t port, int group)
   6854 {
   6855     uint32 reg32, oreg32;
   6856     int rv;
   6857     if ((rv = READ_ING_MODMAP_CTRLr(unit, port, &oreg32)) >= 0) {
   6858         reg32 = oreg32;
   6859         soc_reg_field_set(unit, ING_MODMAP_CTRLr, &reg32,
   6860                           ING_MOD_MAP_IDf, group ? 1 : 0);
   6861         if (reg32 != oreg32) {
   6862             rv = WRITE_ING_MODMAP_CTRLr(unit, port, reg32);
   6863             if (rv >= 0) {
   6864                 /*ING and EGR Registers will be sync. No need to
   6865                   check again if value changed. */
   6866                 rv = READ_EGR_MODMAP_CTRLr(unit, port, &reg32);
   6867                 if (rv < 0) {
   6868                     ESW_STK_UNLOCK;
   6869                     return rv;
   6870                 }
   6871                 soc_reg_field_set(unit, EGR_MODMAP_CTRLr, &reg32,
   6872                          EGR_MOD_MAP_IDf, group ? 1 : 0);
   6873                 rv = WRITE_EGR_MODMAP_CTRLr(unit, port, reg32);
   6874             }
   6875         }
   6876     }
   6877 #ifdef BCM_WARM_BOOT_SUPPORT
   6878     SOC_CONTROL_LOCK(unit);
   6879     SOC_CONTROL(unit)->scache_dirty = 1;
   6880     SOC_CONTROL_UNLOCK(unit);
   6881 #endif
   6882     return rv;
   6883 }
   6884 #endif
   6885 /*
   6886 * Function:
   6887 *      bcm_stk_port_modmap_group_set
   6888 * Purpose:
   6889 *      Assign module mapping group for port to use
   6890 * Parameters:
   6891 *      unit - StrataSwitch PCI device unit number (driver internal).
   6892 *      port - StrataSwitch port number (-1 = All ports)
   6893 *      group - Module mapping group
   6894 * Returns:
   6895 *      BCM_E_NONE - Success.
   6896 *      BCM_E_XXX - Failure.
   6897 * Notes:
   6898 *      Fabric only
   6899 */
   6900 
   6901 int
   6902 bcm_esw_stk_port_modmap_group_set(int unit, bcm_port_t port, int group)
   6903 {
   6904 #if defined(LOCAL_MODMAP_SUPPORT)
   6905     int rv = 0;
   6906     BCM_MODMAP_FEATURE_CHECK(unit, bcm_stk_port_modmap_group_set);
   6907 
   6908     if (BCM_GPORT_IS_SET(port)) {
   6909         BCM_IF_ERROR_RETURN(
   6910             bcm_esw_port_local_get(unit, port, &port));
   6911     }
   6912 
   6913     if (!IS_HG_PORT(unit, port)) {
   6914         return BCM_E_PARAM;
   6915     }
   6916 #if defined(BCM_METROLITE_SUPPORT)
   6917     if (SOC_IS_METROLITE(unit)) {
   6918         if ((group < 0) || (group > _XGS3_MODMAP_GROUPS_MAX)) {
   6919             return BCM_E_PARAM;
   6920         }
   6921         ESW_STK_LOCK; 
   6922         rv = _bcm_metrolite_stk_port_modmap_group_set(unit, port, group);    
   6923         ESW_STK_UNLOCK;
   6924         return rv;
   6925     }
   6926 #endif
   6927 #if defined(BCM_BRADLEY_SUPPORT) || defined(BCM_TRIUMPH_SUPPORT)
   6928     if (SOC_IS_HBX(unit) || SOC_IS_TR_VL(unit)) {
   6929         uint32  reg32, oreg32;
   6930 
   6931         if ((group < 0) || (group > _XGS3_MODMAP_GROUPS_MAX)) {
   6932             return BCM_E_PARAM;
   6933         }
   6934 
   6935         ESW_STK_LOCK;
   6936 
   6937         if ((rv = READ_ING_MODMAP_CTRLr(unit, port, &oreg32)) >= 0) {
   6938             reg32 = oreg32;
   6939             soc_reg_field_set(unit, ING_MODMAP_CTRLr, &reg32,
   6940                               ING_MOD_MAP_IDf, group ? 1 : 0);
   6941             if (reg32 != oreg32) {
   6942                 rv = WRITE_ING_MODMAP_CTRLr(unit, port, reg32);
   6943                 if (rv >= 0) {
   6944                     /* We must keep the ingress and egress copies in sync */
   6945                     rv = WRITE_EGR_MODMAP_CTRLr(unit, port, reg32);
   6946                 }
   6947             }
   6948         }
   6949         ESW_STK_UNLOCK;
   6950     } else
   6951 #endif /* BCM_BRADLEY_SUPPORT || BCM_TRIUMPH_SUPPORT */
   6952     {
   6953         /* Only identity mapping allowed */
   6954         if (group != (port - 1)) {
   6955             return BCM_E_PARAM;
   6956         }
   6957     }
   6958 
   6959 #ifdef BCM_WARM_BOOT_SUPPORT
   6960     SOC_CONTROL_LOCK(unit);
   6961     SOC_CONTROL(unit)->scache_dirty = 1;
   6962     SOC_CONTROL_UNLOCK(unit);
   6963 #endif
   6964 
   6965     return BCM_E_NONE;
   6966 #else
   6967     return BCM_E_UNAVAIL;
   6968 #endif  /* MODMAP_SUPPORT */
   6969 }
   6970 
   6971 /*
   6972 * Function:
   6973 *      bcm_stk_port_modmap_group_get
   6974 * Purpose:
   6975 *      Retrieve module mapping group selected for port
   6976 * Parameters:
   6977 *      unit - StrataSwitch PCI device unit number (driver internal).
   6978 *      port - StrataSwitch port number (-1 = All ports)
   6979 *      group - (OUT) Module mapping group
   6980 * Returns:
   6981 *      BCM_E_NONE - Success.
   6982 *      BCM_E_XXX - Failure.
   6983 * Notes:
   6984 *      Fabric only
   6985 */
   6986 
   6987 int
   6988 bcm_esw_stk_port_modmap_group_get(int unit, bcm_port_t port, int *group)
   6989 {
   6990 #if defined(LOCAL_MODMAP_SUPPORT)
   6991     BCM_MODMAP_FEATURE_CHECK(unit, bcm_esw_stk_port_modmap_group_get);
   6992 
   6993     if (BCM_GPORT_IS_SET(port)) {
   6994         BCM_IF_ERROR_RETURN(
   6995             bcm_esw_port_local_get(unit, port, &port));
   6996     }
   6997 
   6998     if (!IS_HG_PORT(unit, port)) {
   6999         return BCM_E_PARAM;
   7000     }
   7001 
   7002 #if defined(BCM_BRADLEY_SUPPORT) || defined(BCM_TRIUMPH_SUPPORT)
   7003     if (SOC_IS_HBX(unit) || SOC_IS_TR_VL(unit)) {
   7004         uint32  oreg32;
   7005         SOC_IF_ERROR_RETURN(READ_ING_MODMAP_CTRLr(unit, port, &oreg32));
   7006         *group = soc_reg_field_get(unit, ING_MODMAP_CTRLr, oreg32,
   7007                                    ING_MOD_MAP_IDf);
   7008     } else
   7009 #endif /* BCM_BRADLEY_SUPPORT || BCM_TRIUMPH_SUPPORT */
   7010     {
   7011         *group = port - 1;
   7012     }
   7013     return BCM_E_NONE;
   7014 #else
   7015     return BCM_E_UNAVAIL;
   7016 #endif  /* MODMAP_SUPPORT */
   7017 }
   7018 
   7019 /*
   7020 * Function:
   7021 *      bcm_stk_port_modmap_group_max_get
   7022 * Purpose:
   7023 *      Retrieve maximum module mapping group allowed on device
   7024 * Parameters:
   7025 *      unit - StrataSwitch PCI device unit number (driver internal).
   7026 *      max_group - (OUT) Module mapping group
   7027 * Returns:
   7028 *      BCM_E_NONE - Success.
   7029 *      BCM_E_XXX - Failure.
   7030 * Notes:
   7031 *      Fabric only
   7032 */
   7033 
   7034 int
   7035 bcm_esw_stk_port_modmap_group_max_get(int unit, int *max_group)
   7036 {
   7037 #if defined(LOCAL_MODMAP_SUPPORT)
   7038     BCM_MODMAP_FEATURE_CHECK(unit, bcm_stk_port_modmap_group_max_get);
   7039 
   7040     if (SOC_IS_HBX(unit) || SOC_IS_TR_VL(unit)) {
   7041         *max_group = _XGS3_MODMAP_GROUPS_MAX;
   7042     } else {
   7043         *max_group = SOC_MAX_NUM_PORTS - 1;
   7044     }
   7045 
   7046     return BCM_E_NONE;
   7047 #else
   7048     return BCM_E_UNAVAIL;
   7049 #endif  /* MODMAP_SUPPORT */
   7050 }
   7051 
   7052 /*
   7053  * Function:
   7054  *      bcm_stk_modmap_enable_set
   7055  * Purpose:
   7056  *      Enable/Disable Modid mapping on a given fabric port.
   7057  * Parameters:
   7058  *      unit - StrataSwitch PCI device unit number (driver internal).
   7059  *      port - StrataSwitch port number
   7060  *      enable -  Modmap enabled flag. 1 = enabled 0 = disabled
   7061  * Returns:
   7062  *      BCM_E_NONE - Success.
   7063  *      BCM_E_XXX - Failure.
   7064  * Notes:
   7065  *      Fabric only (BCM5675)
   7066  */
   7067 
   7068 int
   7069 bcm_esw_stk_modmap_enable_set(int unit,
   7070               bcm_port_t port, int enable)
   7071 {
   7072 #if defined(LOCAL_MODMAP_SUPPORT)
   7073     uint32  reg32, oreg32;
   7074     int     rv;
   7075 
   7076     BCM_MODMAP_FEATURE_CHECK(unit, bcm_stk_modmap_enable_set);
   7077 
   7078     LOG_VERBOSE(BSL_LS_BCM_STK,
   7079                 (BSL_META_U(unit,
   7080                             "STK %d: %sabling mod mapping port %d\n"),
   7081                  unit, enable ? "En" : "Dis", port));
   7082 
   7083     if (BCM_GPORT_IS_SET(port)) {
   7084         BCM_IF_ERROR_RETURN(
   7085             bcm_esw_port_local_get(unit, port, &port));
   7086     }
   7087 
   7088 
   7089     if (!IS_ST_PORT(unit, port)) {
   7090         return BCM_E_PORT;
   7091     }
   7092 
   7093     ESW_STK_LOCK;
   7094 #if defined(BCM_METROLITE_SUPPORT)
   7095     if (SOC_IS_METROLITE(unit)) {
   7096         if ((rv = READ_ING_MODMAP_CTRLr(unit, port, &oreg32)) >= 0) {
   7097             reg32 = oreg32;
   7098             soc_reg_field_set(unit, ING_MODMAP_CTRLr, &reg32,
   7099                               ING_MAP_ENf, enable ? 1 : 0);
   7100             if (reg32 != oreg32) {
   7101                 rv = WRITE_ING_MODMAP_CTRLr(unit, port, reg32);
   7102                 if (rv >= 0) {
   7103                     /*ING and EGR Registers will be sync. No need to
   7104                       check again if value changed. */
   7105                     rv = READ_EGR_MODMAP_CTRLr(unit, port, &reg32);
   7106                     if (rv < 0) {
   7107                         ESW_STK_UNLOCK;
   7108                         return rv;
   7109                     }
   7110                     soc_reg_field_set(unit, EGR_MODMAP_CTRLr, &reg32,
   7111                     EGR_MAP_ENf, enable?1:0);
   7112                     rv = WRITE_EGR_MODMAP_CTRLr(unit, port, reg32);
   7113                 }
   7114             }
   7115         }
   7116         ESW_STK_UNLOCK;
   7117         return rv;
   7118     }
   7119 #endif
   7120 
   7121 #if defined(BCM_BRADLEY_SUPPORT) || defined(BCM_TRIUMPH_SUPPORT)
   7122     if (SOC_IS_HBX(unit) || SOC_IS_TR_VL(unit)) {
   7123         if ((rv = READ_ING_MODMAP_CTRLr(unit, port, &oreg32)) >= 0) {
   7124             reg32 = oreg32;
   7125             soc_reg_field_set(unit, ING_MODMAP_CTRLr, &reg32,
   7126                               ING_MAP_ENf, enable ? 1 : 0);
   7127             if (reg32 != oreg32) {
   7128                 rv = WRITE_ING_MODMAP_CTRLr(unit, port, reg32);
   7129                 if (rv >= 0) {
   7130                     /* We must keep the ingress and egress copies in sync */
   7131                     rv = WRITE_EGR_MODMAP_CTRLr(unit, port, reg32);
   7132                 }
   7133             }
   7134         }
   7135     } else
   7136 #endif /* BCM_BRADLEY_SUPPORT || BCM_TRIUMPH_SUPPORT */
   7137     {
   7138 #if defined(BCM_HERCULES_SUPPORT)
   7139         if ((rv = READ_MODMAP_CTRLr(unit, port, &oreg32)) >=0 ) {
   7140             reg32 = oreg32;
   7141             soc_reg_field_set(unit, MODMAP_CTRLr, &reg32,
   7142                               EGR_MAP_ENf, (enable)?1:0);
   7143             soc_reg_field_set(unit, MODMAP_CTRLr, &reg32,
   7144                               ING_MAP_ENf, (enable)?1:0);
   7145             if (reg32 != oreg32) {
   7146                 rv = WRITE_MODMAP_CTRLr(unit, port, reg32);
   7147             }
   7148         }
   7149 #endif
   7150     }
   7151     ESW_STK_UNLOCK;
   7152 
   7153     return(BCM_E_NONE);
   7154 #else
   7155     return BCM_E_UNAVAIL;
   7156 #endif  /* MODMAP_SUPPORT */
   7157 }
   7158 
   7159 /*
   7160  * Function:
   7161  *      bcm_stk_modmap_enable_get
   7162  * Purpose:
   7163  *      Get Modid mapping Enable/Disable state on a given fabric port.
   7164  * Parameters:
   7165  *      unit - StrataSwitch PCI device unit number (driver internal).
   7166  *      port - (OUT) StrataSwitch port number
   7167  *      enable - (OUT) Modmap enabled flag. 1 = enabled 0 = disabled
   7168  * Returns:
   7169  *      BCM_E_NONE - Success.
   7170  *      BCM_E_XXX - Failure.
   7171  * Notes:
   7172  *      Fabric only (BCM5675)
   7173  */
   7174 
   7175 int
   7176 bcm_esw_stk_modmap_enable_get(int unit,
   7177               bcm_port_t port, int *enable)
   7178 {
   7179 #if defined(LOCAL_MODMAP_SUPPORT)
   7180 #if defined(BCM_HERCULES_SUPPORT)
   7181     uint32  oreg32;
   7182 #endif
   7183     uint32  i_enable;
   7184     uint32  e_enable;
   7185 
   7186     BCM_MODMAP_FEATURE_CHECK(unit, bcm_stk_modmap_enable_get);
   7187     if (!IS_ST_PORT(unit, port)) {
   7188         return BCM_E_PORT;
   7189     }
   7190 
   7191 #if defined(BCM_BRADLEY_SUPPORT) || defined(BCM_TRIUMPH_SUPPORT)
   7192     if (SOC_IS_HBX(unit) || SOC_IS_TR_VL(unit)) {
   7193         uint32  oreg32;
   7194 
   7195         SOC_IF_ERROR_RETURN(READ_ING_MODMAP_CTRLr(unit, port, &oreg32));
   7196         i_enable = soc_reg_field_get(unit, ING_MODMAP_CTRLr, oreg32,
   7197                                      ING_MAP_ENf);
   7198         SOC_IF_ERROR_RETURN(READ_EGR_MODMAP_CTRLr(unit, port, &oreg32));
   7199         e_enable = soc_reg_field_get(unit, EGR_MODMAP_CTRLr, oreg32,
   7200                                      EGR_MAP_ENf);
   7201     } else
   7202 #endif /* BCM_BRADLEY_SUPPORT || BCM_TRIUMPH_SUPPORT */
   7203     {
   7204 #if defined(BCM_HERCULES_SUPPORT)
   7205         SOC_IF_ERROR_RETURN(READ_MODMAP_CTRLr(unit, port, &oreg32));
   7206         i_enable = soc_reg_field_get(unit, MODMAP_CTRLr, oreg32, ING_MAP_ENf);
   7207         e_enable = soc_reg_field_get(unit, MODMAP_CTRLr, oreg32, EGR_MAP_ENf);
   7208 #else
   7209         return BCM_E_UNAVAIL;
   7210 #endif
   7211     }
   7212     *enable = (i_enable && e_enable);
   7213     if ((i_enable || e_enable) != *enable) {
   7214         return(BCM_E_INTERNAL); /* Error if only Ing or Egr map  enabled */
   7215     }
   7216 
   7217     return(BCM_E_NONE);
   7218 #else
   7219     return BCM_E_UNAVAIL;
   7220 #endif  /* MODMAP_SUPPORT */
   7221 }
   7222 
   7223 /*
   7224  * Module ID Mapping on Switch Chips
   7225  *
   7226  * The programming of module/port destinations that are external to a
   7227  * switch chip must match the mapping that is programmed into the
   7228  * associated fabric chips.  Rather than trying to provide an
   7229  * arbitrarily complex set of APIs to do this for the application, a
   7230  * callback can be registered to map each module/port pair when it is
   7231  * stored into hardware or fetched from hardware.
   7232  *
   7233  * For more information, refer to $SDK/doc/modid-mapping.txt.
   7234  */
   7235 
   7236 bcm_stk_modmap_cb_t     _bcm_stk_modmap_cb[BCM_MAX_NUM_UNITS];
   7237 
   7238 /*
   7239  * Function:
   7240  *      bcm_stk_modmap_register
   7241  * Purpose:
   7242  *      Register module ID mapping/unmapping callback function
   7243  * Parameters:
   7244  *      unit - SOC unit #
   7245  *      func - User callback function for module ID mapping/unmapping
   7246  */
   7247 int
   7248 bcm_esw_stk_modmap_register(int unit, bcm_stk_modmap_cb_t func)
   7249 {
   7250     if (!SOC_UNIT_VALID(unit)) {
   7251         return BCM_E_UNIT;
   7252     }
   7253     if (!SOC_IS_XGS_SWITCH(unit)) {
   7254         return BCM_E_PARAM;
   7255     }
   7256 
   7257     BCM_STK_API_TH3_SUPPORT_CHECK(unit);
   7258 
   7259     _bcm_stk_modmap_cb[unit] = func;
   7260     return BCM_E_NONE;
   7261 }
   7262 
   7263 /*
   7264  * Function:
   7265  *      bcm_stk_modmap_unregister
   7266  * Purpose:
   7267  *      Unregister module ID mapping/unmapping callback function
   7268  * Parameters:
   7269  *      unit - SOC unit #
   7270  */
   7271 int
   7272 bcm_esw_stk_modmap_unregister(int unit)
   7273 {
   7274     BCM_STK_API_TH3_SUPPORT_CHECK(unit);
   7275 
   7276     _bcm_stk_modmap_cb[unit] = NULL;
   7277     return BCM_E_NONE;
   7278 }
   7279 
   7280 /*
   7281  * Function:
   7282  *      _bcm_stk_modmap_map
   7283  * Purpose:
   7284  *      Internal function to call module ID mapping/unmapping callback function
   7285  * Parameters:
   7286  *      unit    - (IN) SOC unit #
   7287  *      setget  - (IN) Mapping direction identifier BCM_STK_MODMAP_GET or BCM_STK_MODMAP_SET
   7288  *      mod_in  - (IN) Module Id to map 
   7289  *      port_in  - (IN) Physical port to map no GPORT accepted
   7290  *      mod_out - (OUT) Module Id after mapping
   7291  *      port_out - (OUT) Physical port after mapping not a GPORT
   7292  * Notes:
   7293  *      This function is called from within the BCM API implementations
   7294  *      whenever module ID mapping is needed. 
   7295  */
   7296 int
   7297 _bcm_esw_stk_modmap_map(int unit, int setget,
   7298                    bcm_module_t mod_in, bcm_port_t port_in,
   7299                    bcm_module_t *mod_out, bcm_port_t *port_out)
   7300 {
   7301     int         rv = BCM_E_NONE;
   7302     bcm_module_t mod;
   7303     bcm_port_t  port;
   7304 
   7305     if (!SOC_UNIT_VALID(unit)) {
   7306         return BCM_E_UNIT;
   7307     }
   7308 
   7309     if ((port_in != -1) && (setget == BCM_STK_MODMAP_GET)) {
   7310         /* Before the mapping, if multiple modid mode is enabled, adjust the
   7311          * mod/port such that any port number above modport_max setting is
   7312          * considered to be in the next module.
   7313          */
   7314 
   7315          if (NUM_MODID(unit) > 1) {
   7316 #if defined(BCM_TOMAHAWK_SUPPORT)
   7317             /* Call asymmetric dual modid mapping function to split the 
   7318              * ports asymmetrically between two modids.
   7319              */
   7320             if (soc_feature(unit, soc_feature_asymmetric_dual_modid) &&
   7321                             port_in > SOC_MODPORT_MAX_FIRST(unit)) {
   7322                 BCM_IF_ERROR_RETURN (
   7323                     _bcm_esw_stk_asymmetric_dual_modmap_map(unit, setget,
   7324                                 &mod_in, &port_in));
   7325             } else
   7326 #endif /* BCM_TOMAHAWK_SUPPORT */
   7327             if (port_in > SOC_MODPORT_MAX(unit)) {
   7328                 bcm_module_t my_modid;
   7329                 BCM_IF_ERROR_RETURN (bcm_esw_stk_my_modid_get(unit, &my_modid));
   7330                 if ((mod_in == my_modid) && (BCM_MODID_INVALID != mod_in)) {
   7331                     mod_in += port_in / (SOC_MODPORT_MAX(unit) + 1);
   7332                     port_in %= (SOC_MODPORT_MAX(unit) + 1);
   7333                 }
   7334             }
   7335         }
   7336     }
   7337 
   7338     if ((_bcm_stk_modmap_cb[unit] != NULL) && (BCM_MODID_INVALID != mod_in)) {
   7339         rv = (*_bcm_stk_modmap_cb[unit])(unit, setget,
   7340                                          mod_in, port_in,
   7341                                          &mod, &port);
   7342         if (rv < 0) {
   7343             mod = mod_in;
   7344             port = port_in;
   7345         }
   7346     } else {
   7347         /* default identity mapping */
   7348         mod = mod_in;
   7349         port = port_in;
   7350     }
   7351     if ((rv >= 0) && (port_in != -1) && (setget == BCM_STK_MODMAP_SET)) {
   7352         /* After the mapping, if multiply-modid mode is enabled, adjust the
   7353          * mod/port such that all ports are considered to be in the first
   7354          * module.
   7355          */
   7356         if (NUM_MODID(unit) > 1) {
   7357             bcm_module_t my_modid;
   7358             int          isLocal;
   7359             BCM_IF_ERROR_RETURN (bcm_esw_stk_my_modid_get(unit, &my_modid));
   7360             if (BCM_MODID_INVALID != my_modid){
   7361                 BCM_IF_ERROR_RETURN
   7362                     (_bcm_esw_modid_is_local(unit, mod, &isLocal));
   7363                 if (isLocal) {
   7364 #if defined(BCM_TOMAHAWK_SUPPORT)
   7365                     /* Call asymmetric dual modid unmapping function */
   7366                     if (soc_feature(unit, soc_feature_asymmetric_dual_modid)) {
   7367                         BCM_IF_ERROR_RETURN (
   7368                             _bcm_esw_stk_asymmetric_dual_modmap_map(unit,
   7369                                                 setget, &mod_in, &port_in));
   7370                         port = port_in;
   7371                         mod = my_modid;
   7372                     } else
   7373 #endif /* BCM_TOMAHAWK_SUPPORT */
   7374                     {
   7375                         port += (mod - my_modid) * (SOC_MODPORT_MAX(unit) + 1);
   7376                         mod = my_modid;
   7377                     }
   7378                 }
   7379             }
   7380         }
   7381     }
   7382     if (port_out != NULL) {
   7383         *port_out = port;
   7384     }
   7385     if (mod_out != NULL) {
   7386         *mod_out = mod;
   7387     }
   7388 
   7389     return rv;
   7390 }
   7391 
   7392 
   7393 #ifdef BCM_TOMAHAWK_SUPPORT
   7394 /*
   7395 * Function:
   7396 *      _bcm_esw_stk_asymmetric_dual_modmap_map
   7397 * Purpose:
   7398 *      Internal function for asymmetric dual module ID mapping/unmapping
   7399 * Parameters:
   7400 *      unit     - (IN)  SOC unit #
   7401 *      setget   - (IN)  Mapping direction identifier BCM_STK_MODMAP_GET
   7402                         or BCM_STK_MODMAP_SET
   7403 *      mod_in   - (IN)  Module Id to map
   7404 *      port_in  - (IN)  Physical port to map no GPORT accepted
   7405 *      mod_out  - (OUT) Module Id after mapping
   7406 *      port_out - (OUT) Physical port after mapping not a GPORT
   7407 * Notes:
   7408 *      This function is called from within the BCM API implementations
   7409 *      whenever asymmetric dual module ID mapping is needed.
   7410 */
   7411 int
   7412 _bcm_esw_stk_asymmetric_dual_modmap_map(int unit, int setget,
   7413                     bcm_module_t *mod_in, bcm_port_t *port_in)
   7414 {
   7415     bcm_module_t my_modid;
   7416 
   7417     /* Input parameters check. */
   7418     if (!SOC_UNIT_VALID(unit)) {
   7419         return BCM_E_UNIT;
   7420     }
   7421 
   7422     /* Get local modulel ID */
   7423     BCM_IF_ERROR_RETURN (bcm_esw_stk_my_modid_get(unit, &my_modid));
   7424 
   7425     /* For TH, the port split used is (64 + 128(use 72)) between two modids.
   7426      * Adjust mod/port such that any port number between modport_max_first
   7427      * and modport_max considered to be in next module.
   7428      */
   7429     if((*mod_in == my_modid) && (BCM_MODID_INVALID != *mod_in)) {
   7430         if (setget == BCM_STK_MODMAP_GET &&
   7431                         *port_in > SOC_MODPORT_MAX_FIRST(unit)) {
   7432             *port_in += (SOC_MODPORT_MAX(unit) + 1) -
   7433                         (SOC_MODPORT_MAX_FIRST(unit) + 1);
   7434             *mod_in += *port_in / (SOC_MODPORT_MAX(unit) + 1);
   7435             *port_in %= (SOC_MODPORT_MAX(unit) + 1);
   7436         }
   7437     }
   7438 
   7439     /* Adjust the mod/port such that all ports are considered to be in
   7440      * the first module.
   7441      */
   7442     if (setget == BCM_STK_MODMAP_SET) {
   7443         *port_in += (*mod_in - my_modid) * (SOC_MODPORT_MAX_FIRST(unit) + 1);
   7444     }
   7445 
   7446 /*
   7447     if (port_out != NULL) {
   7448         *port_out = port_in;
   7449     }
   7450     if (mod_out != NULL) {
   7451         *mod_out = mod_in;
   7452     }
   7453     */
   7454 
   7455     return (BCM_E_NONE);
   7456 }
   7457 #endif /* BCM_TOMAHAWK_SUPPORT */
   7458 
   7459 
   7460 /*
   7461  * Function:
   7462  *      bcm_stk_modmap_map
   7463  * Purpose:
   7464  *      Call module ID mapping/unmapping callback function
   7465  * Parameters:
   7466  *      unit - SOC unit #
   7467  * Notes:
   7468  *      This function is called from within the BCM API implementations
   7469  *      whenever module ID mapping is needed, but it can also be called
   7470  *      by the user application for informational purposes.
   7471  */
   7472 int
   7473 bcm_esw_stk_modmap_map(int unit, int setget,
   7474                    bcm_module_t mod_in, bcm_port_t port_in,
   7475                    bcm_module_t *mod_out, bcm_port_t *port_out)
   7476 {
   7477     bcm_port_t      tmp_port;
   7478     bcm_module_t    tmp_modid;
   7479     bcm_trunk_t     tmp_tgid;
   7480     int             tmp_id, isGport;
   7481     _bcm_gport_dest_t gport_st;
   7482 
   7483     BCM_STK_API_TH3_SUPPORT_CHECK(unit);
   7484 
   7485     if (BCM_GPORT_IS_SET(port_in)) {
   7486         BCM_IF_ERROR_RETURN(
   7487             _bcm_esw_gport_resolve(unit, port_in, &tmp_modid, &tmp_port, 
   7488                                    &tmp_tgid, &tmp_id));
   7489         if ((BCM_TRUNK_INVALID != tmp_tgid) || 
   7490             (-1 != tmp_id)) {
   7491             return BCM_E_PORT;
   7492         }
   7493     } else {
   7494         tmp_port = port_in;
   7495         tmp_modid = mod_in;
   7496     }
   7497 
   7498     BCM_IF_ERROR_RETURN(
   7499         _bcm_esw_stk_modmap_map(unit, setget, tmp_modid, tmp_port, 
   7500                                 mod_out, port_out));
   7501     BCM_IF_ERROR_RETURN(
   7502         bcm_esw_switch_control_get(unit, bcmSwitchUseGport, &isGport));
   7503     if (TRUE == isGport) {
   7504         gport_st.modid = *mod_out;
   7505         gport_st.port = *port_out;
   7506         gport_st.gport_type = _SHR_GPORT_TYPE_MODPORT;
   7507         BCM_IF_ERROR_RETURN(
   7508             _bcm_esw_gport_construct(unit, &gport_st, port_out));
   7509         *mod_out = -1;
   7510     }
   7511 
   7512     return BCM_E_NONE;
   7513 }
   7514 
   7515 /****************************************************************
   7516  *
   7517  * Procedures related to source module ID base indexing
   7518  */
   7519 
   7520 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_HURRICANE3_SUPPORT)
   7521 #if defined BCM_MONTEREY_SUPPORT
   7522 STATIC int
   7523 soc_egr_gpp_attribute_set(int unit, int base_index)
   7524 {
   7525     bcm_pbmp_t          all_pbmp;
   7526     bcm_port_t          port = 0;
   7527     int                 max_index = 0;
   7528 
   7529     SOC_PBMP_CLEAR(all_pbmp);
   7530     BCM_PBMP_ASSIGN(all_pbmp, PBMP_ALL(unit));
   7531 
   7532     max_index = soc_mem_index_max(unit, EGR_GPP_ATTRIBUTESm);
   7533 
   7534     PBMP_ITER(all_pbmp, port) {
   7535         if (max_index < (base_index + port)) {
   7536             continue;
   7537         }
   7538         SOC_IF_ERROR_RETURN(
   7539             soc_mem_field32_modify(unit, EGR_GPP_ATTRIBUTESm, (base_index + port),
   7540                                    EGR_LPORT_PROFILE_IDXf, port + 1));
   7541     }
   7542     return SOC_E_NONE;
   7543 
   7544 }
   7545 #endif
   7546 
   7547 /*
   7548  * Function:
   7549  *      _src_mod_base_index_bk_init
   7550  * Purpose:
   7551  *      Allocate and initialize data structures related to source modid base
   7552  *      indexing.
   7553  * Parameters:
   7554  *      unit - (IN)SOC unit number. 
   7555  * Returns:
   7556  *      BCM_X_XXX
   7557  */
   7558 int
   7559 bcmi_esw_src_modid_base_index_bk_init(int unit)
   7560 {
   7561     int src_mod_port_tbl_size, i;
   7562     soc_info_t *si=&SOC_INFO(unit);
   7563 #if defined BCM_TRIDENT2PLUS_SUPPORT
   7564     int entry_size = 0;
   7565     void *default_entry = NULL;
   7566 #endif /* BCM_TRIDENT2PLUS_SUPPORT */
   7567 
   7568     /* free memory space that is allocated before executing cmd rc */
   7569     _src_modid_base_index_bk_detach(unit);
   7570     
   7571     if (src_modid_base_index_bk[unit] == NULL) {
   7572         src_modid_base_index_bk[unit] = 
   7573             sal_alloc(sizeof(src_modid_base_index_bookkeeping_t),
   7574                     "src_modid_base_index_bk");
   7575         if (src_modid_base_index_bk[unit] == NULL) {
   7576             return BCM_E_MEMORY;
   7577         }
   7578     }
   7579     sal_memset(src_modid_base_index_bk[unit], 0,
   7580             sizeof(src_modid_base_index_bookkeeping_t));
   7581 
   7582     src_modid_base_index_bk[unit]->num_ports =
   7583         sal_alloc(sizeof(uint16) * (SOC_MODID_MAX(unit) + 1),
   7584                 "src_moid_base_index_bk num_ports array");
   7585     if (src_modid_base_index_bk[unit]->num_ports == NULL) {
   7586         _src_modid_base_index_bk_detach(unit);
   7587         return BCM_E_MEMORY;
   7588     }
   7589     sal_memset(src_modid_base_index_bk[unit]->num_ports, 0,
   7590             sizeof(uint16) * (SOC_MODID_MAX(unit) + 1));
   7591 
   7592     src_mod_port_tbl_size = soc_mem_index_count(unit, src_mod_port_mems[0]);
   7593     src_modid_base_index_bk[unit]->src_mod_port_table_bitmap = 
   7594         sal_alloc(SHR_BITALLOCSIZE(src_mod_port_tbl_size),
   7595                 "src_mod_port_table_bitmap");
   7596     if (src_modid_base_index_bk[unit]->src_mod_port_table_bitmap == NULL) {
   7597         _src_modid_base_index_bk_detach(unit);
   7598         return BCM_E_MEMORY;
   7599     }
   7600     sal_memset(src_modid_base_index_bk[unit]->src_mod_port_table_bitmap, 0,
   7601             SHR_BITALLOCSIZE(src_mod_port_tbl_size));
   7602 
   7603     if(si->num_coe_modules != 0) {
   7604 
   7605         /* Intialize the CoE module Id list */
   7606         src_modid_base_index_bk[unit]->coe_module_id_list =
   7607             sal_alloc(sizeof(int) * si->num_coe_modules,
   7608                     "src_moid_base_index_bk coe_module_id_list array");
   7609         if (src_modid_base_index_bk[unit]->coe_module_id_list == NULL) {
   7610             _src_modid_base_index_bk_detach(unit);
   7611             return BCM_E_MEMORY;
   7612         }
   7613 
   7614         for (i=0; i < si->num_coe_modules; i++) {
   7615             src_modid_base_index_bk[unit]->coe_module_id_list[i] = BCM_MODID_INVALID;
   7616         }
   7617     }
   7618 
   7619 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   7620     /* Intialize the module Id type list */
   7621     if (soc_feature(unit, soc_feature_multi_next_hops_on_port)) {
   7622         src_modid_base_index_bk[unit]->module_id_type_list =
   7623             sal_alloc(sizeof(int) * si->num_modules,
   7624                     "src_moid_base_index_bk module_id_type_list array");
   7625         if (src_modid_base_index_bk[unit]->module_id_type_list == NULL) {
   7626             _src_modid_base_index_bk_detach(unit);
   7627             return BCM_E_MEMORY;
   7628         }
   7629 
   7630         for (i=0; i < si->num_modules; i++) {
   7631             src_modid_base_index_bk[unit]->module_id_type_list[i] = 0;
   7632         }
   7633 
   7634         src_modid_base_index_bk[unit]->multi_nexthop_module_id_list =
   7635             sal_alloc(sizeof(int) * si->num_modules,
   7636                     "src_moid_base_index_bk multi_nexthop_module_id_list array");
   7637         if (src_modid_base_index_bk[unit]->multi_nexthop_module_id_list == NULL) {
   7638             _src_modid_base_index_bk_detach(unit);
   7639             return BCM_E_MEMORY;
   7640         }
   7641 
   7642         for (i=0; i < si->num_modules; i++) {
   7643             src_modid_base_index_bk[unit]->multi_nexthop_module_id_list[i] = BCM_MODID_INVALID;
   7644         }
   7645     }
   7646 #endif
   7647 
   7648 #if defined BCM_TRIDENT2PLUS_SUPPORT
   7649     if (SOC_IS_TD2P_TT2P(unit) || SOC_IS_APACHE(unit) || SOC_IS_TRIDENT3X(unit)) {
   7650         /* For TD2P/Apache, all module IDs initially has to share the same
   7651          * region in source mod table but it should not start with 0 as
   7652          * when local MOD ID is configured it will also share the same range
   7653          * and cause issues in HG packet processing. One way of handling it
   7654          * is allowing the local MOD ID to get base idx past the default
   7655          * range (i.e. after range of 0 to SOC_PORT_ADDR_MAX-1), but other
   7656          * modules expect the base index of local MOD ID to be 0 especially
   7657          * if doing upgrade from previous version of SDK code. Furthermore if
   7658          * CoE subport feature exists then it would need first 618 entries
   7659          * (331 for Apache) of source mod por table to support 106 logical ports
   7660          * (75 for Apache) + 512 subports (256 for Apache), hence the local
   7661          * MOD ID cannot be assigned base index past the SOC_PORT_ADDR_MAX-1
   7662          * range. Hence to allow local MOD ID to get base index of 0 and
   7663          * also to overcome HG packet processing issue, instead of blocking
   7664          * range 0 to SOC_PORT_ADDR_MAX-1 for all module IDs to begin with
   7665          * we ought to block SOC_PORT_ADDR_MAX entries from the end of the table
   7666          */
   7667          src_modid_base_index_bk[unit]->default_base_idx =
   7668                      soc_mem_index_count(unit, src_mod_port_mems[0]) -
   7669                                             (SOC_PORT_ADDR_MAX(unit) + 1);
   7670     } else
   7671 #endif /* BCM_TRIDENT2PLUS_SUPPORT */
   7672     {
   7673         /* Initialize all MODBASE tables such that all module IDs initially
   7674          * share the same region in source mod port tables, from entry 0 to
   7675          * entry SOC_PORT_ADDR_MAX. A module ID will be allocated its own
   7676          * region in source mod port tables as needed.
   7677          */
   7678         src_modid_base_index_bk[unit]->default_base_idx = 0;
   7679     }
   7680 
   7681     if (!SOC_WARM_BOOT(unit)) {
   7682         if(SOC_IS_KATANA(unit)) {
   7683             if(soc_mem_is_valid(unit, SOURCE_TRUNK_MAP_MODBASEm)) {
   7684                 SOC_IF_ERROR_RETURN(soc_mem_clear(unit, SOURCE_TRUNK_MAP_MODBASEm,
   7685                                                   MEM_BLOCK_ALL, 0));
   7686             }
   7687         }
   7688 #if defined BCM_TRIDENT2PLUS_SUPPORT
   7689         else if (SOC_IS_TD2P_TT2P(unit) || SOC_IS_APACHE(unit) || SOC_IS_TRIDENT3X(unit)) {
   7690 
   7691             for (i = 0; i < COUNTOF(src_modbase_mems); i++) {
   7692                 if(soc_mem_is_valid(unit, src_modbase_mems[i])) {
   7693                     entry_size = WORDS2BYTES(
   7694                         soc_mem_entry_words(unit, src_modbase_mems[i]));
   7695                     default_entry =
   7696                         soc_cm_salloc(unit, entry_size, "modbase table entry");
   7697 
   7698                     if (default_entry == NULL) {
   7699                         return BCM_E_MEMORY;
   7700                     }
   7701 
   7702                     sal_memset(default_entry, 0x0, entry_size);
   7703                     sal_memcpy(default_entry,
   7704                                 soc_mem_entry_null(unit, src_modbase_mems[i]),
   7705                                 soc_mem_entry_bytes(unit, src_modbase_mems[i]));
   7706 
   7707                     soc_mem_field_set(unit,
   7708                        src_modbase_mems[i],
   7709                        (uint32 *) default_entry,
   7710                        (src_modbase_mems[i]==MODID_BASE_PTRm)?MODID_BASEf:BASEf,
   7711                        &src_modid_base_index_bk[unit]->default_base_idx);
   7712 
   7713                     SOC_IF_ERROR_CLEAN_RETURN(
   7714                         soc_mem_fill(unit,
   7715                             src_modbase_mems[i], MEM_BLOCK_ALL, default_entry),
   7716                         soc_cm_sfree(unit, default_entry));
   7717 
   7718                     soc_cm_sfree(unit, default_entry);
   7719                     default_entry = NULL;
   7720 #if defined BCM_MONTEREY_SUPPORT
   7721                     if (SOC_IS_MONTEREY(unit) &&
   7722                         soc_feature(unit, soc_feature_xflow_macsec) &&
   7723                         (src_modbase_mems[i] == EGR_GPP_ATTRIBUTES_MODBASEm)) {
   7724                         SOC_IF_ERROR_RETURN(
   7725                             soc_egr_gpp_attribute_set(unit,
   7726                              src_modid_base_index_bk[unit]->default_base_idx));
   7727                     }
   7728 #endif
   7729                 }
   7730             }
   7731         }
   7732 #endif /* BCM_TRIDENT2PLUS_SUPPORT */
   7733         else {
   7734             for (i = 0; i < COUNTOF(src_modbase_mems); i++) {
   7735                 if(soc_mem_is_valid(unit, src_modbase_mems[i])) {
   7736                     SOC_IF_ERROR_RETURN(soc_mem_clear(unit, src_modbase_mems[i],
   7737                                 MEM_BLOCK_ALL, 0));
   7738                 }
   7739             }
   7740         }
   7741     }
   7742 
   7743 #if defined BCM_TRIDENT2PLUS_SUPPORT
   7744     if (SOC_IS_TD2P_TT2P(unit)) {
   7745          /* Reserve the range of entries in the port bitmap
   7746           * First range is for its own logical ports and the
   7747           * second range is for ports of non-configured MODs
   7748           */
   7749         _BCM_SRC_MOD_PORT_TABLE_USED_SET_RANGE(unit,0, BCM_STK_TD2P_NUM_LPORTS);
   7750         _BCM_SRC_MOD_PORT_TABLE_USED_SET_RANGE(unit,
   7751             src_modid_base_index_bk[unit]->default_base_idx,
   7752             SOC_PORT_ADDR_MAX(unit) + 1);
   7753     } else
   7754 #endif /* BCM_TRIDENT2PLUS_SUPPORT */
   7755 #if defined BCM_TRIDENT3_SUPPORT
   7756     if (SOC_IS_TRIDENT3X(unit)) {
   7757         /* Reserve the range of entries in the port bitmap
   7758          * First range is for its own logical ports and the
   7759          * second range is for ports of non-configured MODs
   7760          */
   7761         if (SOC_IS_TRIDENT3(unit)) {
   7762             _BCM_SRC_MOD_PORT_TABLE_USED_SET_RANGE(unit,0,
   7763                     TRIDENT3_DEV_PORTS_PER_DEV);
   7764         }
   7765 #if defined(BCM_MAVERICK2_SUPPORT)
   7766         if (SOC_IS_MAVERICK2(unit)) {
   7767             _BCM_SRC_MOD_PORT_TABLE_USED_SET_RANGE(unit,0,
   7768                     MAVERICK2_DEV_PORTS_PER_DEV);
   7769         }
   7770 #endif
   7771 #if defined(BCM_HELIX5_SUPPORT)
   7772         if (SOC_IS_HELIX5(unit)) {
   7773             _BCM_SRC_MOD_PORT_TABLE_USED_SET_RANGE(unit,0,
   7774                     HELIX5_DEV_PORTS_PER_DEV);
   7775         }
   7776 #endif
   7777         _BCM_SRC_MOD_PORT_TABLE_USED_SET_RANGE(unit,
   7778             src_modid_base_index_bk[unit]->default_base_idx,
   7779             SOC_PORT_ADDR_MAX(unit) + 1);
   7780     } else
   7781 #endif /* BCM_TRIDENT3_SUPPORT */
   7782 #if defined BCM_MONTEREY_SUPPORT
   7783     if (SOC_IS_MONTEREY(unit)) {
   7784          /* Reserve the range of entries in the port bitmap
   7785           * First range is for its own logical ports and the
   7786           * second range is for ports of non-configured MODs
   7787           */
   7788         _BCM_SRC_MOD_PORT_TABLE_USED_SET_RANGE(unit,0, BCM_STK_MONTEREY_NUM_LPORTS);
   7789         _BCM_SRC_MOD_PORT_TABLE_USED_SET_RANGE(unit,
   7790             src_modid_base_index_bk[unit]->default_base_idx,
   7791             SOC_PORT_ADDR_MAX(unit) + 1);
   7792     } else
   7793 #endif /* BCM_MONTEREY_SUPPORT */
   7794 #if defined BCM_APACHE_SUPPORT
   7795     if (SOC_IS_APACHE(unit)) {
   7796          /* Reserve the range of entries in the port bitmap
   7797           * First range is for its own logical ports and the
   7798           * second range is for ports of non-configured MODs
   7799           */
   7800         _BCM_SRC_MOD_PORT_TABLE_USED_SET_RANGE(unit,0, BCM_STK_APACHE_NUM_LPORTS);
   7801         _BCM_SRC_MOD_PORT_TABLE_USED_SET_RANGE(unit,
   7802             src_modid_base_index_bk[unit]->default_base_idx,
   7803             SOC_PORT_ADDR_MAX(unit) + 1);
   7804     } else
   7805 #endif /* BCM_APACHE_SUPPORT */
   7806     {
   7807         _BCM_SRC_MOD_PORT_TABLE_USED_SET_RANGE(unit, 0,
   7808             SOC_PORT_ADDR_MAX(unit) + 1);
   7809     }
   7810     if (SOC_IS_KATANA2(unit)) {
   7811         if ((soc_feature(unit, soc_feature_linkphy_coe) &&
   7812              SOC_INFO(unit).linkphy_enabled) ||
   7813             (soc_feature(unit, soc_feature_subtag_coe) &&
   7814              SOC_INFO(unit).subtag_enabled)) {
   7815             _BCM_SRC_MOD_PORT_TABLE_USED_SET_RANGE(unit,
   7816                 SOC_PORT_ADDR_MAX(unit) + 1, SOC_PORT_ADDR_MAX(unit) + 1);
   7817         }
   7818     }
   7819     return BCM_E_NONE;
   7820 }
   7821 
   7822 /*
   7823  * Function:
   7824  *      _src_modid_base_index_bk_detach
   7825  * Purpose:
   7826  *      Deallocate data structures related to source modid base indexing.
   7827  * Parameters:
   7828  *      unit - (IN)SOC unit number. 
   7829  * Returns:
   7830  *      None
   7831  */
   7832 STATIC void
   7833 _src_modid_base_index_bk_detach(int unit) 
   7834 {
   7835     if (src_modid_base_index_bk[unit]) {
   7836         if (src_modid_base_index_bk[unit]->num_ports) {
   7837             sal_free(src_modid_base_index_bk[unit]->num_ports);
   7838             src_modid_base_index_bk[unit]->num_ports = NULL;
   7839         }
   7840         if (src_modid_base_index_bk[unit]->src_mod_port_table_bitmap) {
   7841             sal_free(src_modid_base_index_bk[unit]->src_mod_port_table_bitmap);
   7842             src_modid_base_index_bk[unit]->src_mod_port_table_bitmap = NULL;
   7843         }
   7844         sal_free(src_modid_base_index_bk[unit]);
   7845         src_modid_base_index_bk[unit] = NULL;
   7846 
   7847     }
   7848 }
   7849 
   7850 /*
   7851  * Function:
   7852  *      _src_modid_base_index_alloc
   7853  * Purpose:
   7854  *      Allocate a source modid base index.
   7855  * Parameters:
   7856  *      unit   - (IN) SOC unit number. 
   7857  *      modid  - (IN) Source Module ID.
   7858  *      nports - (IN) Number of ports on the given module.
   7859  *      is_local_modid - (IN) 11 if allocation is needed for local module.
   7860  *      base_index - (OUT) Base index.
   7861  * Returns:
   7862  *      BCM_E_xxx
   7863  */
   7864 STATIC int
   7865 _src_modid_base_index_alloc(
   7866         int unit,
   7867         bcm_module_t modid,
   7868         int nports,
   7869         int is_local_modid,
   7870         int *base_index)
   7871 {
   7872     source_trunk_map_modbase_entry_t  stm_modbase_entry;
   7873     int        max_base_index;
   7874     int        i, j;
   7875     SHR_BITDCL occupied;
   7876     source_trunk_map_table_entry_t stm_entry;
   7877     egr_gpp_attributes_entry_t egr_gpp_entry;
   7878     int lport_default_index, egr_lport_default_index;
   7879     void *entry_null;
   7880 #ifdef BCM_TRIDENT2PLUS_SUPPORT
   7881     uint8 use_base_index_zero = 0;
   7882     bcm_module_t mod_idx = 0;
   7883     bcm_module_t my_modid = 0;
   7884     int          max_lports = BCM_STK_TD2P_NUM_LPORTS;
   7885 #else  /* BCM_TRIDENT2PLUS_SUPPORT */
   7886     COMPILER_REFERENCE(is_local_modid);
   7887 #endif /* BCM_TRIDENT2PLUS_SUPPORT */
   7888 
   7889     SOC_IF_ERROR_RETURN(
   7890         READ_SOURCE_TRUNK_MAP_MODBASEm(
   7891             unit, MEM_BLOCK_ANY, modid, &stm_modbase_entry));
   7892     *base_index =
   7893         soc_SOURCE_TRUNK_MAP_MODBASEm_field32_get(
   7894                     unit, &stm_modbase_entry, BASEf);
   7895 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   7896     if (SOC_IS_TD2P_TT2P(unit) || SOC_IS_APACHE(unit) || SOC_IS_TRIDENT3X(unit)) {
   7897         /* TD2P SKUs can have max 106 logical ports support.
   7898          * Apache SKUs can have max 75 logical ports support.
   7899          */
   7900 #if defined(BCM_APACHE_SUPPORT)
   7901         /* If Apache, override the max lports value, it is set to
   7902            TD2P lport max to start with */
   7903         if (SOC_IS_APACHE(unit)) {
   7904             max_lports = BCM_STK_APACHE_NUM_LPORTS;
   7905         }
   7906 #endif
   7907 #if defined(BCM_MONTEREY_SUPPORT)
   7908         if (SOC_IS_MONTEREY(unit)) {
   7909             max_lports = BCM_STK_MONTEREY_NUM_LPORTS;
   7910         }
   7911 #endif
   7912 #if defined(BCM_TRIDENT3_SUPPORT)
   7913         /* If Trident3, override the max lports value, it is set to
   7914            TD3 lport max to start with */
   7915         if (SOC_IS_TRIDENT3X(unit)) {
   7916             if (SOC_IS_TRIDENT3(unit)) {
   7917                 max_lports = TRIDENT3_DEV_PORTS_PER_DEV;
   7918             }
   7919 #if defined(BCM_MAVERICK2_SUPPORT)
   7920             if (SOC_IS_MAVERICK2(unit)) {
   7921                 max_lports = MAVERICK2_DEV_PORTS_PER_DEV;
   7922             }
   7923 #endif
   7924 #if defined(BCM_HELIX5_SUPPORT)
   7925             if (SOC_IS_HELIX5(unit)) {
   7926                 max_lports = HELIX5_DEV_PORTS_PER_DEV;
   7927             }
   7928 #endif
   7929         }
   7930 #endif
   7931         if (is_local_modid && nports > max_lports) {
   7932             return BCM_E_PARAM;
   7933         }
   7934 
   7935         BCM_IF_ERROR_RETURN(
   7936             bcm_esw_stk_my_modid_get(unit, &my_modid));
   7937 
   7938         if (modid == my_modid || is_local_modid) {
   7939             use_base_index_zero = 1;
   7940             if(0 == *base_index) {
   7941                 return BCM_E_NONE;
   7942             }
   7943             *base_index = 0;
   7944         }
   7945     }
   7946 
   7947     if (!use_base_index_zero)
   7948 #endif /* BCM_TRIDENT2PLUS_SUPPORT */
   7949     {
   7950         if (*base_index != src_modid_base_index_bk[unit]->default_base_idx) {
   7951             return BCM_E_NONE;
   7952         }
   7953 
   7954         /* Find a contiguous region of source mod port tables that's large
   7955          * enough to hold nports entries.
   7956          */
   7957         max_base_index = soc_mem_index_count(unit, src_mod_port_mems[0]) - nports;
   7958         for (i = 0; i <= max_base_index; i++) {
   7959             /* Check if the contiguous region of source mod port tables from
   7960              * index i to (i + nports - 1) is free.
   7961              */
   7962             _BCM_SRC_MOD_PORT_TABLE_TEST_RANGE(unit, i, nports, occupied);
   7963             if (!occupied) {
   7964                 break;
   7965             }
   7966         }
   7967         if (i > max_base_index) {
   7968             /* A contiguous region of the desired size could not be found in
   7969              * source mod port tables.
   7970              */
   7971             return BCM_E_RESOURCE;
   7972         }
   7973         *base_index = i;
   7974     }
   7975 
   7976     if(SOC_IS_KATANA(unit)) {
   7977         SOC_IF_ERROR_RETURN
   7978             (soc_mem_field32_modify(unit, SOURCE_TRUNK_MAP_MODBASEm,
   7979                                     modid, BASEf, *base_index));
   7980     } else {
   7981         for (i = 0; i < COUNTOF(src_modbase_mems); i++) {
   7982             if(soc_mem_is_valid(unit, src_modbase_mems[i])) {
   7983 #ifdef BCM_TRIDENT2PLUS_SUPPORT
   7984                 if (src_modbase_mems[i] == MODID_BASE_PTRm) {
   7985                     mod_idx = modid % 64;  /* lower 6 bit */
   7986                     SOC_IF_ERROR_RETURN(soc_mem_field32_modify(unit,
   7987                         MODID_BASE_PTRm, mod_idx, MODID_BASEf, *base_index));
   7988                 } else 
   7989 #endif /* BCM_TRIDENT2PLUS_SUPPORT */                
   7990                 {
   7991                     SOC_IF_ERROR_RETURN(soc_mem_field32_modify(unit,
   7992                         src_modbase_mems[i], modid, BASEf, *base_index));
   7993                 }
   7994 #if defined BCM_MONTEREY_SUPPORT
   7995                 if (SOC_IS_MONTEREY(unit) &&
   7996                     soc_feature(unit, soc_feature_xflow_macsec) &&
   7997                     (src_modbase_mems[i] == EGR_GPP_ATTRIBUTES_MODBASEm)) {
   7998                     SOC_IF_ERROR_RETURN(
   7999                         soc_egr_gpp_attribute_set(unit,
   8000                                                   *base_index));
   8001                 }
   8002 #endif
   8003             }
   8004         }
   8005     }
   8006 
   8007 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   8008     if ((SOC_IS_TD2P_TT2P(unit) ||  SOC_IS_TRIDENT3X(unit) || SOC_IS_APACHE(unit)) && use_base_index_zero)
   8009     {
   8010         /* For TD2P/Apache platforms base index 0 is reserved for local MODID
   8011          * and hence we should not continue further and reset the relevant
   8012          * src_mod_port_mems entries to default values. This is because local
   8013          * MODID's configuration is done once at init time and we cannot afford
   8014          * to lose it, as it will not be configured back.
   8015          */
   8016         return BCM_E_NONE;
   8017     }
   8018 #endif /* BCM_TRIDENT2PLUS_SUPPORT */
   8019 
   8020     /* Set src_mod_port_table_bitmap */
   8021     _BCM_SRC_MOD_PORT_TABLE_USED_SET_RANGE(unit, *base_index, nports);
   8022 
   8023     /* Set STM LPORT profile index to use default LPORT entry */
   8024     lport_default_index = _bcm_trx_lport_tab_default_entry_index_get(unit);
   8025     sal_memcpy(&stm_entry,
   8026                soc_mem_entry_null(unit, SOURCE_TRUNK_MAP_TABLEm),
   8027                sizeof(stm_entry));
   8028     soc_SOURCE_TRUNK_MAP_TABLEm_field32_set(unit, &stm_entry,
   8029                                             LPORT_PROFILE_IDXf,
   8030                                             lport_default_index);
   8031 
   8032     if(soc_feature(unit, soc_feature_egr_lport_tab_profile)) {
   8033         /* Set Egress GPP LPORT profile index to use default LPORT entry */
   8034 
   8035         
   8036         egr_lport_default_index = 
   8037             _bcm_trx_egr_lport_tab_default_entry_index_get(unit);
   8038        
   8039         sal_memcpy(&egr_gpp_entry,
   8040                    soc_mem_entry_null(unit, EGR_GPP_ATTRIBUTESm),
   8041                    sizeof(egr_gpp_entry));
   8042         soc_EGR_GPP_ATTRIBUTESm_field32_set(unit, &egr_gpp_entry,
   8043                                                 EGR_LPORT_PROFILE_IDXf,
   8044                                                 egr_lport_default_index);
   8045     }
   8046 
   8047     /* Clear the newly allocated region in each src mod port table */
   8048     if(SOC_IS_KATANA(unit)) {
   8049         for (j = *base_index; j < (*base_index + nports); j++) {
   8050             SOC_IF_ERROR_RETURN(soc_mem_write(unit, SOURCE_TRUNK_MAP_TABLEm,
   8051                                               MEM_BLOCK_ALL, j,
   8052                                               &stm_entry));
   8053       }
   8054     } else {
   8055         for (i = 0; i < COUNTOF(src_mod_port_mems); i++) {
   8056             if(!soc_mem_is_valid(unit, src_mod_port_mems[i])) {
   8057                 continue;
   8058             }
   8059 
   8060             if (src_mod_port_mems[i] == SOURCE_TRUNK_MAP_TABLEm) {
   8061                 entry_null = &stm_entry;
   8062             } else if (soc_feature(unit, soc_feature_egr_lport_tab_profile)) {
   8063                 entry_null = &egr_gpp_entry;
   8064             } else {
   8065                 entry_null = soc_mem_entry_null(unit, src_mod_port_mems[i]);
   8066             }
   8067 
   8068             for (j = *base_index; j < (*base_index + nports); j++) {
   8069                 SOC_IF_ERROR_RETURN(soc_mem_write(unit, src_mod_port_mems[i],
   8070                                                   MEM_BLOCK_ALL, j,
   8071                                                   entry_null));
   8072             }
   8073         }
   8074     }
   8075 
   8076     return BCM_E_NONE;
   8077 }
   8078 
   8079 /*
   8080  * Function:
   8081  *      _src_modid_base_index_free
   8082  * Purpose:
   8083  *      Free a source modid base index.
   8084  * Parameters:
   8085  *      unit   - (IN) SOC unit number. 
   8086  *      modid  - (IN) Source Module ID.
   8087  *      nports - (IN) Number of ports on the given module.
   8088  * Returns:
   8089  *      BCM_E_xxx
   8090  */
   8091 STATIC int
   8092 _src_modid_base_index_free(
   8093         int unit,
   8094         bcm_module_t modid,
   8095         int nports)
   8096 {
   8097     source_trunk_map_modbase_entry_t stm_modbase_entry;
   8098     source_trunk_map_table_entry_t stm_entry;
   8099     int base_index;
   8100     int i, j;
   8101     void *entry_null;
   8102 #ifdef BCM_TRIDENT2PLUS_SUPPORT
   8103     bcm_module_t mod_idx = 0;
   8104     bcm_module_t my_modid = 0;
   8105     uint8 reuse_base_index_zero = 0;
   8106 #endif
   8107 
   8108     SOC_IF_ERROR_RETURN
   8109         (READ_SOURCE_TRUNK_MAP_MODBASEm(unit, MEM_BLOCK_ANY, modid,
   8110                                         &stm_modbase_entry));
   8111     base_index = soc_SOURCE_TRUNK_MAP_MODBASEm_field32_get(unit,
   8112             &stm_modbase_entry, BASEf);
   8113     if (base_index == src_modid_base_index_bk[unit]->default_base_idx) {
   8114         return BCM_E_NONE;
   8115     }
   8116 
   8117 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   8118     if (SOC_IS_TD2P_TT2P(unit) || SOC_IS_APACHE(unit) || SOC_IS_TRIDENT3X(unit)) {
   8119         BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_modid));
   8120 
   8121         if (modid == my_modid && 0 == base_index) {
   8122             reuse_base_index_zero = 1;
   8123         }
   8124     }
   8125 
   8126     if (!reuse_base_index_zero)
   8127 #endif /* BCM_TRIDENT2PLUS_SUPPORT */
   8128     {
   8129         /* Clear src mod port table bitmap */
   8130         _BCM_SRC_MOD_PORT_TABLE_USED_CLR_RANGE(unit, base_index, nports);
   8131 
   8132         sal_memcpy(&stm_entry,
   8133                    soc_mem_entry_null(unit, SOURCE_TRUNK_MAP_TABLEm),
   8134                    sizeof(stm_entry));
   8135         /* Clear the region to be freed in each src mod port table */
   8136         if(SOC_IS_KATANA(unit)) {
   8137             for (j = base_index; j < (base_index + nports); j++) {
   8138                 SOC_IF_ERROR_RETURN(
   8139                     soc_mem_write(unit, SOURCE_TRUNK_MAP_TABLEm,
   8140                                     MEM_BLOCK_ALL, j, &stm_entry));
   8141             }
   8142         } else {
   8143             for (i = 0; i < COUNTOF(src_mod_port_mems); i++) {
   8144                 if(!soc_mem_is_valid(unit, src_mod_port_mems[i])) {
   8145                     continue;
   8146                 }
   8147 
   8148                 if (src_mod_port_mems[i] == SOURCE_TRUNK_MAP_TABLEm) {
   8149                     entry_null = &stm_entry;
   8150                 } else {
   8151                     entry_null = soc_mem_entry_null(unit, src_mod_port_mems[i]);
   8152                 }
   8153 
   8154                 for (j = base_index; j < (base_index + nports); j++) {
   8155                     SOC_IF_ERROR_RETURN(
   8156                         soc_mem_write(unit, src_mod_port_mems[i],
   8157                                     MEM_BLOCK_ALL, j, entry_null));
   8158                 }
   8159             }
   8160         }
   8161     }
   8162 
   8163     if(SOC_IS_KATANA(unit)) {
   8164         SOC_IF_ERROR_RETURN
   8165             (soc_mem_field32_modify(unit, SOURCE_TRUNK_MAP_MODBASEm,
   8166                                     modid, BASEf, 0));
   8167     } else {
   8168         for (i = 0; i < COUNTOF(src_modbase_mems); i++) {
   8169             if(soc_mem_is_valid(unit, src_modbase_mems[i])) {
   8170 #ifdef BCM_TRIDENT2PLUS_SUPPORT
   8171                 if (src_modbase_mems[i] == MODID_BASE_PTRm) {
   8172                     mod_idx = modid % 64;  /* lower 6 bit */
   8173                     SOC_IF_ERROR_RETURN(
   8174                         soc_mem_field32_modify(
   8175                             unit, MODID_BASE_PTRm, mod_idx, MODID_BASEf,
   8176                             src_modid_base_index_bk[unit]->default_base_idx));
   8177                 } else
   8178 #endif /* BCM_TRIDENT2PLUS_SUPPORT */
   8179                 {
   8180                     SOC_IF_ERROR_RETURN(
   8181                         soc_mem_field32_modify(
   8182                             unit, src_modbase_mems[i], modid, BASEf,
   8183                             src_modid_base_index_bk[unit]->default_base_idx));
   8184                 }
   8185             }
   8186         }
   8187     }
   8188     return BCM_E_NONE;
   8189 }
   8190 
   8191 #endif /* BCM_TRIDENT_SUPPORT || BCM_HURRICANE3_SUPPORT */
   8192 
   8193 /*
   8194  * Function:
   8195  *      bcm_esw_stk_module_enable
   8196  * Purpose:
   8197  *      Enable or disable a module and specify its number of ports.
   8198  * Parameters:
   8199  *      unit   - (IN) SOC unit number. 
   8200  *      modid  - (IN) Module ID that is being enabled/disabled.
   8201  *      nports - (IN) Number of ports on the given module, 0 for no port
   8202  *                    status change, -1 for default number of ports.
   8203  *      enable - (IN) TRUE to enable, FALSE to disable.
   8204  * Returns:
   8205  *      BCM_E_xxx
   8206  */
   8207 int 
   8208 bcm_esw_stk_module_enable(
   8209     int unit, 
   8210     bcm_module_t modid, 
   8211     int nports, 
   8212     int enable)
   8213 {
   8214 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_HURRICANE3_SUPPORT)
   8215     if (soc_feature(unit, soc_feature_src_modid_base_index)) {
   8216 
   8217         bcm_module_t        mod_out;
   8218         bcm_port_t          port_out;
   8219         int                 is_local;
   8220         int                 old_nports;
   8221         int                 base_index;
   8222 
   8223         if (modid > SOC_MODID_MAX(unit)) {
   8224             return BCM_E_PARAM;
   8225         }
   8226 
   8227         if ((nports > (SOC_PORT_ADDR_MAX(unit) + 1)) || (nports < -1)) {
   8228             return BCM_E_PARAM;
   8229         }
   8230 
   8231         if (enable && (nports == 0)) {
   8232             return BCM_E_PARAM;
   8233         }
   8234 
   8235         BCM_IF_ERROR_RETURN
   8236             (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_SET,
   8237                                      modid, -1,
   8238                                      &mod_out, &port_out));
   8239         BCM_IF_ERROR_RETURN
   8240             (_bcm_esw_modid_is_local(unit, mod_out, &is_local));
   8241 
   8242         if (enable) {
   8243             if (is_local) {
   8244                 /* If local modid, use the base modid */
   8245                 mod_out = SOC_BASE_MODID(unit);
   8246             }
   8247 
   8248             old_nports = src_modid_base_index_bk[unit]->num_ports[mod_out];
   8249             if (old_nports > 0) {
   8250                 /* Already enabled */
   8251                 return BCM_E_EXISTS;
   8252             }
   8253 
   8254             if (nports == -1) {
   8255 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   8256                 if (is_local &&
   8257                     (SOC_IS_TD2P_TT2P(unit))) {
   8258                     /* In TD2P num of ports default to 106 for local MODID
   8259                      */
   8260                     nports = BCM_STK_TD2P_NUM_LPORTS;
   8261                 } else
   8262 #endif /* BCM_TRIDENT2PLUS_SUPPORT */
   8263 #if defined(BCM_MONTEREY_SUPPORT)
   8264                 if (is_local &&
   8265                     (SOC_IS_MONTEREY(unit))) {
   8266                     nports = BCM_STK_MONTEREY_NUM_LPORTS;
   8267                 } else
   8268 #endif /* BCM_MONTEREY_SUPPORT */
   8269 #if defined(BCM_APACHE_SUPPORT)
   8270                 if (is_local &&
   8271                     (SOC_IS_APACHE(unit))) {
   8272                     /* In Apache num of ports default to 75 for local MODID
   8273                      */
   8274                     nports = BCM_STK_APACHE_NUM_LPORTS;
   8275                 } else
   8276 #endif /* BCM_APACHE_SUPPORT */
   8277 #if defined(BCM_TRIDENT3_SUPPORT)
   8278                 if (is_local &&
   8279                     (SOC_IS_TRIDENT3X(unit))) {
   8280                     /* In trident3 num of ports default to max logical for local MODID
   8281                      */
   8282                     if (SOC_IS_TRIDENT3(unit)) {
   8283                         nports = TRIDENT3_DEV_PORTS_PER_DEV;
   8284                     }
   8285 #if defined(BCM_MAVERICK2_SUPPORT)
   8286                     if (SOC_IS_MAVERICK2(unit)) {
   8287                         nports = MAVERICK2_DEV_PORTS_PER_DEV;
   8288                     }
   8289 #endif
   8290 #if defined(BCM_HELIX5_SUPPORT)
   8291                     if (SOC_IS_HELIX5(unit)) {
   8292                         nports = HELIX5_DEV_PORTS_PER_DEV;
   8293                     }
   8294 #endif
   8295                 } else
   8296 #endif /* BCM_TRIDENT3_SUPPORT */
   8297                 {
   8298                     /* Number of ports default to SOC_PORT_ADDR_MAX + 1 */
   8299                     nports = SOC_PORT_ADDR_MAX(unit) + 1;
   8300                 }
   8301             }
   8302 
   8303             if (nports > 0) {
   8304                 BCM_IF_ERROR_RETURN
   8305                     (_src_modid_base_index_alloc(unit, mod_out, nports,
   8306                                                      is_local, &base_index));
   8307                 src_modid_base_index_bk[unit]->num_ports[mod_out] = nports;
   8308             }
   8309         } else {
   8310             if (is_local) {
   8311                 /* Cannot disable local module */
   8312                 return BCM_E_PARAM;
   8313             }
   8314 
   8315             old_nports = src_modid_base_index_bk[unit]->num_ports[mod_out];
   8316             if (old_nports == 0) {
   8317                 /* Not enabled */
   8318                 return BCM_E_DISABLED;
   8319             }
   8320             BCM_IF_ERROR_RETURN
   8321                 (_src_modid_base_index_free(unit, mod_out, old_nports));
   8322             src_modid_base_index_bk[unit]->num_ports[mod_out] = 0;
   8323         }
   8324 
   8325         return BCM_E_NONE;
   8326     } 
   8327 #endif /* BCM_TRIDENT_SUPPORT || BCM_HURRICANE3_SUPPORT */
   8328 
   8329     return BCM_E_UNAVAIL;
   8330 }
   8331 
   8332 /*
   8333  * Function:
   8334  *      _bcm_esw_src_modid_base_index_get
   8335  * Purpose:
   8336  *      Allocate a source modid base index.
   8337  * Parameters:
   8338  *      unit   - (IN) SOC unit number. 
   8339  *      modid  - (IN) Source Module ID.
   8340  *      is_local  - (IN) 1 if local Module ID.
   8341  *      base_index - (OUT) Source module base index.
   8342  * Returns:
   8343  *      BCM_E_xxx
   8344  */
   8345 int
   8346 _bcm_esw_src_modid_base_index_get(
   8347         int unit,
   8348         bcm_module_t modid,
   8349         int is_local,
   8350         int *base_index)
   8351 {
   8352 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_HURRICANE3_SUPPORT)
   8353     if (soc_feature(unit, soc_feature_src_modid_base_index)) {
   8354 
   8355         source_trunk_map_modbase_entry_t  stm_modbase_entry;
   8356         int nports;
   8357 
   8358         SOC_IF_ERROR_RETURN
   8359             (READ_SOURCE_TRUNK_MAP_MODBASEm(unit, MEM_BLOCK_ANY, modid,
   8360                                             &stm_modbase_entry));
   8361         *base_index = soc_SOURCE_TRUNK_MAP_MODBASEm_field32_get(unit,
   8362                 &stm_modbase_entry, BASEf);
   8363         if (*base_index != src_modid_base_index_bk[unit]->default_base_idx) {
   8364             /* Source module base index already allocated */
   8365             return BCM_E_NONE;
   8366         }
   8367 
   8368         if (NULL == src_modid_base_index_bk[unit]) {
   8369             return BCM_E_INIT;
   8370         }
   8371 
   8372         /* Allocate a source module base index */
   8373         nports = src_modid_base_index_bk[unit]->num_ports[modid];
   8374         if (nports == 0) {
   8375 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   8376             if (is_local && (SOC_IS_TD2P_TT2P(unit))) {
   8377                 /* In TD2P num of ports default to 106 for local MODID */
   8378                 nports = BCM_STK_TD2P_NUM_LPORTS;
   8379             } else
   8380 #endif /* BCM_TRIDENT2PLUS_SUPPORT */
   8381 #if defined(BCM_MONTEREY_SUPPORT)
   8382             if (is_local && SOC_IS_MONTEREY(unit)) {
   8383                 /* In Apache num of ports default to 75 for local MODID */
   8384                 nports = BCM_STK_MONTEREY_NUM_LPORTS;
   8385             } else
   8386 #endif /* BCM_MONTEREY_SUPPORT */
   8387 #if defined(BCM_APACHE_SUPPORT)
   8388             if (is_local && SOC_IS_APACHE(unit)) {
   8389                 /* In Apache num of ports default to 75 for local MODID */
   8390                 nports = BCM_STK_APACHE_NUM_LPORTS;
   8391             } else
   8392 #endif /* BCM_APACHE_SUPPORT */
   8393 #if defined(BCM_TRIDENT3_SUPPORT)
   8394             if (is_local && SOC_IS_TRIDENT3X(unit)) {
   8395                 /* In Apache num of ports default to max logical ports for local MODID */
   8396                 if (SOC_IS_TRIDENT3(unit)) {
   8397                     nports = TRIDENT3_DEV_PORTS_PER_DEV;
   8398                 }
   8399 #if defined(BCM_MAVERICK2_SUPPORT)
   8400                 if (SOC_IS_MAVERICK2(unit)) {
   8401                     nports = MAVERICK2_DEV_PORTS_PER_DEV;
   8402                 }
   8403 #endif
   8404 #if defined(BCM_HELIX5_SUPPORT)
   8405                 if (SOC_IS_HELIX5(unit)) {
   8406                     nports = HELIX5_DEV_PORTS_PER_DEV;
   8407                 }
   8408 #endif
   8409             } else
   8410 #endif /* BCM_TRIDENT3_SUPPORT */
   8411             {
   8412                 /* Assume (SOC_PORT_ADDR_MAX + 1) if nports is not initialized
   8413                 * using bcm_esw_stk_module_enable API
   8414                 */
   8415                 nports = SOC_PORT_ADDR_MAX(unit) + 1;
   8416             }
   8417         }
   8418         BCM_IF_ERROR_RETURN
   8419             (_src_modid_base_index_alloc(
   8420                 unit, modid, nports, is_local, base_index));
   8421         src_modid_base_index_bk[unit]->num_ports[modid] = nports;
   8422 
   8423         return BCM_E_NONE;
   8424     }
   8425 #endif /* BCM_TRIDENT_SUPPORT || BCM_HURRICANE3_SUPPORT */
   8426 
   8427     return BCM_E_UNAVAIL;
   8428 }
   8429 
   8430 /*
   8431  * Function:
   8432  *      _bcm_esw_src_modid_port_get
   8433  * Purpose:
   8434  *      get modid and port number from STM entry index.
   8435  * Parameters:
   8436  *      unit   - (IN) SOC unit number. 
   8437  *      stm_inx  - (IN) Source Trunk Map entry index.
   8438  *      modid  - (OUT) Source Module ID.
   8439  *      port - (OUT) Port Number.
   8440  * Returns:
   8441  *      BCM_E_xxx
   8442  */
   8443 int
   8444 _bcm_esw_src_modid_port_get(
   8445         int unit,
   8446         int stm_inx,
   8447         bcm_module_t *modid,
   8448         int *port)
   8449 {
   8450 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_HURRICANE3_SUPPORT)
   8451     if (soc_feature(unit, soc_feature_src_modid_base_index)) {
   8452         int i;
   8453         int rv;
   8454         int base_inx;
   8455         source_trunk_map_modbase_entry_t  stm_modbase_entry;
   8456 
   8457         /* The SOURCE_TRUNK_MAP entry range pointed by the base index
   8458          * for each modid is not overlapped.
   8459          */
   8460         for (i = 0; i <= SOC_MODID_MAX(unit) ; i++) {
   8461 
   8462             /* only read the valid entry */
   8463             if (src_modid_base_index_bk[unit]->num_ports[i]) {
   8464                 rv = READ_SOURCE_TRUNK_MAP_MODBASEm(unit, MEM_BLOCK_ANY, i,
   8465                         &stm_modbase_entry);
   8466                 if (SOC_FAILURE(rv)) {
   8467                     continue;
   8468                 }
   8469                 base_inx = soc_SOURCE_TRUNK_MAP_MODBASEm_field32_get(unit,
   8470                               &stm_modbase_entry, BASEf);
   8471                 /* check if the stm_inx falls in the range */
   8472                 if ((stm_inx >= base_inx) && (stm_inx < (base_inx + 
   8473                         src_modid_base_index_bk[unit]->num_ports[i]))) {
   8474                     /* found the modid */
   8475                     *modid = i;
   8476                     *port = stm_inx - base_inx;
   8477                     return BCM_E_NONE;
   8478                 }
   8479             }
   8480         }
   8481         return BCM_E_PARAM; 
   8482     }
   8483 #endif /* BCM_TRIDENT_SUPPORT || BCM_HURRICANE3_SUPPORT */
   8484 
   8485 #ifdef BCM_TRX_SUPPORT
   8486     if (soc_feature(unit, soc_feature_trunk_group_overlay)) {
   8487         *modid = stm_inx / (SOC_PORT_ADDR_MAX(unit) + 1);
   8488         *port  = stm_inx % (SOC_PORT_ADDR_MAX(unit) + 1);
   8489         return BCM_E_NONE;
   8490     } 
   8491 #endif
   8492     return BCM_E_UNAVAIL;
   8493 }
   8494 
   8495 /*
   8496  * Function:
   8497  *      _bcm_esw_src_mod_port_table_index_get
   8498  * Purpose:
   8499  *      Derive index to source mod port tables.
   8500  * Parameters:
   8501  *      unit  - (IN) SOC unit number. 
   8502  *      modid - (IN) Source Module ID.
   8503  *      port  - (IN) Source Port ID.
   8504  *      index - (OUT) Source mod port table index.
   8505  * Returns:
   8506  *      BCM_E_xxx
   8507  */
   8508 int
   8509 _bcm_esw_src_mod_port_table_index_get(
   8510         int unit,
   8511         bcm_module_t modid,
   8512         bcm_port_t port,
   8513         int *index)
   8514 {
   8515 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_HURRICANE3_SUPPORT)
   8516     if (soc_feature(unit, soc_feature_src_modid_base_index)) {
   8517         int is_local;
   8518         bcm_module_t mod_out;
   8519 
   8520         BCM_IF_ERROR_RETURN
   8521             (_bcm_esw_stk_modmap_map(
   8522                 unit, BCM_STK_MODMAP_SET, modid, -1, &mod_out, NULL));
   8523         BCM_IF_ERROR_RETURN
   8524             (_bcm_esw_modid_is_local(unit, mod_out, &is_local));
   8525 
   8526         BCM_IF_ERROR_RETURN
   8527             (_bcm_esw_src_modid_base_index_get(unit, modid, is_local, index));
   8528         *index += port;
   8529     } else
   8530 #endif /* BCM_TRIDENT_SUPPORT || BCM_HURRICANE3_SUPPORT */
   8531     if (SOC_IS_ENDURO(unit)) {
   8532         *index = (modid * 64) + port;
   8533     } else 
   8534 #ifdef BCM_TRX_SUPPORT
   8535     if (soc_feature(unit, soc_feature_trunk_group_overlay)) {
   8536         *index = (modid * (SOC_PORT_ADDR_MAX(unit) + 1)) + port;
   8537     } else
   8538 #endif
   8539     {
   8540         *index = (modid << SOC_TRUNK_BIT_POS(unit)) + port;
   8541     }
   8542 
   8543     return BCM_E_NONE;
   8544 }
   8545 
   8546 /*
   8547  * Function:
   8548  *      _bcm_esw_src_mod_port_table_index_get_from_port
   8549  * Purpose:
   8550  *      Derive index to source mod port tables.
   8551  * Parameters:
   8552  *      unit  - (IN) SOC unit number.
   8553  *      port  - (IN) Source Port ID.
   8554  *      index - (OUT) Source mod port table index.
   8555  *
   8556  *  port only accept:
   8557  *                   GPORT Subport
   8558  *                   Pysical port
   8559  * Returns:
   8560  *      BCM_E_xxx
   8561  */
   8562 int
   8563 _bcm_esw_src_mod_port_table_index_get_from_port(
   8564         int unit,
   8565         bcm_port_t port,
   8566         int *index)
   8567 {
   8568     int mod_out;
   8569 #if defined BCM_HGPROXY_COE_SUPPORT
   8570     bcm_trunk_t trunk_id;
   8571     bcm_port_t port_out;
   8572     int id;
   8573 #endif
   8574 
   8575 #if defined BCM_HGPROXY_COE_SUPPORT
   8576     if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) &&
   8577         BCM_GPORT_IS_SET(port) &&
   8578         _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port)) {
   8579         BCM_IF_ERROR_RETURN(
   8580             _bcm_esw_gport_resolve(unit, port, &mod_out, &port_out,
   8581                                    &trunk_id, &id));
   8582         BCM_IF_ERROR_RETURN(
   8583             _bcm_esw_src_mod_port_table_index_get(unit, mod_out,
   8584                                                   port_out, index));
   8585     } else
   8586 #endif
   8587 
   8588     {
   8589         /* Get module id for unit. */
   8590         BCM_IF_ERROR_RETURN(
   8591             bcm_esw_stk_my_modid_get(unit, &mod_out));
   8592         BCM_IF_ERROR_RETURN(
   8593             _bcm_esw_src_mod_port_table_index_get(unit, mod_out,
   8594                                                   port, index));
   8595     }
   8596 
   8597     return BCM_E_NONE;
   8598 }
   8599 
   8600 
   8601 #if defined(BCM_KATANA2_SUPPORT)
   8602 
   8603 /*
   8604  * Function:
   8605  *      _bcm_stk_index_based_cfg_modport_count
   8606  * Purpose:
   8607  *      Given a index, compute modports already created prior
   8608  *      to this mod_index. This is called when creating modports
   8609  *      to check if there is room to create additional modports.
   8610  * Parameters:
   8611  *      unit            - (IN) unit number.
   8612  *      mod_index       - (IN) Module index to use for computation
   8613  *      modport_count   - (OUT) Number of modports created prior to
   8614  *                              this mod_index
   8615  * Returns:
   8616  *      BCM_E_XXX
   8617  */
   8618 
   8619 int
   8620 _bcm_stk_index_based_cfg_modport_count(int unit, int mod_index,
   8621                                       uint8 *modport_count)
   8622 {
   8623     int my_modid_list[KT2_MAX_MODIDS_PER_TRANSLATION_TABLE] = {0};
   8624     int my_modid_valid[KT2_MAX_MODIDS_PER_TRANSLATION_TABLE] = {0};
   8625     int my_modport_base_ptr[KT2_MAX_MODIDS_PER_TRANSLATION_TABLE] = {0};
   8626     int modid = 0;
   8627 
   8628     if(modport_count == NULL) {
   8629         return BCM_E_PARAM;
   8630     }
   8631 
   8632     /* Sanity check the 'mod_index' value, first index (_BCMI_KATANA2_MODULE_1)
   8633        reserved for front panel ports */
   8634     if((mod_index < _BCMI_KATANA2_MODULE_2) ||
   8635        (mod_index > KT2_MAX_MODIDS_PER_TRANSLATION_TABLE)) {
   8636         return BCM_E_PARAM;
   8637     }
   8638 
   8639     BCM_IF_ERROR_RETURN(
   8640         bcm_kt2_modid_get_all(unit, my_modid_list, my_modid_valid,
   8641                               my_modport_base_ptr));
   8642 
   8643     /* Depending on the mod_index, compute the previous allocation of
   8644        modports, fall through to get full list */
   8645     switch(mod_index) {
   8646         case _BCMI_KATANA2_MODULE_4:
   8647             if(my_modid_valid[_BCMI_KATANA2_MODULE_3]) {
   8648                 modid = my_modid_list[_BCMI_KATANA2_MODULE_3];
   8649                 *modport_count +=
   8650                     src_modid_base_index_bk[unit]->num_ports[modid];
   8651             }
   8652         case _BCMI_KATANA2_MODULE_3:
   8653             if(my_modid_valid[_BCMI_KATANA2_MODULE_2]) {
   8654                 modid = my_modid_list[_BCMI_KATANA2_MODULE_2];
   8655                 *modport_count +=
   8656                     src_modid_base_index_bk[unit]->num_ports[modid];
   8657             }
   8658          break;
   8659         case _BCMI_KATANA2_MODULE_2:
   8660             /* This is the first Coe Module being created, just set the
   8661                modport_count to 0 */
   8662             *modport_count = 0;
   8663             break;
   8664         default:
   8665             *modport_count = 0;
   8666             return BCM_E_PARAM;
   8667     }
   8668 
   8669     return BCM_E_NONE;
   8670 }
   8671 
   8672 /*
   8673  * Function:
   8674  *      _bcm_stk_index_based_mod_cfg_check
   8675  * Purpose:
   8676  *      Given a index, determine if the subsequent modules are
   8677  *      created. This is called when deleting modports so
   8678  *      ordered deletion can be enforced. User has to essentially
   8679  *      delete latest added modules first.
   8680  *
   8681  * Parameters:
   8682  *      unit            - (IN) unit number.
   8683  *      mod_index       - (IN) Module index to use for computation
   8684  *      mod_cfg         - (OUT) True if subsequent mods created
   8685  *                              already
   8686  * Returns:
   8687  *      BCM_E_XXX
   8688  */
   8689 
   8690 int
   8691 _bcm_stk_index_based_mod_cfg_check(int unit, int mod_index,
   8692                                       uint8 *mod_cfg)
   8693 {
   8694     int my_modid_list[KT2_MAX_MODIDS_PER_TRANSLATION_TABLE] = {0};
   8695     int my_modid_valid[KT2_MAX_MODIDS_PER_TRANSLATION_TABLE] = {0};
   8696     int my_modport_base_ptr[KT2_MAX_MODIDS_PER_TRANSLATION_TABLE] = {0};
   8697 
   8698     if(mod_cfg == NULL) {
   8699         return BCM_E_PARAM;
   8700     }
   8701 
   8702     /* Sanity check the 'mod_index' value, first index (_BCMI_KATANA2_MODULE_1)
   8703        reserved for front panel ports */
   8704     if((mod_index < _BCMI_KATANA2_MODULE_2) ||
   8705        (mod_index > KT2_MAX_MODIDS_PER_TRANSLATION_TABLE)) {
   8706         return BCM_E_PARAM;
   8707     }
   8708 
   8709 
   8710     BCM_IF_ERROR_RETURN(
   8711         bcm_kt2_modid_get_all(unit, my_modid_list, my_modid_valid,
   8712                               my_modport_base_ptr));
   8713 
   8714     *mod_cfg = FALSE;
   8715 
   8716     /* Depending on the mod_index, compute the subsequent mods,
   8717        to check if they are already created, fall thru to check all,
   8718        the array index is '0' based whereas the index is '1' based.
   8719        _BCMI_KATANA2_MODULE_1 is reserved for local-mod and the
   8720        _BCMI_KATANA2_MODULE_2/3/4 are used for CoE ports */
   8721     switch(mod_index) {
   8722 
   8723         /* coverity[fallthrough] */
   8724         case _BCMI_KATANA2_MODULE_2:
   8725             *mod_cfg = my_modid_valid[_BCMI_KATANA2_MODULE_3];
   8726 
   8727         /* coverity[unterminated_case] */
   8728         case _BCMI_KATANA2_MODULE_3:
   8729             if(*mod_cfg == FALSE) {
   8730                 *mod_cfg = my_modid_valid[_BCMI_KATANA2_MODULE_4];
   8731             }
   8732             break;
   8733         case _BCMI_KATANA2_MODULE_4:
   8734             /* The last module can always be deleted, just set to 0 */
   8735             *mod_cfg = 0;
   8736             break;
   8737         default:
   8738             return BCM_E_PARAM;
   8739     }
   8740 
   8741     return BCM_E_NONE;
   8742 }
   8743 
   8744 #endif /* #if defined(BCM_KATANA2_SUPPORT) */
   8745 
   8746 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   8747 
   8748 /*
   8749  * Function:
   8750  *      _bcm_update_mod_config_by_type
   8751  * Purpose:
   8752  *      Derive index to source mod port tables.
   8753  * Parameters:
   8754  *      unit        - (IN) SOC unit number.
   8755  *      flags       - (IN) Indicates type of module
   8756  *      mod_index   - (IN) Index of the module being updated
   8757  *      mod_id      - (IN) The module identifier being updated
   8758  *      valid       - (IN) Indicates if the mod being passed is valid
   8759  *      base_idx    - (IN) Base index to program if the module is valid
   8760  * Returns:
   8761  *      BCM_E_xxx
   8762  */
   8763 
   8764 STATIC int _bcm_esw_stk_update_mod_config_by_type(int unit, int flags, int mod_index, 
   8765                                                   int mod_id, int valid, int base_idx)
   8766 {
   8767     uint64      mod_64;
   8768     soc_reg_t   reg;
   8769     int mod_id_fld, mod_base_fld, mod_valid_fld;
   8770 
   8771     /* Make sure the caller has provided a valid type of module */
   8772     if(!(flags & BCM_MODID_TYPE_COE) &&
   8773        !(flags & BCM_MODID_TYPE_MULTI_NEXT_HOPS)) {
   8774         return BCM_E_INTERNAL;
   8775     }
   8776 
   8777     /* Switch based on the mod_id and set the appropriate registry */
   8778     switch (mod_index) {
   8779 
   8780         case BCM_TD2P_COE_MODULE_1:
   8781 
   8782             /* Determine the correct field to program */
   8783             mod_id_fld = MODID_1f;
   8784             mod_base_fld = MODID_1_BASEf;
   8785             mod_valid_fld = MODID_1_VALIDf;
   8786 
   8787             /* Make a note of the specific register we need to update */
   8788             reg = MY_MODID_SET_2_64r;
   8789 
   8790             break;
   8791 
   8792         case BCM_TD2P_COE_MODULE_2:
   8793 
   8794             /* Determine the correct field to program */
   8795             mod_id_fld = MODID_2f;
   8796             mod_base_fld  = MODID_2_BASEf;
   8797             mod_valid_fld = MODID_2_VALIDf;
   8798 
   8799             /* Make a note of the specific register we need to update */
   8800             reg = MY_MODID_SET_3_64r;
   8801 
   8802             break;
   8803 
   8804         case BCM_TD2P_COE_MODULE_3:
   8805 
   8806            mod_id_fld = MODID_3f;
   8807            mod_base_fld  = MODID_3_BASEf;
   8808            mod_valid_fld = MODID_3_VALIDf;
   8809 
   8810            /* Make a note of the specific register we need to update */
   8811            reg = MY_MODID_SET_3_64r;
   8812 
   8813            break;
   8814 
   8815         case BCM_TD2P_COE_MODULE_4:
   8816 
   8817             mod_id_fld = MODID_4f;
   8818             mod_base_fld  = MODID_4_BASEf;
   8819             mod_valid_fld = MODID_4_VALIDf;
   8820 
   8821             /* Make a note of the specific register we need to update */
   8822             reg = MY_MODID_SET_4_64r;
   8823             break;
   8824 
   8825         case BCM_TD2P_COE_MODULE_5:
   8826 
   8827            mod_id_fld = MODID_5f;
   8828            mod_base_fld  = MODID_5_BASEf;
   8829            mod_valid_fld = MODID_5_VALIDf;
   8830 
   8831            /* Make a note of the specific register we need to update */
   8832            reg = MY_MODID_SET_4_64r;
   8833 
   8834            break;
   8835 
   8836         default:
   8837             return BCM_E_PARAM;
   8838     }
   8839 
   8840     /* Setup the base register */
   8841     COMPILER_64_ZERO(mod_64);
   8842     BCM_IF_ERROR_RETURN(READ_MY_MODID_SET_64r(unit, &mod_64));
   8843     soc_reg64_field32_set(unit, MY_MODID_SET_64r, &mod_64,
   8844             mod_id_fld, (valid ? (mod_id): 0));
   8845     soc_reg64_field32_set(unit, MY_MODID_SET_64r, &mod_64,
   8846             mod_valid_fld, valid);
   8847     BCM_IF_ERROR_RETURN(WRITE_MY_MODID_SET_64r(unit, mod_64));
   8848 
   8849     /* Update the specific register */
   8850 
   8851     /* Set the individual registers */
   8852     COMPILER_64_ZERO(mod_64);
   8853     BCM_IF_ERROR_RETURN(soc_reg_get(unit, reg, REG_PORT_ANY, 0, &mod_64));
   8854 
   8855     soc_reg64_field32_set(unit, reg, &mod_64,
   8856             mod_id_fld, (valid ? (mod_id): 0));
   8857     soc_reg64_field32_set(unit, reg, &mod_64,
   8858             mod_base_fld, base_idx);
   8859     soc_reg64_field32_set(unit, reg, &mod_64,
   8860             mod_valid_fld, valid);
   8861     BCM_IF_ERROR_RETURN(soc_reg_set(unit, reg, REG_PORT_ANY, 0, mod_64));
   8862 
   8863     /* Set the egress registers */
   8864     if (!(flags & BCM_MODID_TYPE_MULTI_NEXT_HOPS)) {
   8865         /* Set the egress registers */
   8866         COMPILER_64_ZERO(mod_64);
   8867         BCM_IF_ERROR_RETURN(READ_EGR_MY_MODID_SET_64r(unit, &mod_64));
   8868         soc_reg64_field32_set(unit, EGR_MY_MODID_SET_64r, &mod_64,
   8869                               mod_id_fld, (valid ? (mod_id): 0));
   8870         soc_reg64_field32_set(unit, EGR_MY_MODID_SET_64r, &mod_64,
   8871                               mod_valid_fld, valid);
   8872         BCM_IF_ERROR_RETURN(WRITE_EGR_MY_MODID_SET_64r(unit, mod_64));
   8873     }
   8874 
   8875     return BCM_E_NONE;
   8876 }
   8877 
   8878 /*
   8879  * Function:
   8880  *      _bcm_esw_stk_get_mod_config_by_type
   8881  * Purpose:
   8882  *      Retrieve index to source mod port tables.
   8883  * Parameters:
   8884  *      unit        - (IN) SOC unit number.
   8885  *      flags       - (IN) Indicates type of module
   8886  *      mod_index   - (IN) Index of the module being retrieved
   8887  *      mod_id      - (OUT) The module identifier being retrieved
   8888  *      valid       - (OUT) Indicates if the mod is valid
   8889  *      base_idx    - (OUT) Base index to program
   8890  * Returns:
   8891  *      BCM_E_xxx
   8892  */
   8893 
   8894 int _bcm_esw_stk_get_mod_config_by_type(int unit, int flags, int mod_index,
   8895                                         int *mod_id, int *valid, int *base_idx)
   8896 {
   8897     uint64      mod_64;
   8898 
   8899     int mod_id_fld[] = {MODID_1f,
   8900                         MODID_2f,
   8901                         MODID_3f,
   8902                         MODID_4f,
   8903                         MODID_5f};
   8904     int mod_base_fld[] = {MODID_1_BASEf,
   8905                           MODID_2_BASEf,
   8906                           MODID_3_BASEf,
   8907                           MODID_4_BASEf,
   8908                           MODID_5_BASEf};
   8909     int mod_valid_fld[] = {MODID_1_VALIDf,
   8910                            MODID_2_VALIDf,
   8911                            MODID_3_VALIDf,
   8912                            MODID_4_VALIDf,
   8913                            MODID_5_VALIDf};
   8914     int reg[] = {MY_MODID_SET_2_64r,
   8915                  MY_MODID_SET_3_64r,
   8916                  MY_MODID_SET_3_64r,
   8917                  MY_MODID_SET_4_64r,
   8918                  MY_MODID_SET_4_64r};
   8919 
   8920     /* Make sure the caller has provided a valid type of module */
   8921     if(!(flags & BCM_MODID_TYPE_COE) &&
   8922        !(flags & BCM_MODID_TYPE_MULTI_NEXT_HOPS)) {
   8923         return BCM_E_INTERNAL;
   8924     }
   8925 
   8926 
   8927     if ((mod_index < BCM_TD2P_COE_MODULE_1) ||
   8928         (mod_index > BCM_TD2P_COE_MODULE_5)) {
   8929         return BCM_E_PARAM;
   8930     }
   8931 
   8932     /* Get the individual registers */
   8933     COMPILER_64_ZERO(mod_64);
   8934     BCM_IF_ERROR_RETURN(
   8935         soc_reg_get(unit, reg[mod_index - 1], REG_PORT_ANY, 0, &mod_64));
   8936 
   8937     *mod_id = soc_reg64_field32_get(unit, reg[mod_index - 1], mod_64,
   8938                                     mod_id_fld[mod_index - 1]);
   8939     *base_idx = soc_reg64_field32_get(unit, reg[mod_index - 1], mod_64,
   8940                                       mod_base_fld[mod_index - 1]);
   8941     *valid = soc_reg64_field32_get(unit, reg[mod_index - 1], mod_64,
   8942                                    mod_valid_fld[mod_index - 1]);
   8943 
   8944     return BCM_E_NONE;
   8945 }
   8946 
   8947 /*
   8948  * Function    : _bcm_esw_my_modid_additional_check
   8949  * Description : Identifies if given modid is my modid on a given unit
   8950  *
   8951  * Parameters  : 
   8952  *               (IN)   unit        - BCM device number
   8953  *               (IN)   modnd    - Module ID
   8954  *               (OUT)  result    - TRUE if modid is local, FALSE otherwise
   8955  * Returns     : BCM_E_XXX
   8956  */
   8957 int
   8958 _bcm_esw_my_modid_additional_check(int unit, bcm_module_t modid, int *result)
   8959 {
   8960     int modid_value = 0;
   8961     uint32 modid_mask = 0;
   8962 
   8963     /* Parameter check */
   8964     if (result == NULL) {
   8965         return (BCM_E_PARAM);
   8966     }
   8967 
   8968     BCM_IF_ERROR_RETURN
   8969         (_bcm_esw_stk_modid_range_info_get(unit, &modid_value, &modid_mask));
   8970     if(!modid_mask) { /* No extra my modid */
   8971         *result = FALSE;
   8972         return (BCM_E_NONE);
   8973     }
   8974 
   8975     if((modid & modid_mask) == (modid_value & modid_mask)) {
   8976         *result = TRUE;
   8977     } else {
   8978         *result = FALSE;
   8979     }
   8980 
   8981 	return (BCM_E_NONE);
   8982 }
   8983 /*
   8984  * Function:
   8985  *      _bcm_esw_stk_modid_range_info_get
   8986  * Purpose:
   8987  *      Get the module ID and module MASK from HW.
   8988  * Parameters:
   8989  *      unit                - (IN) SOC unit#
   8990  *      mod_base       - (OUT) module ID.
   8991  *      mod_mask       - (OUT) The module mask.
   8992  * Returns:
   8993  *      BCM_E_xxx
   8994  */
   8995 int _bcm_esw_stk_modid_range_info_get(int unit, int *mod_base, uint32 *mod_mask)
   8996 {
   8997 
   8998     /* Parameter check */
   8999     if(NULL == mod_base || NULL == mod_mask) {
   9000         return BCM_E_PARAM;
   9001     }
   9002 
   9003     *mod_base = src_modid_base_index_bk[unit]->module_id_range.mod_base;
   9004     *mod_mask = src_modid_base_index_bk[unit]->module_id_range.mod_mask;
   9005 
   9006     return BCM_E_NONE;
   9007 }
   9008 
   9009 /*
   9010  * Function:
   9011  *      _bcm_esw_stk_modid_range_set
   9012  * Purpose:
   9013  *      Set the module ID and module MASK into HW.
   9014  * Parameters:
   9015  *      unit                - (IN) SOC unit#
   9016  *      mod_base       - (IN) module ID.
   9017  *      mod_mask       - (IN) The module mask.
   9018  *      valid               - (IN) valid bit.
   9019  * Returns:
   9020  *      BCM_E_xxx
   9021  */
   9022 int _bcm_esw_stk_modid_range_set(int unit, int mod_base, uint32 mod_mask, uint32 valid)
   9023 {
   9024     uint32 rval = 0;
   9025 
   9026     /* Parameter check */
   9027     if((mod_base < 0) || (mod_base > 0xff) || (mod_mask > 0xff)) {
   9028         return BCM_E_PARAM;
   9029     }
   9030 
   9031     BCM_IF_ERROR_RETURN
   9032         (soc_reg32_get(unit, MY_MODID_CONFIGr, REG_PORT_ANY, 0, &rval));
   9033     soc_reg_field_set(unit, MY_MODID_CONFIGr, &rval, VALUEf, mod_base);
   9034     soc_reg_field_set(unit, MY_MODID_CONFIGr, &rval, MASKf, mod_mask);
   9035     soc_reg_field_set(unit, MY_MODID_CONFIGr, &rval, VALIDf, (valid ? 1 : 0));
   9036     BCM_IF_ERROR_RETURN
   9037         (soc_reg32_set(unit, MY_MODID_CONFIGr, REG_PORT_ANY, 0, rval));
   9038     BCM_IF_ERROR_RETURN
   9039         (soc_reg32_get(unit, MY_MODID_CONFIG_2r, REG_PORT_ANY, 0, &rval));
   9040     soc_reg_field_set(unit, MY_MODID_CONFIG_2r, &rval, VALUEf, mod_base);
   9041     soc_reg_field_set(unit, MY_MODID_CONFIG_2r, &rval, MASKf, mod_mask);
   9042     soc_reg_field_set(unit, MY_MODID_CONFIG_2r, &rval, VALIDf, (valid ? 1 : 0));
   9043     BCM_IF_ERROR_RETURN
   9044         (soc_reg32_set(unit, MY_MODID_CONFIG_2r, REG_PORT_ANY, 0, rval));
   9045     src_modid_base_index_bk[unit]->module_id_range.mod_base = mod_base;
   9046     src_modid_base_index_bk[unit]->module_id_range.mod_mask = mod_mask;
   9047 
   9048     return BCM_E_NONE;
   9049 }
   9050 
   9051 /*
   9052  * Function:
   9053  *      _bcm_esw_stk_multi_next_hops_modid_valid
   9054  * Purpose:
   9055  *      Check the module ID for multiple next hops.
   9056  * Parameters:
   9057  *      modid             - (IN) Module ID.
   9058  *      mod_mask       - (IN) The module mask.
   9059  * Returns:
   9060  *      BCM_E_xxx
   9061  */
   9062 int _bcm_esw_stk_multi_nexthops_modid_valid(int modid, uint32 mod_mask)
   9063 {
   9064     int i = 0;
   9065 
   9066     for (i = 0; i < BCM_MAX_NUM_MODID_MASK; i++) {
   9067         /* The range only one module */
   9068         if(mod_mask == modid_mask_data[0].mod_mask) {
   9069             return BCM_E_NONE;
   9070         }
   9071 
   9072         /* The range more than one module */
   9073         if(mod_mask == modid_mask_data[i].mod_mask) {
   9074             break;
   9075         }
   9076     }
   9077 
   9078     for (; i < BCM_MAX_NUM_MODID_MASK; i++) {
   9079         if((modid % modid_mask_data[i].num_mods) == 0) {
   9080             break;
   9081         }
   9082     }
   9083 
   9084     if(i == BCM_MAX_NUM_MODID_MASK) {
   9085         return BCM_E_PARAM;
   9086     }
   9087 
   9088     return BCM_E_NONE;
   9089 }
   9090 
   9091 /*
   9092  * Function:
   9093  *      _bcm_esw_stk_multi_nexthops_module_mask_get
   9094  * Purpose:
   9095  *      Get the module mask for the specified number of modules.
   9096  * Parameters:
   9097  *      num_mods       - (IN) The number of modules.
   9098  *      mod_mask       - (OUT) The module mask.
   9099  * Returns:
   9100  *      BCM_E_xxx
   9101  */
   9102 int _bcm_esw_stk_multi_nexthops_module_mask_get(int num_mods, uint32 *mod_mask)
   9103 {
   9104     int i = 0;
   9105 
   9106     /* Parameter check */
   9107     if(NULL == mod_mask || num_mods <= 0) {
   9108         return BCM_E_PARAM;
   9109     }
   9110 
   9111     for (i = 0; i < BCM_MAX_NUM_MODID_MASK; i++) {
   9112         if(num_mods == modid_mask_data[i].num_mods) {
   9113             break;
   9114         }
   9115     }
   9116 
   9117     if(i == BCM_MAX_NUM_MODID_MASK) {
   9118         return BCM_E_PARAM;
   9119     }
   9120 
   9121     *mod_mask = modid_mask_data[i].mod_mask;
   9122 
   9123     return BCM_E_NONE;
   9124 }
   9125 
   9126 /*
   9127  * Function:
   9128  *      _bcm_esw_stk_multi_nexthops_modules_num_get
   9129  * Purpose:
   9130  *      Get the number of modules for the specified module mask.
   9131  * Parameters:
   9132  *      mod_mask       - (IN) The module mask.
   9133  *      num_mods       - (OUT) The number of modules.
   9134  * Returns:
   9135  *      BCM_E_xxx
   9136  */
   9137 
   9138 int _bcm_esw_stk_multi_nexthops_modules_num_get(uint32 mod_mask, int *num_mods)
   9139 {
   9140     int i = 0;
   9141 
   9142     /* Parameter check */
   9143     if(NULL == num_mods) {
   9144         return BCM_E_PARAM;
   9145     }
   9146 
   9147     if(mod_mask == 0) {
   9148         *num_mods = 0;
   9149         return BCM_E_NONE;
   9150     }
   9151 
   9152     for (i = 0; i < BCM_MAX_NUM_MODID_MASK; i++) {
   9153         if(mod_mask == modid_mask_data[i].mod_mask) {
   9154             break;
   9155         }
   9156     }
   9157 
   9158     if(i == BCM_MAX_NUM_MODID_MASK) {
   9159         return BCM_E_PARAM;
   9160     }
   9161 
   9162     *num_mods = modid_mask_data[i].num_mods;
   9163 
   9164     return BCM_E_NONE;
   9165 }
   9166 
   9167 /*
   9168  * Function:
   9169  *      _bcm_esw_stk_modid_range_config_add
   9170  * Purpose:
   9171  *      Add a module range of multiple next hop type 
   9172  * Parameters:
   9173  *      unit            -  (IN)SOC unit#
   9174  *      mod_cfg      -  (OUT)the value
   9175  * Returns:
   9176  *      BCM_E_XXX
   9177  */	
   9178 int _bcm_esw_stk_modid_range_config_add(int unit, bcm_stk_modid_config_t *mod_cfg)
   9179 {
   9180     uint32 mod_mask = 0, old_mod_mask = 0;
   9181     int mod_idx = 0, i = 0, rv = 0;
   9182     int old_modid = 0, base_index = 0;
   9183     int modid = mod_cfg->modid;
   9184     int n_ports = mod_cfg->num_ports;
   9185     int n_mods = mod_cfg->num_mods;
   9186     soc_info_t *si = &SOC_INFO(unit);
   9187 
   9188     /* Parameter check */
   9189     if ((mod_cfg == NULL)||(modid > SOC_MODID_MAX(unit)) || (modid < 0) 
   9190         || ((n_ports < 0) && (n_ports != -1))
   9191         || (n_ports > SOC_PORT_ADDR_MAX(unit) + 1)
   9192         || (mod_cfg->modid_type != bcmStkModidTypeMultiNextHops)) {
   9193         return BCM_E_PARAM;
   9194     }
   9195 
   9196     if (n_ports == 0) {
   9197         /* num_ports 0 for a module only mapping to a local egress port
   9198          * and port on this module is ignored during this mapping.
   9199          */
   9200         BCM_IF_ERROR_RETURN(
   9201             _bcm_esw_stk_multi_nexthops_module_mask_get(mod_cfg->num_mods,
   9202             &mod_mask));
   9203 
   9204         BCM_IF_ERROR_RETURN
   9205             (_bcm_esw_stk_multi_nexthops_modid_valid(modid, mod_mask));
   9206 
   9207         BCM_IF_ERROR_RETURN(
   9208             _bcm_esw_stk_modid_range_info_get(unit, &old_modid, &old_mod_mask));
   9209         if ((old_modid && (old_modid != modid)) ||
   9210             (old_mod_mask && (old_mod_mask != mod_mask))) {
   9211             return BCM_E_RESOURCE;
   9212         }
   9213 
   9214         for (mod_idx = modid; mod_idx < modid + mod_cfg->num_mods; mod_idx++) {
   9215             /* Check if the modid passed in is the same as any of the existing
   9216              * mod ids, if it is return error
   9217              */
   9218             if (src_modid_base_index_bk[unit]->num_ports[mod_idx] > 0) {
   9219                 return BCM_E_EXISTS;
   9220             }
   9221         }
   9222 
   9223         n_ports = 1;
   9224         for (mod_idx = modid; mod_idx < modid + mod_cfg->num_mods; mod_idx++) {
   9225             rv = _src_modid_base_index_alloc(
   9226                     unit, mod_idx, n_ports, 0, &base_index);
   9227             if (BCM_FAILURE(rv)) {
   9228                 goto cleanup;
   9229             }
   9230             src_modid_base_index_bk[unit]->num_ports[mod_idx] = n_ports;
   9231         }
   9232 
   9233         BCM_IF_ERROR_RETURN
   9234             (_bcm_esw_stk_modid_range_set(unit, modid, mod_mask, 1));
   9235     } else {
   9236         if (n_mods > 1) {
   9237             return BCM_E_PARAM;
   9238         }
   9239 
   9240         /* Now check if the dual_mod id mode is enable, if it is, the modid
   9241          * cannot be a odd, since the modid+1 is always reserved for the second
   9242          * set of ports
   9243          */
   9244         if ((NUM_MODID(unit) > 1) && ((modid % 2) != 0)) {
   9245             return BCM_E_PARAM;
   9246         }
   9247 
   9248         /* Check if the modid passed in is the same as any of the existing
   9249                mod ids, if it is return error */
   9250         if (src_modid_base_index_bk[unit]->num_ports[modid] > 0) {
   9251             return BCM_E_EXISTS;
   9252         }
   9253 
   9254         /* Check if the current mod list is full */
   9255         for (i = 0; i < si->num_modules; i++) {
   9256             if (src_modid_base_index_bk[unit]->module_id_type_list[i] == 0) {
   9257                 break;
   9258             }
   9259         }
   9260 
   9261         /* If no room left, send back a resource error */
   9262         if (i == si->num_modules) {
   9263             return BCM_E_RESOURCE;
   9264         }
   9265 
   9266         /* Start allocating resources based on the 'nports' value */
   9267         if (n_ports == -1) {
   9268             /* If nports is '-1' allocate max ports possible */
   9269             n_ports = SOC_PORT_ADDR_MAX(unit) + 1;
   9270         }
   9271 
   9272         rv = _src_modid_base_index_alloc(unit, modid, n_ports, 0,
   9273                                          &base_index);
   9274         if (BCM_FAILURE(rv)) {
   9275             goto cleanup;
   9276         }
   9277         rv = _bcm_esw_stk_update_mod_config_by_type(
   9278                 unit, BCM_MODID_TYPE_MULTI_NEXT_HOPS, i+1, modid, 1,
   9279                 base_index);
   9280         if (BCM_FAILURE(rv)) {
   9281             goto cleanup;
   9282         }
   9283 
   9284         /* Store the number of ports allocated */
   9285         src_modid_base_index_bk[unit]->num_ports[modid] = n_ports;
   9286 
   9287         /* Record the fact that we have added a Multi Nexthop module */
   9288         src_modid_base_index_bk[unit]->multi_nexthop_module_id_list[i] = modid;
   9289 
   9290         /* Record the module id and type that we have added*/
   9291         src_modid_base_index_bk[unit]->module_id_type_list[i] =
   9292             BCM_MODID_TYPE_MULTI_NEXT_HOPS;
   9293     }
   9294     return BCM_E_NONE;
   9295 
   9296 cleanup:
   9297     for (i = modid; i < mod_idx; i++) {
   9298         (void) _src_modid_base_index_free(unit, i, 
   9299                    src_modid_base_index_bk[unit]->num_ports[i]);
   9300         src_modid_base_index_bk[unit]->num_ports[i] = 0;
   9301     }
   9302     return rv;
   9303 }
   9304 
   9305 /*
   9306  * Function:
   9307  *      _bcm_esw_stk_modid_range_config_get
   9308  * Purpose:
   9309  *      Get the module range config
   9310  * Parameters:
   9311  *      unit          - (IN)SOC unit#
   9312  *      mod_cfg    - (OUT)the value
   9313  * Returns:
   9314  *      BCM_E_XXX
   9315  */
   9316 int _bcm_esw_stk_modid_range_config_get(int unit, bcm_stk_modid_config_t *mod_cfg)
   9317 {
   9318     uint32 mod_mask = 0;
   9319     int i = 0;
   9320     soc_info_t *si = &SOC_INFO(unit);
   9321 
   9322     /* Parameter check */
   9323     if ((mod_cfg == NULL)
   9324         || (mod_cfg->modid_type != bcmStkModidTypeMultiNextHops)) {
   9325         return BCM_E_PARAM;
   9326     }
   9327 
   9328     if (mod_cfg->modid == BCM_MODID_INVALID) {
   9329         BCM_IF_ERROR_RETURN(
   9330             _bcm_esw_stk_modid_range_info_get(unit, &mod_cfg->modid,
   9331             &mod_mask));
   9332         if(!mod_mask) {
   9333             mod_cfg->modid = BCM_MODID_INVALID;
   9334         }
   9335 
   9336         BCM_IF_ERROR_RETURN(
   9337             _bcm_esw_stk_multi_nexthops_modules_num_get(mod_mask,
   9338             &mod_cfg->num_mods));
   9339 
   9340         if (mod_cfg->modid >= 0) {
   9341             mod_cfg->num_ports = 0;
   9342         }
   9343     } else {
   9344         if ((mod_cfg->modid < 0) || (mod_cfg->modid > SOC_MODID_MAX(unit))) {
   9345             return BCM_E_PARAM;
   9346         }
   9347 
   9348         /* Look for and return details for the mod-id passed in */
   9349         for (i = 0; i < si->num_modules; i++) {
   9350             if (src_modid_base_index_bk[unit]->multi_nexthop_module_id_list[i]
   9351                 == mod_cfg->modid) {
   9352                 mod_cfg->num_ports =
   9353                     src_modid_base_index_bk[unit]->num_ports[mod_cfg->modid];
   9354                 mod_cfg->num_mods = 1;
   9355                 break;
   9356             }
   9357         }
   9358 
   9359         if (i == si->num_modules) {
   9360             return BCM_E_NOT_FOUND;
   9361         }
   9362     }
   9363 
   9364     return BCM_E_NONE;
   9365 }
   9366 
   9367 /*
   9368  * Function:
   9369  *      _bcm_esw_stk_modid_range_config_delete
   9370  * Purpose:
   9371  *      Delete the specific module range
   9372  * Parameters:
   9373  *      unit              - (IN) SOC unit#
   9374  *      modid_type   - (IN)The type of module
   9375  * Returns:
   9376  *      BCM_E_XXX
   9377  */
   9378 int _bcm_esw_stk_modid_range_config_delete(int unit,
   9379         bcm_stk_modid_config_t *mod_cfg)
   9380 {
   9381     uint32 mod_mask = 0;
   9382     int mod_idx = 0, i = 0;
   9383     int modid = 0;
   9384     int num_mods = 0;
   9385     int nports = 0;
   9386     soc_info_t *si = &SOC_INFO(unit);
   9387     /* Parameter check */
   9388     if (mod_cfg->modid_type != bcmStkModidTypeMultiNextHops) {
   9389         return BCM_E_PARAM;
   9390     }
   9391 
   9392     if (mod_cfg->modid == BCM_MODID_INVALID) {
   9393         BCM_IF_ERROR_RETURN
   9394             (_bcm_esw_stk_modid_range_info_get(unit, &modid, &mod_mask));
   9395         if(mod_mask) {
   9396             nports = src_modid_base_index_bk[unit]->num_ports[modid];
   9397         }
   9398 
   9399         BCM_IF_ERROR_RETURN(
   9400             _bcm_esw_stk_multi_nexthops_modules_num_get(mod_mask, &num_mods));
   9401         for (mod_idx = modid; mod_idx < modid + num_mods; mod_idx++) {
   9402             BCM_IF_ERROR_RETURN
   9403                 (_src_modid_base_index_free(unit, mod_idx, nports));
   9404             src_modid_base_index_bk[unit]->num_ports[mod_idx] = 0;
   9405         }
   9406 
   9407         /* Clear MY_MODID_CONFIGr */
   9408         BCM_IF_ERROR_RETURN
   9409             (_bcm_esw_stk_modid_range_set(unit, 0, 0, 0));
   9410     } else {
   9411         modid = mod_cfg->modid;
   9412         if (modid > SOC_MODID_MAX(unit)) {
   9413             return BCM_E_PARAM;
   9414         }
   9415 
   9416         /* Now check if the dual_mod id mode is enable, if it is, the modid
   9417            cannot be a odd, since the modid+1 is always reserved for the second
   9418            set of ports */
   9419         if((NUM_MODID(unit) > 1) && ((modid%2) != 0)) {
   9420             return BCM_E_PARAM;
   9421         }
   9422 
   9423         /* Check if the modid passed in is configured, if it is not
   9424            return error */
   9425         if (src_modid_base_index_bk[unit]->num_ports[modid] <= 0) {
   9426             return BCM_E_NOT_FOUND;
   9427         }
   9428 
   9429         /* Get the index of the Multi Next Hop array where this mod lives */
   9430         for (i = 0; i < si->num_modules; i++) {
   9431             if (src_modid_base_index_bk[unit]->multi_nexthop_module_id_list[i] ==
   9432                 modid) {
   9433                 break;
   9434             }
   9435         }
   9436 
   9437         /* No such module configued, send back an error */
   9438         if (i == si->num_modules) {
   9439             return BCM_E_PARAM;
   9440         }
   9441 
   9442         BCM_IF_ERROR_RETURN(
   9443             _bcm_esw_stk_update_mod_config_by_type(unit,
   9444             BCM_MODID_TYPE_MULTI_NEXT_HOPS, i+1, modid, 0, 0));
   9445 
   9446         /* Get the number of ports for this mod id */
   9447         nports = src_modid_base_index_bk[unit]->num_ports[modid];
   9448 
   9449         /* Free the range of modports allocated */
   9450         BCM_IF_ERROR_RETURN
   9451             (_src_modid_base_index_free(unit, modid, nports));
   9452 
   9453         /* Reset the number of ports */
   9454         src_modid_base_index_bk[unit]->num_ports[modid] = 0;
   9455 
   9456         /* Record the fact that we this entry is now available */
   9457         src_modid_base_index_bk[unit]->multi_nexthop_module_id_list[i] =
   9458             BCM_MODID_INVALID;
   9459 
   9460         /* Reset the module id type*/
   9461         src_modid_base_index_bk[unit]->module_id_type_list[i] = 0;
   9462     }
   9463 
   9464     return BCM_E_NONE;
   9465 }
   9466 
   9467 #endif /* #if BCM_TRIDENT2PLUS_SUPPORT */
   9468 
   9469 #if defined(BCM_TRIDENT2PLUS_SUPPORT) || defined(BCM_KATANA2_SUPPORT)
   9470 
   9471 /*
   9472  * Function:
   9473  *      _bcm_esw_stk_modid_config_add
   9474  * Purpose:
   9475  *      Add a new module
   9476  * Parameters:
   9477  *      unit        - (In)SOC unit#
   9478  *      mod_cfg  - (Out)The config parm
   9479  * Returns:
   9480  *      BCM_E_XXX
   9481  */
   9482 int
   9483 _bcm_esw_stk_modid_config_add(
   9484     int unit,
   9485     bcm_stk_modid_config_t *mod_cfg)
   9486 {
   9487     int modid = 0, i = 0, rv = BCM_E_NONE, base_index = 0;
   9488     int n_ports = mod_cfg->num_ports;
   9489     soc_info_t *si = &SOC_INFO(unit);
   9490 
   9491     /* Parameter check */
   9492     if ((mod_cfg == NULL) ||
   9493         (mod_cfg->modid < 0) ||
   9494         (mod_cfg->modid > SOC_MODID_MAX(unit))) {
   9495             return BCM_E_PARAM;
   9496     }
   9497 
   9498     /* Ensure the number of ports is a valid value */
   9499 	if ((n_ports > (SOC_PORT_ADDR_MAX(unit) + 1)) || (n_ports < -1) ||
   9500 		(n_ports == 0)) {
   9501 		return BCM_E_PARAM;
   9502 	}
   9503 
   9504     /* Get the module Id */
   9505     modid = mod_cfg->modid;
   9506 
   9507     /* Now check if the dual_mod id mode is enable, if it is, the modid
   9508          * cannot be a odd, since the modid+1 is always reserved for the second
   9509          * set of ports
   9510          */
   9511     if((NUM_MODID(unit) > 1) && ((modid % 2) != 0)) {
   9512         return BCM_E_PARAM;
   9513     }
   9514 
   9515     /* Check if the modid passed in is the same as any of the existing
   9516            mod ids, if it is return error */
   9517     if (src_modid_base_index_bk[unit]->num_ports[modid] > 0) {
   9518         return BCM_E_EXISTS;
   9519     }
   9520 
   9521     /* Check if the current CoE mod list is full */
   9522     for (i=0; i<si->num_coe_modules; i++) {
   9523         if (src_modid_base_index_bk[unit]->coe_module_id_list[i] ==
   9524                  BCM_MODID_INVALID) {
   9525                     break;
   9526         }
   9527     }
   9528 
   9529     /* If no room left, send back a resource error */
   9530     if (i == si->num_coe_modules) {
   9531         return BCM_E_RESOURCE;
   9532     }
   9533 
   9534     if (soc_feature(unit, soc_feature_multi_next_hops_on_port)) {
   9535         /* Check if the current mod list is full */
   9536         for (i = 0; i < si->num_modules; i++) {
   9537             if (src_modid_base_index_bk[unit]->module_id_type_list[i] == 0) {
   9538                 break;
   9539             }
   9540         }
   9541 
   9542         /* If no room left, send back a resource error */
   9543         if (i == si->num_modules) {
   9544             return BCM_E_RESOURCE;
   9545         }
   9546     }
   9547 
   9548     /* Start allocating resources based on the 'nports' value */
   9549     if (n_ports <= -1) {
   9550         /* If nports is '-1' allocate max ports possible */
   9551         n_ports = SOC_PORT_ADDR_MAX(unit) + 1;
   9552     }
   9553 
   9554     BCM_IF_ERROR_RETURN
   9555         (_src_modid_base_index_alloc(unit, modid, n_ports, 0, &base_index));
   9556 
   9557 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   9558 
   9559     if (soc_feature(unit, soc_feature_hgproxy_subtag_coe)) {
   9560 
   9561         
   9562 
   9563         /* Program the relevant registers */
   9564         rv = _bcm_esw_stk_update_mod_config_by_type(unit,
   9565                      BCM_MODID_TYPE_COE, i+1, modid, 1, base_index);
   9566         if (BCM_FAILURE(rv)) {
   9567             goto cleanup;
   9568         }
   9569     }
   9570 #endif /* #if defined(BCM_TRIDENT2PLUS_SUPPORT) */
   9571 
   9572 #if defined(BCM_KATANA2_SUPPORT)
   9573 
   9574     if (si->coe_stacking_mode) {
   9575         uint8 modport_count = 0;
   9576         int pp_port_index_min = SOC_INFO(unit).pp_port_index_min;
   9577         int subport_port_max = SOC_INFO(unit).subport_port_max;
   9578 
   9579         /* Based on the current mod_index, gather modports already
   9580            configured, prior to this index */
   9581         rv = _bcm_stk_index_based_cfg_modport_count(unit, (i+1),
   9582                                                     &modport_count);
   9583         if (BCM_FAILURE(rv)) {
   9584             goto cleanup;
   9585         }
   9586 
   9587         /* Make sure there is room to fit the current allocation */
   9588         if ((modport_count + n_ports) > subport_port_max) {
   9589             return BCM_E_PARAM;
   9590         }
   9591 
   9592         /* Setup the CoE module */
   9593         rv = bcm_kt2_modid_set(unit, (i+1), modid, 1,
   9594                       (modport_count + pp_port_index_min));
   9595         if (BCM_FAILURE(rv)) {
   9596             goto cleanup;
   9597         }
   9598     }
   9599 
   9600 #endif /* #if defined(BCM_KATANA2_SUPPORT) */
   9601 
   9602     /* Store the number of ports allocated */
   9603     src_modid_base_index_bk[unit]->num_ports[modid] = n_ports;
   9604 
   9605     /* Record the fact that we have added a CoE module */
   9606     src_modid_base_index_bk[unit]->coe_module_id_list[i] = modid;
   9607 
   9608     /* Record the module id and type that we have added*/
   9609     if (soc_feature(unit, soc_feature_multi_next_hops_on_port)) {
   9610         src_modid_base_index_bk[unit]->module_id_type_list[i] =
   9611             BCM_MODID_TYPE_COE;
   9612     }
   9613 
   9614 cleanup:
   9615 
   9616     /* On a failure, release the allocate resource */
   9617     if (BCM_FAILURE(rv)) {
   9618         (void)_src_modid_base_index_free(unit, modid,
   9619                  src_modid_base_index_bk[unit]->num_ports[modid]);
   9620     }
   9621 
   9622     return rv;
   9623 }
   9624 
   9625 #endif
   9626 
   9627 /*
   9628  * Function:
   9629  *      bcm_esw_stk_modid_config_add
   9630  * Purpose:
   9631  *      Add a new module or module range
   9632  * Parameters:
   9633  *      unit     - (In)SOC unit#
   9634  *      mod_cfg  - (Out)The config parm
   9635  * Returns:
   9636  *      BCM_E_XXX
   9637  */
   9638 int
   9639 bcm_esw_stk_modid_config_add(
   9640     int unit,
   9641     bcm_stk_modid_config_t *mod_cfg)
   9642 {
   9643 #if defined(BCM_TRIDENT2PLUS_SUPPORT) || defined(BCM_KATANA2_SUPPORT)
   9644     soc_info_t *si = &SOC_INFO(unit);
   9645 #endif /* (BCM_TRIDENT2PLUS_SUPPORT) || defined(BCM_KATANA2_SUPPORT) */
   9646 
   9647     BCM_STK_API_TH3_SUPPORT_CHECK(unit);
   9648 
   9649 #if defined(BCM_TRIDENT2PLUS_SUPPORT) || defined(BCM_KATANA2_SUPPORT)
   9650     /* Parameter check */
   9651     if (mod_cfg == NULL) {
   9652         return BCM_E_PARAM;
   9653     }
   9654 
   9655     switch (mod_cfg->modid_type) {
   9656 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   9657     case bcmStkModidTypeMultiNextHops:
   9658         if (soc_feature(unit, soc_feature_multi_next_hops_on_port)) {
   9659             BCM_IF_ERROR_RETURN
   9660                 (_bcm_esw_stk_modid_range_config_add(unit, mod_cfg));
   9661         } else {
   9662             return BCM_E_UNAVAIL;
   9663         }
   9664         break;
   9665 #endif
   9666     case bcmStkModidTypeCoe:
   9667         /* If hg_proxy or if (subtag/linkPhy-Coe && stacking-mode)
   9668            check the local modid */
   9669         if ((soc_feature(unit, soc_feature_hgproxy_subtag_coe)) ||
   9670             ((soc_feature(unit, soc_feature_subtag_coe) ||
   9671              (soc_feature(unit, soc_feature_linkphy_coe))) &&
   9672                si->coe_stacking_mode)) {
   9673                 BCM_IF_ERROR_RETURN
   9674                     (_bcm_esw_stk_modid_config_add(unit, mod_cfg));
   9675         } else {
   9676             return BCM_E_UNAVAIL;
   9677         }
   9678         break;
   9679     default:
   9680         return BCM_E_UNAVAIL;
   9681     }
   9682 
   9683     return BCM_E_NONE;
   9684 #endif /* #if defined(BCM_TRIDENT2PLUS_SUPPORT) || defined(BCM_KATANA2_SUPPORT)*/
   9685 
   9686     return BCM_E_UNAVAIL;
   9687 }
   9688 
   9689 
   9690 #if defined(BCM_TRIDENT2PLUS_SUPPORT) || defined(BCM_KATANA2_SUPPORT)
   9691 
   9692 /*
   9693  * Function:
   9694  *      _bcm_esw_stk_modid_config_delete
   9695  * Purpose:
   9696  *      Add a new module
   9697  * Parameters:
   9698  *      unit  - SOC unit#
   9699  *      my_modid - (IN) The modid value
   9700  *      force_delete - (IN) True if modid needs to be deleted without checks
   9701  * Returns:
   9702  *      BCM_E_XXX
   9703  */
   9704 int
   9705 _bcm_esw_stk_modid_config_delete(int unit, int modid, int force_delete)
   9706 {
   9707 
   9708     int             old_nports = 0, i = 0;
   9709     soc_info_t      *si = &SOC_INFO(unit);
   9710 
   9711     /* Parameter check */
   9712     if (modid > SOC_MODID_MAX(unit)) {
   9713         return BCM_E_PARAM;
   9714     }
   9715 
   9716     /* Now check if the dual_mod id mode is enable, if it is, the modid
   9717        cannot be a odd, since the modid+1 is always reserved for the second
   9718        set of ports */
   9719     if((NUM_MODID(unit) > 1) && ((modid%2) != 0)) {
   9720         return BCM_E_PARAM;
   9721     }
   9722 
   9723     /* Check if the modid passed in is configured, if it is not
   9724        return error */
   9725     if (src_modid_base_index_bk[unit]->num_ports[modid] <= 0) {
   9726         return BCM_E_NOT_FOUND;
   9727     }
   9728 
   9729     /* Get the index of the CoE array where this mod lives */
   9730     for (i=0; i<si->num_coe_modules; i++) {
   9731         if (src_modid_base_index_bk[unit]->coe_module_id_list[i] ==
   9732             modid) {
   9733             break;
   9734         }
   9735     }
   9736 
   9737     /* No such module configued, send back an error */
   9738     if (i == si->num_coe_modules) {
   9739         return BCM_E_PARAM;
   9740     }
   9741 
   9742 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   9743     if (soc_feature(unit, soc_feature_hgproxy_subtag_coe)) {
   9744 
   9745         /* Program the relevant registers */
   9746         _bcm_esw_stk_update_mod_config_by_type(unit, BCM_MODID_TYPE_COE,
   9747                                                i+1, modid, 0, 0);
   9748     }
   9749 #endif
   9750 
   9751 #if defined(BCM_KATANA2_SUPPORT)
   9752     if (si->coe_stacking_mode) {
   9753         uint8 mod_cfg = 0;
   9754 
   9755         /* If the 'force_delete' flag is not set, check that the
   9756            previous modules are already deleted, this is because
   9757            the module are allocated in a sequence */
   9758         if(!force_delete) {
   9759             /* Based on the current mod_index, gather modports already
   9760                configured, prior to this index */
   9761             BCM_IF_ERROR_RETURN(_bcm_stk_index_based_mod_cfg_check(unit,
   9762                                                        (i+1), &mod_cfg));
   9763             if(mod_cfg) {
   9764                 return BCM_E_CONFIG;
   9765             }
   9766         }
   9767 
   9768         /* Delete the CoE module info */
   9769         BCM_IF_ERROR_RETURN(bcm_kt2_modid_set(unit, (i+1), 0, 0 /* Not-valid */,
   9770                                               0));
   9771     }
   9772 #endif
   9773 
   9774     /* Get the number of ports for this mod id */
   9775     old_nports = src_modid_base_index_bk[unit]->num_ports[modid];
   9776 
   9777     /* Free the range of modports allocated */
   9778     BCM_IF_ERROR_RETURN
   9779         (_src_modid_base_index_free(unit, modid, old_nports));
   9780 
   9781     /* Reset the number of ports */
   9782     src_modid_base_index_bk[unit]->num_ports[modid] = 0;
   9783 
   9784     /* Record the fact that we this entry is now available */
   9785     src_modid_base_index_bk[unit]->coe_module_id_list[i] = BCM_MODID_INVALID;
   9786 
   9787     /* Reset the module id type*/
   9788     if (soc_feature(unit, soc_feature_multi_next_hops_on_port)) {
   9789         src_modid_base_index_bk[unit]->module_id_type_list[i] = 0;
   9790     }
   9791 
   9792     return BCM_E_NONE;
   9793 }
   9794 
   9795 #endif /* #if defined(BCM_TRIDENT2PLUS_SUPPORT) || defined(BCM_KATANA2_SUPPORT) */
   9796 
   9797 /*
   9798  * Function:
   9799  *      bcm_esw_stk_modid_config_delete
   9800  * Purpose:
   9801  *      Delete the specific module
   9802  * Parameters:
   9803  *      unit         - SOC unit#
   9804  *      mod_cfg   - (out)the value
   9805  * Returns:
   9806  *      BCM_E_XXX
   9807  */
   9808 int
   9809 bcm_esw_stk_modid_config_delete(int unit,
   9810                                 bcm_stk_modid_config_t *mod_cfg)
   9811 {
   9812 #if defined(BCM_TRIDENT2PLUS_SUPPORT) || defined(BCM_KATANA2_SUPPORT)
   9813     soc_info_t *si = &SOC_INFO(unit);
   9814 #endif /* (BCM_TRIDENT2PLUS_SUPPORT) || defined(BCM_KATANA2_SUPPORT) */
   9815 
   9816     BCM_STK_API_TH3_SUPPORT_CHECK(unit);
   9817 
   9818 #if defined(BCM_TRIDENT2PLUS_SUPPORT) || defined(BCM_KATANA2_SUPPORT)
   9819     /* Parameter check */
   9820     if (mod_cfg == NULL) {
   9821         return BCM_E_PARAM;
   9822     }
   9823 
   9824     switch (mod_cfg->modid_type) {
   9825 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   9826     case bcmStkModidTypeMultiNextHops:
   9827         if (soc_feature(unit, soc_feature_multi_next_hops_on_port)) {
   9828             BCM_IF_ERROR_RETURN
   9829                 (_bcm_esw_stk_modid_range_config_delete(unit, mod_cfg));
   9830         } else {
   9831             return BCM_E_UNAVAIL;
   9832         }
   9833         break;
   9834 #endif
   9835     case bcmStkModidTypeCoe:
   9836         if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) ||
   9837             si->coe_stacking_mode) {
   9838             BCM_IF_ERROR_RETURN
   9839                 (_bcm_esw_stk_modid_config_delete(unit, mod_cfg->modid,
   9840                   0 /* Not a force_delete, since this is not 'delete_all' */));
   9841         } else {
   9842             return BCM_E_UNAVAIL;
   9843         }
   9844         break;
   9845     default:
   9846         return BCM_E_UNAVAIL;
   9847     }
   9848 
   9849     return BCM_E_NONE;
   9850 #endif /* #if defined(BCM_TRIDENT2PLUS_SUPPORT) || defined(BCM_KATANA2_SUPPORT) */
   9851     return BCM_E_UNAVAIL;
   9852 }
   9853 
   9854 /*
   9855  * Function:
   9856  *      bcm_esw_stk_modid_config_delete_all
   9857  * Purpose:
   9858  *      Add a new module
   9859  * Parameters:
   9860  *      unit  - SOC unit#
   9861  *      my_modid - (out)the value
   9862  * Returns:
   9863  *      BCM_E_XXX
   9864  */
   9865 int
   9866 bcm_esw_stk_modid_config_delete_all(int unit)
   9867 {
   9868 #if defined(BCM_TRIDENT2PLUS_SUPPORT) || defined(BCM_KATANA2_SUPPORT)
   9869     soc_info_t *si=&SOC_INFO(unit);
   9870 #endif /* (BCM_TRIDENT2PLUS_SUPPORT) || defined(BCM_KATANA2_SUPPORT) */
   9871 
   9872     BCM_STK_API_TH3_SUPPORT_CHECK(unit);
   9873 
   9874 #if defined(BCM_TRIDENT2PLUS_SUPPORT) || defined(BCM_KATANA2_SUPPORT)
   9875     if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) ||
   9876         si->coe_stacking_mode) {
   9877 
   9878         int i = 0;
   9879 
   9880         /* Check if the current CoE mod list is full */
   9881         for (i=0; i<si->num_coe_modules; i++) {
   9882             if (src_modid_base_index_bk[unit]->coe_module_id_list[i] !=
   9883                 BCM_MODID_INVALID) {
   9884                     BCM_IF_ERROR_RETURN(_bcm_esw_stk_modid_config_delete(unit,
   9885                         src_modid_base_index_bk[unit]->coe_module_id_list[i],
   9886                         1 /* Force_delete, since this is a 'delete_all' */));
   9887             }
   9888         }
   9889 	}
   9890 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   9891     if (soc_feature(unit, soc_feature_multi_next_hops_on_port)) {
   9892         int i = 0;
   9893         bcm_stk_modid_config_t mod_cfg;
   9894         bcm_stk_modid_config_t_init(&mod_cfg);
   9895 
   9896         mod_cfg.modid_type = bcmStkModidTypeMultiNextHops;
   9897         mod_cfg.modid = BCM_MODID_INVALID;
   9898         BCM_IF_ERROR_RETURN
   9899             (_bcm_esw_stk_modid_range_config_delete(unit, &mod_cfg));
   9900 
   9901         for (i = 0; i < si->num_modules; i++) {
   9902             if (src_modid_base_index_bk[unit]->multi_nexthop_module_id_list[i] !=
   9903                 BCM_MODID_INVALID) {
   9904                 mod_cfg.modid_type = bcmStkModidTypeMultiNextHops;
   9905                 mod_cfg.modid =
   9906                     src_modid_base_index_bk[unit]->multi_nexthop_module_id_list[i];
   9907                 BCM_IF_ERROR_RETURN
   9908                     (_bcm_esw_stk_modid_range_config_delete(unit, &mod_cfg));
   9909             }
   9910         }
   9911     }
   9912 #endif
   9913 
   9914     return BCM_E_NONE;
   9915 #endif /* #if defined(BCM_TRIDENT2PLUS_SUPPORT) || defined(BCM_KATANA2_SUPPORT) */
   9916 
   9917     return BCM_E_UNAVAIL;
   9918 }
   9919 
   9920 /*
   9921  * Function:
   9922  *      bcm_esw_stk_modid_config_set
   9923  * Purpose:
   9924  *      Sets a module id
   9925  * Parameters:
   9926  *      unit  - SOC unit#
   9927  *      my_modid - (out)the value
   9928  * Returns:
   9929  *      BCM_E_XXX
   9930  */
   9931 
   9932 int
   9933 bcm_esw_stk_modid_config_set(int unit,
   9934                              bcm_stk_modid_config_t *mod_cfg)
   9935 {
   9936     return BCM_E_UNAVAIL;
   9937 }
   9938 
   9939 #if defined(BCM_TRIDENT2PLUS_SUPPORT) || defined(BCM_KATANA2_SUPPORT)
   9940 /*
   9941  * Function:
   9942  *      _bcm_esw_stk_modid_config_get
   9943  * Purpose:
   9944  *      Get the module config
   9945  * Parameters:
   9946  *      unit          - (IN)SOC unit#
   9947  *      mod_cfg    - (OUT)the module config
   9948  * Returns:
   9949  *      BCM_E_XXX
   9950  */
   9951 int
   9952 _bcm_esw_stk_modid_config_get(int unit,
   9953                              bcm_stk_modid_config_t *mod_cfg)
   9954 {
   9955     int i = 0;
   9956     soc_info_t *si = &SOC_INFO(unit);
   9957 
   9958     /* Parameter check */
   9959     if ((mod_cfg == NULL) ||
   9960         (mod_cfg->modid < 0) ||
   9961         (mod_cfg->modid > SOC_MODID_MAX(unit))) {
   9962             return BCM_E_PARAM;
   9963     }
   9964 
   9965     /* Look for and return details for the mod-id passed in */
   9966     for (i = 0; i < si->num_coe_modules; i++) {
   9967         if (src_modid_base_index_bk[unit]->coe_module_id_list[i] ==
   9968                 mod_cfg->modid) {
   9969             mod_cfg->num_ports =
   9970                     src_modid_base_index_bk[unit]->num_ports[mod_cfg->modid];
   9971             break;
   9972         }
   9973     }
   9974 
   9975     if (i == si->num_coe_modules) {
   9976         return BCM_E_NOT_FOUND;
   9977     }
   9978 
   9979     return BCM_E_NONE;
   9980 }
   9981 
   9982 #endif /* #if defined(BCM_TRIDENT2PLUS_SUPPORT) || defined(BCM_KATANA2_SUPPORT) */
   9983 
   9984 /*
   9985  * Function:
   9986  *      bcm_esw_stk_modid_config_get
   9987  * Purpose:
   9988  *      Get the module config
   9989  * Parameters:
   9990  *      unit  - SOC unit#
   9991  *      my_modid - (out)the value
   9992  * Returns:
   9993  *      BCM_E_XXX
   9994  */
   9995 int
   9996 bcm_esw_stk_modid_config_get(int unit,
   9997                              bcm_stk_modid_config_t *mod_cfg)
   9998 {
   9999 #if defined(BCM_TRIDENT2PLUS_SUPPORT) || defined(BCM_KATANA2_SUPPORT)
  10000     soc_info_t *si=&SOC_INFO(unit);
  10001 #endif /* #if defined(BCM_TRIDENT2PLUS_SUPPORT) || defined(KATANA2_SUPPORT) */
  10002 
  10003     BCM_STK_API_TH3_SUPPORT_CHECK(unit);
  10004 
  10005 #if defined(BCM_TRIDENT2PLUS_SUPPORT) || defined(BCM_KATANA2_SUPPORT)
  10006     /* Parameter check */
  10007     if (mod_cfg == NULL) {
  10008         return BCM_E_PARAM;
  10009     }
  10010 
  10011     switch (mod_cfg->modid_type) {
  10012 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
  10013     case bcmStkModidTypeMultiNextHops:
  10014         if (soc_feature(unit, soc_feature_multi_next_hops_on_port)) {
  10015             BCM_IF_ERROR_RETURN
  10016                 (_bcm_esw_stk_modid_range_config_get(unit, mod_cfg));
  10017         } else {
  10018             return BCM_E_UNAVAIL;
  10019         }
  10020         break;
  10021 #endif
  10022     case bcmStkModidTypeCoe:
  10023         if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) ||
  10024             si->coe_stacking_mode) {
  10025             BCM_IF_ERROR_RETURN
  10026                 (_bcm_esw_stk_modid_config_get(unit, mod_cfg));
  10027         } else {
  10028             return BCM_E_UNAVAIL;
  10029         }
  10030         break;
  10031     default:
  10032         return BCM_E_UNAVAIL;
  10033     }
  10034 
  10035     return BCM_E_NONE;
  10036 #endif /* #if defined(BCM_TRIDENT2PLUS_SUPPORT) || defined(KATANA2_SUPPORT) */
  10037 
  10038     return BCM_E_UNAVAIL;
  10039 }
  10040 
  10041 #if defined(BCM_TRIDENT2PLUS_SUPPORT) || defined(BCM_KATANA2_SUPPORT)
  10042 
  10043 /*
  10044  * Function:
  10045  *      _bcm_stk_aux_modport_info_get
  10046  * Purpose:
  10047  *      Get module info by type
  10048  * Parameters:
  10049  *      unit  - SOC unit#
  10050  *      type - To identify the type of module
  10051  *      modList - Array that holds the module list
  10052  *      portNum - Number of ports for each of the modules
  10053  *                in the modList
  10054  * Returns:
  10055  *      BCM_E_XXX
  10056  */
  10057 int 
  10058 _bcm_stk_aux_modport_info_get(int unit, uint32 type, 
  10059                               bcm_stk_modid_config_t *modIdInfo)
  10060 {
  10061     if (soc_feature(unit, soc_feature_hgproxy_subtag_coe)) {
  10062         
  10063         int i=0, j=0;
  10064         soc_info_t *si=&SOC_INFO(unit);
  10065 
  10066         /* Make sure the caller has provided a valid type of module */
  10067         if(!(type & BCM_MODID_TYPE_COE)) {
  10068             return BCM_E_INTERNAL;
  10069         }
  10070 
  10071         /* Look for and return details for the mod-id passed in */
  10072         for (i=0; i<si->num_coe_modules; i++) {
  10073             if (src_modid_base_index_bk[unit]->coe_module_id_list[i] !=
  10074                 BCM_MODID_INVALID) {
  10075                     /* Assign the module Id */
  10076                     modIdInfo[j].modid = src_modid_base_index_bk[unit]->
  10077                                         coe_module_id_list[i];
  10078                     /* Assign ports configured on that moduleId */
  10079                     modIdInfo[j].num_ports = src_modid_base_index_bk[unit]->
  10080                                         num_ports[modIdInfo[j].modid];
  10081 
  10082                     /* Increment module counter*/
  10083                     j++;
  10084             }
  10085         }
  10086 	} 
  10087 
  10088     return BCM_E_NONE;
  10089 }
  10090 
  10091 #endif /* #if defined(BCM_TRIDENT2PLUS_SUPPORT) || defined(KATANA2_SUPPORT)*/
  10092 
  10093 /*
  10094  * Function:
  10095  *      bcm_esw_stk_modid_config_get_all
  10096  * Purpose:
  10097  *      Add a new module
  10098  * Parameters:
  10099  *      unit  - SOC unit#
  10100  *      my_modid - (out)the value
  10101  * Returns:
  10102  *      BCM_E_XXX
  10103  */
  10104 int 
  10105 bcm_esw_stk_modid_config_get_all(int unit, 
  10106                                  int modid_max, 
  10107                                  bcm_stk_modid_config_t *modid_array,
  10108                                  int *modid_count)
  10109 {
  10110 #if defined(BCM_TRIDENT2PLUS_SUPPORT) || defined(BCM_KATANA2_SUPPORT)
  10111     soc_info_t *si=&SOC_INFO(unit);
  10112 #endif /* #if BCM_TRIDENT2PLUS_SUPPORT  || defined(BCM_KATANA2_SUPPORT) */
  10113 
  10114     BCM_STK_API_TH3_SUPPORT_CHECK(unit);
  10115 
  10116 #if defined(BCM_TRIDENT2PLUS_SUPPORT) || defined(BCM_KATANA2_SUPPORT)
  10117     if(modid_count) {
  10118         *modid_count = 0;
  10119     } else {
  10120         return BCM_E_PARAM;
  10121     }
  10122 
  10123 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
  10124     if (soc_feature(unit, soc_feature_multi_next_hops_on_port)) {
  10125         int i = 0;
  10126         bcm_stk_modid_config_t mod_cfg;
  10127         mod_cfg.modid_type = bcmStkModidTypeMultiNextHops;
  10128         mod_cfg.modid = BCM_MODID_INVALID;
  10129         BCM_IF_ERROR_RETURN
  10130             (bcm_esw_stk_modid_config_get(unit, &mod_cfg));
  10131         if (mod_cfg.modid != BCM_MODID_INVALID) {
  10132             if(modid_max == 0) {
  10133                 (*modid_count)++;
  10134             } else {
  10135                 if(modid_max && modid_array) {
  10136                     modid_array[*modid_count].modid = mod_cfg.modid;
  10137                     modid_array[*modid_count].num_mods = mod_cfg.num_mods;
  10138                     modid_array[*modid_count].modid_type = bcmStkModidTypeMultiNextHops;
  10139                     modid_array[*modid_count].num_ports = 0;
  10140 
  10141                     /* Keep incrementing the number of modules processed */
  10142                     (*modid_count)++;
  10143                     /* Keep decrementing the number of mods requested */
  10144                     if(modid_max > 0) {
  10145                         --modid_max;
  10146                     }
  10147                 }
  10148             }
  10149         }
  10150 
  10151         /* If the 'modid_max' is 0, the user only wants to get a count of modIds */
  10152         if(modid_max == 0) {
  10153             for (i = 0; i < si->num_modules; i++) {
  10154                 if (src_modid_base_index_bk[unit]->multi_nexthop_module_id_list[i] !=
  10155                     BCM_MODID_INVALID) {
  10156                     /* Keep incrementing the number of modules processed */
  10157                     (*modid_count)++;
  10158                 }
  10159             }
  10160         } else {
  10161             /* Run through the CoE mod list and fill in needed data */
  10162             for (i = 0; i < si->num_modules; i++) {
  10163                 if (src_modid_base_index_bk[unit]->multi_nexthop_module_id_list[i] ==
  10164                     BCM_MODID_INVALID) {
  10165                     continue;
  10166                 }
  10167 
  10168                 /* Fill in the modid data if the modid_max is non-zero and the
  10169                  *data place holder is allocated
  10170                  */
  10171                 if(modid_max && modid_array) {
  10172                     modid_array[*modid_count].modid =
  10173                         src_modid_base_index_bk[unit]->multi_nexthop_module_id_list[i];
  10174                     modid_array[*modid_count].num_ports =
  10175                         src_modid_base_index_bk[unit]->num_ports[modid_array[*modid_count].modid];
  10176                     modid_array[*modid_count].modid_type =
  10177                         bcmStkModidTypeMultiNextHops;
  10178                     modid_array[*modid_count].num_mods = 1;
  10179 
  10180                     /* Keep incrementing the number of modules processed */
  10181                     (*modid_count)++;
  10182                     /* Keep decrementing the number of mods requested */
  10183                     if(modid_max > 0) {
  10184                         --modid_max;
  10185                     }
  10186                 }
  10187             }
  10188         }
  10189     }
  10190 #endif
  10191 
  10192     if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) ||
  10193         si->coe_stacking_mode) {
  10194 
  10195         int i = 0;
  10196         /* If the 'modid_max' is 0, the user only wants to get a count of modIds */
  10197         if(modid_max == 0) {
  10198             for (i=0; i<si->num_coe_modules; i++) {
  10199                 if (src_modid_base_index_bk[unit]->coe_module_id_list[i] !=
  10200                     BCM_MODID_INVALID) {
  10201                     /* Keep incrementing the number of modules processed */
  10202                     (*modid_count)++;
  10203                 }
  10204             }
  10205             return BCM_E_NONE;
  10206         }
  10207 
  10208         /* Run through the CoE mod list and fill in needed data */
  10209         for (i=0; i<si->num_coe_modules; i++) {
  10210             if (src_modid_base_index_bk[unit]->coe_module_id_list[i] !=
  10211                 BCM_MODID_INVALID) {
  10212 
  10213                     /* Fill in the modid data if the modid_max is non-zero and the
  10214                        data place holder is allocated */
  10215                     if(modid_max && modid_array) {
  10216                         modid_array[*modid_count].modid = src_modid_base_index_bk[unit]->
  10217                                                 coe_module_id_list[i];
  10218                         modid_array[*modid_count].num_ports = src_modid_base_index_bk[unit]->
  10219                                                     num_ports[modid_array[i].modid];
  10220                         modid_array[*modid_count].modid_type = bcmStkModidTypeCoe;
  10221 
  10222                         /* Keep incrementing the number of modules processed */
  10223                         (*modid_count)++;
  10224                         /* Keep decrementing the number of mods requested */
  10225                         if(modid_max > 0) {
  10226                             --modid_max;
  10227                         }
  10228                     }
  10229             }
  10230         }
  10231 	} 
  10232 
  10233     return BCM_E_NONE;
  10234 #endif /* #if BCM_TRIDENT2PLUS_SUPPORT */
  10235 
  10236     return BCM_E_UNAVAIL;
  10237 }
  10238 
  10239 #if defined(BCM_TRIDENT2PLUS_SUPPORT) || defined(BCM_KATANA2_SUPPORT)
  10240 
  10241 int _bcm_stk_aux_modport_valid(int unit, uint32 type, 
  10242                                int modid, bcm_port_t port)
  10243 {
  10244     int num_ports = 0, i = 0;
  10245     soc_info_t *si=&SOC_INFO(unit);
  10246 
  10247     /* Make sure the caller has provided a valid type of module */
  10248     if(!(type & BCM_MODID_TYPE_COE)) {
  10249         return BCM_E_INTERNAL;
  10250     }
  10251 
  10252     for (i=0; i<si->num_coe_modules; i++) {
  10253         /* First check if the modId passed in is one of the CoE modIds */
  10254         if (src_modid_base_index_bk[unit]->coe_module_id_list[i] ==
  10255             modid) {
  10256                 num_ports = src_modid_base_index_bk[unit]->
  10257                                   num_ports[modid];
  10258 
  10259                 /* If the num_ports for the mod is valid, check if
  10260                    the passed in 'port' is within range */
  10261                 if(num_ports <= 0) {
  10262                     return BCM_E_NOT_FOUND;
  10263                 } else if((port >= 0) && (port < num_ports)) {
  10264                     return BCM_E_NONE;
  10265                 }
  10266         }
  10267     }
  10268 
  10269     /* Send back a 'Not_Found' by default */
  10270     return BCM_E_NOT_FOUND;
  10271 }
  10272 
  10273 int _bcm_stk_aux_mod_valid(int unit, uint32 type, int modid)
  10274 {
  10275     int i = 0;
  10276     soc_info_t *si=&SOC_INFO(unit);
  10277 
  10278     /* Make sure the caller has provided a valid type of module */
  10279     if(!(type & BCM_MODID_TYPE_COE)) {
  10280         return BCM_E_INTERNAL;
  10281     }
  10282 
  10283     for (i=0; i<si->num_coe_modules; i++) {
  10284         /* First check if the modId passed in is one of the CoE modIds */
  10285         if (src_modid_base_index_bk[unit]->coe_module_id_list[i] ==
  10286             modid) {
  10287             return BCM_E_NONE;
  10288         }
  10289     }
  10290 
  10291     if(i == si->num_coe_modules) {
  10292         return BCM_E_NOT_FOUND;
  10293     }
  10294 
  10295     /* Send back a 'Not_Found' by default */
  10296     return BCM_E_NOT_FOUND;
  10297 }
  10298 
  10299 #endif /* #if defined(BCM_TRIDENT2PLUS_SUPPORT) || defined(KATANA2_SUPPORT) */
  10300 
  10301 /*
  10302  * Function:
  10303  *     bcm_esw_stk_module_control_set
  10304  * Purpose:
  10305  *     Set module controls.
  10306  * Parameters:
  10307  *     unit - Device unit number
  10308  *     flags - Flags with options
  10309  *     module - The module on which the contrl needs to be set
  10310  *     control - The actual control to be set
  10311  *     arg - The value for the control to be set
  10312  * Returns:
  10313  *     None
  10314  */
  10315 
  10316 int
  10317 bcm_esw_stk_module_control_set(int unit,
  10318                                    uint32 flags,
  10319                                    bcm_module_t module,
  10320                                    bcm_stk_module_control_t control,
  10321                                    int arg)
  10322 {
  10323 
  10324     int rv = BCM_E_UNAVAIL;
  10325 
  10326     if (soc_feature(unit, soc_feature_hg_proxy_module_config)) {
  10327 
  10328         soc_info_t *si = &SOC_INFO(unit);
  10329         source_mod_proxy_table_entry_t source_mod_proxy_entry;
  10330         soc_mem_t mem = SOURCE_MOD_PROXY_TABLEm;
  10331         int rv;
  10332 
  10333         /* The only supported control currently is
  10334            'bcmStkModuleMHPriorityUse' */
  10335         if (control != bcmStkModuleMHPriorityUse) {
  10336             return BCM_E_UNAVAIL;
  10337         }
  10338 
  10339         /* Ensure the module is within range */
  10340         if ((module < 0) || (module > si->modid_max)) {
  10341             return BCM_E_PARAM;
  10342         }
  10343 
  10344         /* Ensure the arg is no greater than '1' */
  10345         if ((arg < 0) || (arg > 1)) {
  10346             return BCM_E_PARAM;
  10347         }
  10348 
  10349         /* Get the mem entry and write the desired value */
  10350         rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, module,
  10351                           &source_mod_proxy_entry);
  10352         if (SOC_FAILURE(rv)) {
  10353             LOG_ERROR(BSL_LS_BCM_STK,
  10354                       (BSL_META_U(unit,
  10355                                   "ERROR:SOURCE_MOD_PROXYm read failed\n")));
  10356             return rv;
  10357         }
  10358 
  10359         rv = soc_mem_field32_modify(unit, mem , module, USE_MH_PRIORITYf,
  10360                                     arg);
  10361 
  10362         if (SOC_FAILURE(rv)) {
  10363             LOG_ERROR(BSL_LS_BCM_STK,
  10364                       (BSL_META_U(unit,
  10365                                   "ERROR: MH Priority setting failed"
  10366                                   "for module %d\n"),
  10367                                    module));
  10368             return rv;
  10369         }
  10370 
  10371         return rv;
  10372 
  10373     }
  10374 
  10375     return rv;
  10376 }
  10377 
  10378 /*
  10379  * Function:
  10380  *     bcm_esw_stk_module_control_get
  10381  * Purpose:
  10382  *     Get module controls.
  10383  * Parameters:
  10384  *     unit - Device unit number
  10385  *     flags - Flags with options
  10386  *     module - The module from which the control value needs to be got from
  10387  *     control - The actual control to be retrirved
  10388  *     arg - The value for the control to be set
  10389  * Returns:
  10390  *     None
  10391  */
  10392 
  10393 int
  10394 bcm_esw_stk_module_control_get(int unit,
  10395                                    uint32 flags,
  10396                                    bcm_module_t module,
  10397                                    bcm_stk_module_control_t control,
  10398                                    int *arg)
  10399 {
  10400 
  10401     int rv = BCM_E_UNAVAIL;
  10402 
  10403     if (soc_feature(unit, soc_feature_hg_proxy_module_config)) {
  10404 
  10405         soc_info_t *si = &SOC_INFO(unit);
  10406         source_mod_proxy_table_entry_t source_mod_proxy_entry;
  10407         soc_mem_t mem = SOURCE_MOD_PROXY_TABLEm;
  10408 
  10409         /* The only supported control currently is
  10410            'bcmStkModuleMHPriorityUse' */
  10411         if (control != bcmStkModuleMHPriorityUse) {
  10412             return BCM_E_UNAVAIL;
  10413         }
  10414 
  10415         /* Ensure the module is within range */
  10416         if ((module < 0) || (module > si->modid_max)) {
  10417             return BCM_E_PARAM;
  10418         }
  10419 
  10420         /* Get the mem entry and read the desired field */
  10421         rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, module,
  10422                           &source_mod_proxy_entry);
  10423 
  10424         if (SOC_FAILURE(rv)) {
  10425             LOG_ERROR(BSL_LS_BCM_STK,
  10426                       (BSL_META_U(unit,
  10427                                   "ERROR:SOURCE_MOD_PROXYm read failed"
  10428                                   "for module %d\n"),
  10429                                    module));
  10430             return rv;
  10431         }
  10432 
  10433         *arg = soc_mem_field32_get(unit, mem, &source_mod_proxy_entry,
  10434                                    USE_MH_PRIORITYf);
  10435 
  10436 
  10437         return rv;
  10438 
  10439     }
  10440 
  10441     return rv;
  10442 
  10443 }
  10444 
  10445 
  10446 #ifdef BCM_WARM_BOOT_SUPPORT_SW_DUMP
  10447 /*
  10448  * Function:
  10449  *     _bcm_stk_sw_dump
  10450  * Purpose:
  10451  *     Displays Stack software structure information.
  10452  * Parameters:
  10453  *     unit - Device unit number
  10454  * Returns:
  10455  *     None
  10456  */
  10457 void
  10458 _bcm_stk_sw_dump(int unit)
  10459 {
  10460     char  pfmt[SOC_PBMP_FMT_LEN];
  10461 
  10462     LOG_CLI((BSL_META_U(unit,
  10463                         "\nSW Information Stack - Unit %d\n\n"), unit));
  10464 
  10465     /* Source module id */
  10466     LOG_CLI((BSL_META_U(unit,
  10467                         "  Source Module Id: %d\n\n"), SOC_BASE_MODID(unit)));
  10468 
  10469     /* Stack port bitmaps */
  10470     LOG_CLI((BSL_META_U(unit,
  10471                         "  Stack Ports\n")));
  10472     LOG_CLI((BSL_META_U(unit,
  10473                         "      Current :  %s\n"),
  10474              SOC_PBMP_FMT(SOC_PBMP_STACK_CURRENT(unit), pfmt)));
  10475     LOG_CLI((BSL_META_U(unit,
  10476                         "      Inactive:  %s\n"),
  10477              SOC_PBMP_FMT(SOC_PBMP_STACK_INACTIVE(unit), pfmt)));
  10478     LOG_CLI((BSL_META_U(unit,
  10479                         "      Previous:  %s\n"),
  10480              SOC_PBMP_FMT(SOC_PBMP_STACK_PREVIOUS(unit), pfmt)));
  10481     LOG_CLI((BSL_META_U(unit,
  10482                         "\n")));
  10483 
  10484 #if defined(BCM_TRX_SUPPORT)
  10485     /* Modport profile */
  10486     /* Display those entries with reference count > 0 */
  10487     if (modport_profile[unit] != NULL) {
  10488         int     i;
  10489         int     num_entries;
  10490         int     ref_count;
  10491         int     entries_per_set;
  10492         int     modid_count;
  10493         uint32  index;
  10494         pbmp_t  hg_pbmp;
  10495         modport_map_entry_t    *entry_p;
  10496         int dest_is_hg_pbmp = 0;
  10497         int p;
  10498         int profile_index;
  10499         bcmi_trx_modport_map_profile_t profile;
  10500         int istrunk, dest;
  10501 
  10502         num_entries = soc_mem_index_count
  10503             (unit, modport_profile[unit]->tables[0].mem);
  10504         LOG_CLI((BSL_META_U(unit,
  10505                             "  Stack Modport Profile\n")));
  10506         LOG_CLI((BSL_META_U(unit,
  10507                             "      Number of entries: %d\n"), num_entries));
  10508         LOG_CLI((BSL_META_U(unit,
  10509                             "      Index RefCount EntriesPerSet - "
  10510                  "HIGIG_PORT_BITMAP\n")));
  10511 
  10512        sal_memset(&profile, 0x0, sizeof(profile));
  10513        if (soc_feature(unit, soc_feature_modport_map_dest_is_hg_port_bitmap)) {
  10514            dest_is_hg_pbmp = 1;
  10515        }
  10516 
  10517         modid_count = SOC_MODID_MAX(unit) + 1;
  10518         for (index = 0; index < num_entries; index += modid_count) {
  10519             if (SOC_FAILURE
  10520                 (soc_profile_mem_ref_count_get(unit,
  10521                                                modport_profile[unit],
  10522                                                index, &ref_count))) {
  10523                 break;
  10524             }
  10525 
  10526             if (ref_count <= 0) {
  10527                 continue;
  10528             }
  10529 
  10530             if (dest_is_hg_pbmp) {
  10531                 profile_index = (index / modid_count);
  10532                 profile = TRX_MODPORT_MAP_PROFILE(unit, profile_index);
  10533             }
  10534             for (i = 0; i < modid_count; i++) {
  10535                 entries_per_set =
  10536                     modport_profile[unit]->tables[0].entries[index+i].entries_per_set;
  10537                 LOG_CLI((BSL_META_U(unit,
  10538                                     "     %5d %8d %13d    "),
  10539                          index + i, ref_count, entries_per_set));
  10540 
  10541                 switch (BCM_CHIP_FAMILY(unit)) {
  10542                 case BCM_FAMILY_TRIUMPH:
  10543                 case BCM_FAMILY_TRIUMPH2:
  10544                     entry_p = SOC_PROFILE_MEM_ENTRY(unit,
  10545                                                     modport_profile[unit],
  10546                                                     modport_map_entry_t *,
  10547                                                     index + i);
  10548                     soc_mem_pbmp_field_get(unit, MODPORT_MAPm, entry_p,
  10549                                            HIGIG_PORT_BITMAPf, &hg_pbmp);
  10550                     LOG_CLI((BSL_META_U(unit,
  10551                                         "%s\n"), SOC_PBMP_FMT(hg_pbmp, pfmt)));
  10552 
  10553                     if (dest_is_hg_pbmp) {
  10554                         if (profile.ref_count == 0) {
  10555                             continue;
  10556                         }
  10557                         for (p = 0; p < SOC_MAX_NUM_PORTS; p++) {
  10558                             if (SOC_PORT_VALID(unit, p)) {
  10559                                 istrunk =
  10560                                     profile.entry_array[i].dest_istrunk[p];
  10561                                 dest = profile.entry_array[i].dest[p];
  10562                                 if (dest != 0) {
  10563                                     LOG_CLI((BSL_META_U(unit,
  10564                                                         "dest_istrunk[%d]=%d, "
  10565                                                         "dest[%d]=%d\n"),
  10566                                              p, istrunk, p, dest));
  10567                                 }
  10568                             }
  10569                         }
  10570                     }
  10571                     break;
  10572                 default:
  10573                     BCM_PBMP_CLEAR(hg_pbmp);
  10574                     LOG_CLI((BSL_META_U(unit,
  10575                                         "%s\n"), SOC_PBMP_FMT(hg_pbmp, pfmt)));
  10576                     break;
  10577                 }
  10578             }
  10579         }
  10580     }
  10581 #endif /* BCM_TRX_SUPPORT */
  10582 
  10583 #if defined(BCM_TRIDENT_SUPPORT)
  10584     if (soc_feature(unit, soc_feature_modport_map_dest_is_port_or_trunk)) {
  10585         bcm_td_modport_map_sw_dump(unit);
  10586     }
  10587 #endif /* BCM_TRIDENT_SUPPORT */
  10588 
  10589 #if defined(LOCAL_MODMAP_SUPPORT)
  10590     /* Modmap information */
  10591     if (mod_map_data[unit] != NULL) {
  10592         int  i;
  10593         int  num;
  10594         int  count;
  10595 
  10596         LOG_CLI((BSL_META_U(unit,
  10597                             "\n  Stack Modmap Data\n")));
  10598 
  10599         count = 0;
  10600         num = COUNTOF(mod_map_data[unit]->l_modid);
  10601         LOG_CLI((BSL_META_U(unit,
  10602                             "      l_modid: ")));
  10603         for (i = 0; i < num; i++) {
  10604             if ((count > 0) && (!(count % 10))) {
  10605                 LOG_CLI((BSL_META_U(unit,
  10606                                     "\n               ")));
  10607             }
  10608             LOG_CLI((BSL_META_U(unit,
  10609                                 " %4d"), mod_map_data[unit]->l_modid[i]));
  10610             count++;
  10611         }
  10612         LOG_CLI((BSL_META_U(unit,
  10613                             "\n")));
  10614 
  10615         count = 0;
  10616         num = COUNTOF(mod_map_data[unit]->thresh_d);
  10617         LOG_CLI((BSL_META_U(unit,
  10618                             "      thresh_d:")));
  10619         for (i = 0; i < num; i++) {
  10620             if ((count > 0) && (!(count % 10))) {
  10621                 LOG_CLI((BSL_META_U(unit,
  10622                                     "\n               ")));
  10623             }
  10624             LOG_CLI((BSL_META_U(unit,
  10625                                 " %4d"), mod_map_data[unit]->thresh_d[i]));
  10626             count++;
  10627         }
  10628         LOG_CLI((BSL_META_U(unit,
  10629                             "\n")));
  10630 
  10631         count = 0;
  10632         LOG_CLI((BSL_META_U(unit,
  10633                             "      fmod0:   ")));
  10634         num = COUNTOF(mod_map_data[unit]->fmod0);
  10635         for (i = 0; i < num; i++) {
  10636             if ((count > 0) && (!(count % 10))) {
  10637                 LOG_CLI((BSL_META_U(unit,
  10638                                     "\n               ")));
  10639             }
  10640             LOG_CLI((BSL_META_U(unit,
  10641                                 " %4d"), mod_map_data[unit]->fmod0[i]));
  10642             count++;
  10643         }
  10644         LOG_CLI((BSL_META_U(unit,
  10645                             "\n")));
  10646     }
  10647 #endif  /* MODMAP_SUPPORT */
  10648 
  10649 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_HURRICANE3_SUPPORT)
  10650     if (soc_feature(unit, soc_feature_src_modid_base_index)) {
  10651         int i, rv, base_index;
  10652         source_trunk_map_modbase_entry_t stm_modbase_entry;
  10653 
  10654         LOG_CLI((BSL_META_U(unit,
  10655                             "\n  Stack Source Trunk Map Modbase Data\n")));
  10656 
  10657         for (i = 0; i <= SOC_MODID_MAX(unit) ; i++) {
  10658             rv = READ_SOURCE_TRUNK_MAP_MODBASEm(unit, MEM_BLOCK_ANY, i,
  10659                     &stm_modbase_entry);
  10660             if (SOC_FAILURE(rv)) {
  10661                 continue;
  10662             }
  10663             base_index = soc_SOURCE_TRUNK_MAP_MODBASEm_field32_get(unit,
  10664                     &stm_modbase_entry, BASEf);
  10665             if (src_modid_base_index_bk[unit]->default_base_idx == base_index) {
  10666                 continue;
  10667             }
  10668             LOG_CLI((BSL_META_U(unit,
  10669                                 "    Modid %3d, "), i));
  10670             LOG_CLI((BSL_META_U(unit,
  10671                                 "source trunk map modbase index %4d, "), base_index));
  10672             LOG_CLI((BSL_META_U(unit,
  10673                                 "num_ports %2d\n"),
  10674                      src_modid_base_index_bk[unit]->num_ports[i]));
  10675         }
  10676 
  10677         if (src_modid_base_index_bk[unit]->coe_module_id_list) {
  10678             LOG_CLI((BSL_META_U(unit, "CoE mod list: %3d %3d %3d %3d %3d\n"),
  10679                         src_modid_base_index_bk[unit]->coe_module_id_list[0],
  10680                         src_modid_base_index_bk[unit]->coe_module_id_list[1],
  10681                         src_modid_base_index_bk[unit]->coe_module_id_list[2],
  10682                         src_modid_base_index_bk[unit]->coe_module_id_list[3],
  10683                         src_modid_base_index_bk[unit]->coe_module_id_list[4]));
  10684         }
  10685     }
  10686 #endif /* BCM_TRIDENT_SUPPORT || BCM_HURRICANE3_SUPPORT */
  10687 
  10688 #ifdef BCM_RPC_SUPPORT
  10689 #if defined(BROADCOM_DEBUG)
  10690     bcm_rlink_dump();
  10691     atp_dump(1);
  10692 #endif
  10693 #endif
  10694 
  10695     return;
  10696 }
  10697 #endif /* BCM_WARM_BOOT_SUPPORT_SW_DUMP */
  10698