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

trunk.c (286552B)


      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:    trunk.c
      8  * Purpose: BCM level APIs for trunking (a.k.a. Port Aggregation)
      9  */
     10 
     11 #include <shared/bsl.h>
     12 
     13 #include <soc/drv.h>
     14 #include <soc/scache.h>
     15 #if defined(BCM_BRADLEY_SUPPORT)
     16 #include <soc/bradley.h>
     17 #include <soc/firebolt.h>
     18 #endif /* BCM_BRADLEY_SUPPORT */
     19 
     20 #include <bcm/error.h>
     21 #include <bcm/mirror.h>
     22 #include <bcm/trunk.h>
     23 
     24 #include <bcm_int/api_xlate_port.h>
     25 #include <bcm_int/common/lock.h>
     26 #include <bcm_int/common/multicast.h>
     27 #include <bcm_int/esw/mbcm.h>
     28 #include <bcm_int/esw/trunk.h>
     29 #include <bcm_int/esw/port.h>
     30 #include <bcm_int/esw/mirror.h>
     31 #include <bcm_int/esw/firebolt.h>
     32 #include <bcm_int/esw/stack.h>
     33 #include <bcm_int/esw/switch.h>
     34 #include <bcm_int/esw/trident.h>
     35 #include <bcm_int/esw/trident2.h>
     36 #ifdef BCM_KATANA2_SUPPORT
     37 #include <bcm_int/esw/katana2.h>
     38 #endif /* BCM_KATANA2_SUPPORT */
     39 #ifdef BCM_TOMAHAWK3_SUPPORT
     40 #include <soc/tomahawk3.h>
     41 #endif /* BCM_TOMAHAWK3_SUPPORT */
     42 #ifdef BCM_HGPROXY_COE_SUPPORT
     43 #include <bcm_int/esw/xgs5.h>
     44 #endif /* BCM_HGPROXY_COE_SUPPORT */
     45 #if defined(BCM_SABER2_SUPPORT)
     46 #include <soc/saber2.h>
     47 #endif /* BCM_SABER2_SUPPORT */
     48 
     49 #include <bcm_int/esw_dispatch.h>
     50 #include <bcm_int/esw/switch.h>
     51 
     52 #ifdef BCM_WARM_BOOT_SUPPORT
     53 #include <bcm/types.h>
     54 #endif /* BCM_WARM_BOOT_SUPPORT */
     55 
     56 
     57 typedef struct trunk_cntl_s {
     58     int                ngroups_fp;  /* number of (front panel) trunk groups */
     59     int                nports_fp;   /* max ports per trunk group */
     60     int                ngroups_hg;  /* number of fabric trunk groups */
     61     int                nports_hg;   /* max ports per fabric trunk group */
     62 #ifdef BCM_APACHE_SUPPORT
     63     int              ngroups_rr_fp; /* number of fp trunks supporting Round Robin Load balancing */
     64     SHR_BITDCL      *fp_rr_lag_bmp; /* FP RoundRobin Lag usage bitmap */
     65 #endif /* BCM_APACHE_SUPPORT */
     66     trunk_private_t   *t_info;
     67     sal_mutex_t        lock;        /* Trunk module lock. */
     68 #ifdef BCM_WARM_BOOT_SUPPORT
     69     SHR_BITDCL  *trunk_bmp_ptr;     /* Warm Boot trunk use bitmap */
     70     int         trunk_bmp_alloc;    /* WB trunk use allocation */
     71     uint8       *fp_hwf_flags;      /* WB FP - HW failover flags record */
     72     int         fp_hwf_alloc;       /* WB FP - HW failover allocation */
     73     uint8       *hg_hwf_flags;      /* WB HG - HW failover flags record */
     74     int         hg_hwf_alloc;       /* WB HG - HW failover allocation */
     75 #endif /* BCM_WARM_BOOT_SUPPORT */
     76 } trunk_cntl_t;
     77 
     78 /*
     79  * One trunk control entry for each SOC device containing trunk book keeping
     80  * info for that device.
     81  */
     82 static trunk_cntl_t bcm_trunk_control[BCM_MAX_NUM_UNITS];
     83 
     84 #define TRUNK_CNTL(unit)	bcm_trunk_control[unit]
     85 #define TRUNK_INFO(unit, tid)	bcm_trunk_control[unit].t_info[tid]
     86 
     87 /*
     88  * Cause a routine to return BCM_E_INIT if trunking subsystem is not
     89  * initialized.
     90  */
     91 
     92 #define TRUNK_INIT(unit)	                    \
     93 	if ( (TRUNK_CNTL(unit).ngroups_fp <= 0) && \
     94 	     (TRUNK_CNTL(unit).ngroups_hg <= 0) ) { return BCM_E_INIT; }
     95 
     96 #define TRUNK_NUM_GROUPS(unit) \
     97         (TRUNK_CNTL(unit).ngroups_fp + TRUNK_CNTL(unit).ngroups_hg)
     98 
     99 /*
    100  * Make sure TID is within valid range.
    101  */
    102 
    103 #define TRUNK_CHECK(unit, tid) \
    104 	if ((tid) < 0 || (tid) >= TRUNK_NUM_GROUPS(unit)) \
    105            { return BCM_E_PARAM; }
    106 
    107 #define TRUNK_FP_TID(unit, tid) \
    108     ( ((tid) >= 0) && ((tid) < TRUNK_CNTL(unit).ngroups_fp) )
    109 
    110 #define TRUNK_FABRIC_TID(unit, tid)             \
    111     ( ((tid) >= TRUNK_CNTL(unit).ngroups_fp) && \
    112       ((tid) < TRUNK_NUM_GROUPS(unit)) )
    113 
    114 /*
    115  * Function:
    116  *	_bcm_esw_trunk_gport_construct
    117  * Purpose:
    118  *	Converts ports and modules given in t_data structure into gports
    119  * Parameters:
    120  *      unit - StrataSwitch PCI device unit number (driver internal).
    121  *      fabric_trunk - trunk is a fabric trunk
    122  *      count - number of failover gports in list
    123  *      port_list - (IN) list of port numbers
    124  *      modid_list - (IN) list of module ids
    125  *      port_array - (OUT) list of gports to return
    126  *
    127  * Note:
    128  *      port_list and port_array may be the same list.  This updates
    129  *      the list in place.
    130  */
    131 int
    132 _bcm_esw_trunk_gport_construct(int unit, int fabric_trunk, int count,
    133                                bcm_port_t *port_list,
    134                                bcm_module_t *modid_list,
    135                                bcm_gport_t *port_array)
    136 {
    137     bcm_gport_t         gport;
    138     int                 i, mod_is_local;
    139     _bcm_gport_dest_t   dest;
    140     bcm_module_t        base_modid;
    141     bcm_port_t          local_port;
    142 #if defined(BCM_KATANA2_SUPPORT)
    143     int                 local_subport = 0, pp_port = 0;
    144 #endif
    145 
    146     _bcm_gport_dest_t_init(&dest);
    147     
    148     for (i = 0; i < count; i++) {
    149         gport = 0;
    150         /* Stacking ports should be encoded as devport */
    151         if (fabric_trunk) {
    152             /* Error checking during set functions should guarantee that
    153              * stack ports iff fabric trunks */
    154             dest.gport_type = _SHR_GPORT_TYPE_DEVPORT;
    155             BCM_IF_ERROR_RETURN
    156                 (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_SET, modid_list[i],
    157                                         port_list[i], &dest.modid, &dest.port));
    158             BCM_IF_ERROR_RETURN(
    159                     _bcm_esw_gport_construct(unit, &dest, &gport));
    160         } else {
    161             dest.gport_type = _SHR_GPORT_TYPE_MODPORT;
    162             dest.modid = modid_list[i];
    163             dest.port = port_list[i];
    164 #if defined(BCM_KATANA2_SUPPORT)
    165             BCM_IF_ERROR_RETURN(_bcm_kt2_modport_is_local_coe_subport(unit,
    166                                     dest.modid, dest.port, &local_subport));
    167             if (local_subport) {
    168                  BCM_IF_ERROR_RETURN(_bcm_kt2_modport_to_pp_port_get(unit,
    169                                         dest.modid, dest.port, &pp_port)); 
    170 
    171                 /* construct LinkPHY/SubportPkttag subport gport */
    172                 _BCM_KT2_SUBPORT_PORT_ID_SET(gport, pp_port);
    173                 if (BCM_PBMP_MEMBER(
    174                     SOC_INFO(unit).linkphy_pp_port_pbm, pp_port)) {
    175                     _BCM_KT2_SUBPORT_PORT_TYPE_SET(gport,
    176                         _BCM_KT2_SUBPORT_TYPE_LINKPHY);
    177                 } else if (BCM_PBMP_MEMBER(
    178                     SOC_INFO(unit).subtag_pp_port_pbm, pp_port)) {
    179                     _BCM_KT2_SUBPORT_PORT_TYPE_SET(gport,
    180                         _BCM_KT2_SUBPORT_TYPE_SUBTAG);
    181                 } else {
    182                     return BCM_E_PARAM;
    183                 }
    184             } else
    185 #endif
    186             {
    187 #ifdef BCM_HGPROXY_COE_SUPPORT
    188                 if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) &&
    189                     _bcm_xgs5_subport_coe_mod_port_local(
    190                         unit, dest.modid, dest.port)) {
    191                 } else
    192 #endif
    193                 {
    194                     BCM_IF_ERROR_RETURN
    195                         (_bcm_esw_modid_is_local(unit, modid_list[i],
    196                                                  &mod_is_local));
    197                     if (mod_is_local) {
    198                         BCM_IF_ERROR_RETURN
    199                             (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_SET,
    200                                                      modid_list[i], port_list[i],
    201                                                      &base_modid, &local_port));
    202                         if (IS_ST_PORT(unit, local_port)) {
    203                             dest.gport_type = _SHR_GPORT_TYPE_DEVPORT;
    204                             dest.modid = base_modid;
    205                             dest.port = local_port;
    206                         }
    207                     }
    208                 }
    209                 BCM_IF_ERROR_RETURN(
    210                     _bcm_esw_gport_construct(unit, &dest, &gport));
    211             }
    212         }
    213         port_array[i] = gport;
    214     }
    215 
    216     return BCM_E_NONE;
    217 }
    218 
    219 /*
    220  * Function:
    221  *	_bcm_esw_trunk_gport_array_resolve
    222  * Purpose:
    223  *	Converts gports list into ports and modules
    224  * Parameters:
    225  *      unit - StrataSwitch PCI device unit number (driver internal).
    226  *      fabric_trunk - trunk is a fabric trunk
    227  *      count - number of failover gports in list
    228  *      port_array - (IN) list of gports
    229  *      port_list - (OUT) list of port numbers to return
    230  *      modid_list - (OUT) list of module ids to return
    231  *
    232  * Note:
    233  *      port_list and port_array may be the same list.  This updates
    234  *      the list in place.
    235  */
    236 int
    237 _bcm_esw_trunk_gport_array_resolve(int unit, int fabric_trunk, int count,
    238                                    bcm_gport_t *port_array,
    239                                    bcm_port_t *port_list,
    240                                    bcm_module_t *modid_list)
    241                              
    242 {
    243     bcm_port_t      port;
    244     bcm_module_t    modid, local_modid;
    245     bcm_trunk_t     tgid;
    246     int             i, id, rv;
    247 
    248     rv = bcm_esw_stk_my_modid_get(unit, &local_modid);
    249     if (BCM_FAILURE(rv) && !SOC_IS_XGS_FABRIC(unit) ) {
    250         return (rv);
    251     }
    252 
    253     for (i = 0; i < count; i++) {
    254         if (BCM_GPORT_IS_SET(port_array[i])) {
    255             if (fabric_trunk) {
    256                 /* Must be local */
    257                 BCM_IF_ERROR_RETURN
    258                     (bcm_esw_port_local_get(unit, port_array[i], &port));
    259 #if defined(BCM_HGPROXY_COE_SUPPORT)
    260                 /*Cascaded port*/
    261                 if (IS_SUBTAG_PORT(unit, port)
    262                     && soc_feature(unit, soc_feature_hgproxy_subtag_coe)) {
    263                     BCM_IF_ERROR_RETURN
    264                         (_bcm_esw_gport_resolve(unit, port_array[i],
    265                                                 &modid, &port, &tgid, &id));
    266                     port_list[i] = port;
    267                     modid_list[i] = modid;
    268                 } else 
    269 #endif
    270                 {
    271                     port_list[i] = port;
    272                     modid_list[i] = -1;
    273                 }
    274             } else {
    275                 BCM_IF_ERROR_RETURN
    276                     (_bcm_esw_gport_resolve(unit, port_array[i],
    277                                             &modid, &port, &tgid, &id));
    278 
    279 #if defined(BCM_HGPROXY_COE_SUPPORT)
    280                 if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) &&
    281                     _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port_array[i])) {
    282                             id = -1;
    283                 } else
    284 #endif
    285 
    286 #if defined(BCM_KATANA2_SUPPORT)
    287                 if (_BCM_KT2_GPORT_IS_LINKPHY_OR_SUBTAG_SUBPORT_GPORT(unit,
    288                     port_array[i])) {
    289                     id = -1;
    290                 }
    291 #endif
    292                 if ((-1 != tgid) || (-1 != id)) {
    293                     return BCM_E_PARAM;
    294                 }
    295                 port_list[i] = port;
    296                 modid_list[i] = modid;
    297             }
    298         } else {
    299             if (fabric_trunk) {
    300                 if (SOC_PORT_VALID(unit, port_array[i])) {
    301                     port_list[i] = port_array[i];
    302                     modid_list[i] = -1;
    303                 } else {
    304                     return BCM_E_PORT;
    305                 }
    306             } else {
    307                 PORT_DUALMODID_VALID(unit, port_array[i]);
    308                 if (port_array != port_list) {
    309                     port_list[i] = port_array[i];
    310                     modid_list[i] = local_modid;
    311                 }
    312             }
    313         }
    314     }
    315 
    316     return BCM_E_NONE;
    317 }
    318 
    319 /*
    320  * Function:
    321  *	_bcm_esw_trunk_port_property_get
    322  * Purpose:
    323  *	Determines whether a system port is part of a trunk
    324  * Parameters:
    325  *      unit - StrataSwitch PCI device unit number (driver internal).
    326  *      modid  - Module id.
    327  *      port   - Port number.
    328  *      tid - (OUT) Trunk ID if trunk member.
    329  * Notes:
    330  *      Currently used only by RX module, gport support not required.
    331  */
    332 int
    333 _bcm_esw_trunk_port_property_get(int unit,
    334                                  bcm_module_t modid,
    335                                  bcm_port_t port,
    336                                  int *tid)
    337 {
    338 #if defined(BCM_TRIDENT_SUPPORT)
    339     if (soc_feature(unit, soc_feature_shared_trunk_member_table)) {
    340         return _bcm_trident_trunk_get_port_property(unit, modid, port, tid);
    341     }
    342 #if defined(BCM_TOMAHAWK3_SUPPORT)
    343     if (SOC_IS_TOMAHAWK3(unit)) {
    344         return _bcm_th3_trunk_get_port_property(unit, port, tid);
    345     }
    346 #endif
    347 #endif
    348 #if defined(BCM_FIREBOLT_SUPPORT)
    349     if (SOC_IS_XGS_SWITCH(unit)) {
    350         return _bcm_xgs3_trunk_get_port_property(unit, modid, port, tid);
    351     }
    352 #endif
    353     return BCM_E_UNAVAIL;
    354 }
    355 
    356 /*
    357  * Function:
    358  *	_bcm_esw_trunk_active_member_get
    359  * Purpose:
    360  *      Returns active port information for a given trunk.
    361  *      Returns only the members on which EGRESS_DISABLE is not set.
    362  * Parameters:
    363  *      unit   - StrataSwitch PCI device unit number (driver internal).
    364  *      tid    - Trunk ID.
    365  *      trunk_info   - (OUT) Place to store returned trunk info.
    366  *      member_max   - (IN) Size of member_array.
    367  *      active_member_array - (OUT) Place to store returned active trunk 
    368  *                                  members.
    369  *      active_member_count - (OUT) Place to store returned number of active
    370  *                                  trunk members.
    371  * Returns:
    372  *      BCM_E_NONE              Success.
    373  *      BCM_E_XXX
    374  */
    375 int
    376 _bcm_esw_trunk_active_member_get(int unit, bcm_trunk_t tid, 
    377                                  bcm_trunk_info_t *trunk_info,
    378                                  int member_max, 
    379                                  bcm_trunk_member_t *active_member_array,
    380                                  int *active_member_count)
    381 {
    382     int                  rv = BCM_E_NONE;
    383     int                  member_count;
    384     bcm_trunk_member_t   member_array[BCM_SWITCH_TRUNK_MAX_PORTCNT];
    385     int                  filled_count = 0;
    386 
    387     if ((member_max > 0) && (NULL == active_member_array)) {
    388         return BCM_E_PARAM;
    389     }
    390 
    391     if ((member_max > 0) && (NULL == active_member_count)) {
    392         return BCM_E_PARAM;
    393     }
    394 
    395     BCM_IF_ERROR_RETURN
    396         (bcm_esw_trunk_get(unit, tid, NULL, BCM_SWITCH_TRUNK_MAX_PORTCNT, 
    397                            member_array, &member_count));
    398 
    399     if (0 < member_count) {
    400         int i;
    401         if (active_member_array != NULL) {
    402             sal_memset(active_member_array, 0, 
    403                        sizeof(bcm_trunk_member_t) * member_max);
    404         }
    405 
    406         *active_member_count = 0;
    407 
    408         /* Get only the active member ports */
    409         for (i = 0; i < member_count; i++) {
    410              if (!(member_array[i].flags & BCM_TRUNK_MEMBER_EGRESS_DISABLE)) {
    411                  if ( (active_member_array != NULL) && (member_max > 0) ) {
    412                      sal_memcpy(&active_member_array[*active_member_count], 
    413                                 &member_array[i], sizeof(member_array[i]));
    414                      filled_count++;
    415                  }
    416                  (*active_member_count)++;
    417 
    418                  if ( (member_max > 0) && (filled_count == member_max) ) {
    419                      break;
    420                  }
    421              }
    422         }
    423     }
    424  
    425     return rv;
    426 }
    427 
    428 /*
    429  * Function:
    430  *	_bcm_esw_trunk_rtag_get
    431  * Purpose:
    432  *	Retrieve the RTAG HW value of a trunk
    433  * Parameters:
    434  *      unit - StrataSwitch PCI device unit number (driver internal).
    435  *      tid - Trunk ID.
    436  *      rtag - (OUT) HW RTAG value for trunk.
    437  * Notes:
    438  *      Currently used by mirror module
    439  */
    440 int
    441 _bcm_esw_trunk_rtag_get(int unit,  bcm_trunk_t tid, int *rtag)
    442 
    443 {
    444     trunk_private_t *t_info;
    445 
    446     if (NULL == rtag) {
    447         return BCM_E_PARAM;
    448     }
    449 
    450     TRUNK_CHECK(unit, tid);
    451 
    452     t_info = &TRUNK_INFO(unit, tid);
    453 
    454     if (t_info->tid == BCM_TRUNK_INVALID) {
    455         return BCM_E_NOT_FOUND;
    456     }
    457 
    458     *rtag = t_info->rtag;
    459     return BCM_E_NONE;
    460 }
    461 
    462 /*
    463  * Function:
    464  *	bcm_trunk_deinit
    465  * Purpose:
    466  *	Release allocated trunk data structures.
    467  * Parameters:
    468  *      unit - StrataSwitch PCI device unit number (driver internal).
    469  * Returns:
    470  *      BCM_E_NONE              Success.
    471  *      BCM_E_XXX
    472  */
    473 void
    474 _bcm_esw_trunk_deinit(int unit)
    475 {
    476 #if defined(BCM_XGS3_SWITCH_SUPPORT)
    477     if (SOC_IS_XGS3_SWITCH(unit)) {
    478 #if defined(BCM_TRIDENT_SUPPORT)
    479         if (soc_feature(unit, soc_feature_shared_trunk_member_table)) {
    480             _bcm_trident_trunk_deinit(unit);
    481         } else
    482 #endif /* BCM_TRIDENT_SUPPORT */
    483         {
    484             _bcm_xgs3_trunk_member_detach(unit);
    485             _bcm_xgs3_trunk_swfailover_detach(unit);
    486             _bcm_xgs3_trunk_mod_port_map_deinit(unit);
    487 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT)
    488             _bcm_xgs3_trunk_hwfailover_detach(unit);
    489 #endif /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */
    490         }
    491 
    492 #ifdef BCM_APACHE_SUPPORT
    493         if (soc_feature(unit, soc_feature_apache_round_robin_fp_lag)) {
    494             if (NULL != TRUNK_CNTL(unit).fp_rr_lag_bmp) {
    495                 sal_free(TRUNK_CNTL(unit).fp_rr_lag_bmp);
    496                 TRUNK_CNTL(unit).fp_rr_lag_bmp = NULL;
    497             }
    498         }
    499 #endif /* BCM_APACHE_SUPPORT */
    500 
    501 #ifdef BCM_WARM_BOOT_SUPPORT
    502         if (NULL != TRUNK_CNTL(unit).trunk_bmp_ptr) {
    503             sal_free(TRUNK_CNTL(unit).trunk_bmp_ptr);
    504             TRUNK_CNTL(unit).trunk_bmp_ptr = NULL;
    505         }
    506         if (NULL != TRUNK_CNTL(unit).fp_hwf_flags) {
    507             sal_free(TRUNK_CNTL(unit).fp_hwf_flags);
    508             TRUNK_CNTL(unit).fp_hwf_flags = NULL;
    509         }
    510         if (NULL != TRUNK_CNTL(unit).hg_hwf_flags) {
    511             sal_free(TRUNK_CNTL(unit).hg_hwf_flags);
    512             TRUNK_CNTL(unit).hg_hwf_flags = NULL;
    513         }
    514 #endif /* BCM_WARM_BOOT_SUPPORT */
    515 
    516 #if defined(BCM_TRIDENT2_SUPPORT) && defined(INCLUDE_L3)
    517     if (soc_feature(unit, soc_feature_vp_lag)) {
    518         bcm_td2_vp_lag_deinit(unit);
    519     }
    520 #endif /* BCM_TRIDENT2_SUPPORT && INCLUDE_L3 */
    521 
    522     }
    523 #endif /* BCM_XGS3_SWITCH_SUPPORT */
    524 }
    525 
    526 #ifdef BCM_WARM_BOOT_SUPPORT
    527 
    528 #define BCM_WB_VERSION_1_0                SOC_SCACHE_VERSION(1,0)
    529 #define BCM_WB_VERSION_1_1                SOC_SCACHE_VERSION(1,1)
    530 #define BCM_WB_VERSION_1_2                SOC_SCACHE_VERSION(1,2)
    531 #define BCM_WB_VERSION_1_3                SOC_SCACHE_VERSION(1,3)
    532 #define BCM_WB_VERSION_1_4                SOC_SCACHE_VERSION(1,4)
    533 #define BCM_WB_VERSION_1_5                SOC_SCACHE_VERSION(1,5)
    534 #define BCM_WB_VERSION_1_6                SOC_SCACHE_VERSION(1,6)
    535 /*add dlf_index to scache*/
    536 #define BCM_WB_VERSION_1_7                SOC_SCACHE_VERSION(1,7)
    537 /* Add bcm_trident_trunk_mbr_zero_rsvd to scache. */
    538 #define BCM_WB_VERSION_1_8                SOC_SCACHE_VERSION(1,8)
    539 #define BCM_WB_DEFAULT_VERSION            BCM_WB_VERSION_1_8
    540 
    541 
    542 #endif /* BCM_WARM_BOOT_SUPPORT */
    543 
    544 STATIC int
    545 _bcm_esw_trunk_hwmem_clear(int unit, soc_mem_t mem)
    546 {
    547     uint8 *mbuf;
    548     int rv, size;
    549 
    550     size = SOC_MEM_TABLE_BYTES(unit, mem);
    551     mbuf = soc_cm_salloc(unit, size, "trunk_memory");
    552     if (mbuf == NULL) {
    553         return BCM_E_MEMORY;
    554     }
    555 
    556     sal_memset(mbuf, 0, size);
    557 
    558     rv = soc_mem_write_range(unit, mem, MEM_BLOCK_ANY,
    559                              soc_mem_index_min(unit, mem),
    560                              soc_mem_index_max(unit, mem), mbuf);
    561     soc_cm_sfree(unit, mbuf);
    562 
    563     return rv;
    564 }
    565 
    566 /*
    567  * Function:
    568  *	bcm_trunk_init
    569  * Purpose:
    570  *	Initializes the trunk tables to empty (no trunks configured)
    571  * Parameters:
    572  *      unit - StrataSwitch PCI device unit number (driver internal).
    573  * Returns:
    574  *      BCM_E_NONE              Success.
    575  *      BCM_E_XXX
    576  */
    577 
    578 int
    579 bcm_esw_trunk_init(int unit)
    580 {
    581 #ifdef BCM_XGS_SWITCH_SUPPORT
    582     uint16      dev_id;
    583     uint8       rev_id;
    584 #endif
    585     trunk_private_t *t_info;
    586     bcm_trunk_t     tid;
    587     bcm_pbmp_t      all_pbmp;
    588     soc_mem_t       trunk_mem = TRUNK_GROUPm;
    589 
    590 #ifdef BCM_TOMAHAWK3_SUPPORT
    591     soc_info_t *si;
    592     source_trunk_map_table_entry_t stm_ent;
    593     int stm_entry_per_pipe;
    594     int pipe;
    595 #endif
    596 
    597     int rv = BCM_E_NONE;
    598 
    599     COMPILER_REFERENCE(t_info);
    600     COMPILER_REFERENCE(tid);
    601     COMPILER_REFERENCE(all_pbmp);
    602 
    603     if (soc_feature(unit, soc_feature_fastlag)) {
    604         trunk_mem = FAST_TRUNK_GROUPm;
    605     }
    606 
    607     /* Create protection mutex. */
    608     if (NULL == TRUNK_CNTL(unit).lock) {
    609         TRUNK_CNTL(unit).lock = sal_mutex_create("Trunk module mutex");
    610         if(NULL == TRUNK_CNTL(unit).lock) {
    611             return BCM_E_MEMORY;
    612         }
    613     }
    614 
    615     TRUNK_LOCK(unit);
    616 
    617     BCM_PBMP_CLEAR(all_pbmp);
    618     BCM_PBMP_ASSIGN(all_pbmp, PBMP_ALL(unit));
    619 
    620     TRUNK_CNTL(unit).ngroups_fp = 0;
    621     TRUNK_CNTL(unit).nports_fp = 0;
    622     TRUNK_CNTL(unit).ngroups_hg = 0;
    623     TRUNK_CNTL(unit).nports_hg = 0;
    624 
    625 #ifdef BCM_XGS_SWITCH_SUPPORT
    626     if (SOC_IS_XGS_SWITCH(unit)) {
    627 #ifdef BCM_WARM_BOOT_SUPPORT
    628 #ifdef BCM_XGS3_SWITCH_SUPPORT
    629         int                 ngroups_fp_max;
    630         soc_scache_handle_t scache_handle;
    631         uint32              trunk_scache_size;
    632         uint8               *trunk_scache;
    633 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT)
    634         int                 trunk_fp_hwf_flags_alloc_size;
    635         int                 trunk_hg_hwf_flags_alloc_size;
    636 
    637         COMPILER_REFERENCE(trunk_fp_hwf_flags_alloc_size);
    638         COMPILER_REFERENCE(trunk_hg_hwf_flags_alloc_size);;
    639 
    640 #endif /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */
    641 
    642         COMPILER_REFERENCE(ngroups_fp_max);
    643         COMPILER_REFERENCE(scache_handle);
    644         COMPILER_REFERENCE(trunk_scache_size);
    645         COMPILER_REFERENCE(trunk_scache);
    646 
    647 #endif /* BCM_XGS3_SWITCH_SUPPORT */
    648 #endif /* BCM_WARM_BOOT_SUPPORT */
    649 
    650         if (SOC_IS_SHADOW(unit)) {
    651             TRUNK_UNLOCK(unit);
    652             return BCM_E_UNAVAIL;
    653         }
    654 #ifdef BCM_TOMAHAWK3_SUPPORT
    655         if (SOC_IS_TOMAHAWK3(unit)) {
    656             TRUNK_CNTL(unit).ngroups_fp =
    657                 soc_mem_index_count(unit, FAST_TRUNK_PORTS_1m);
    658 
    659             /* No HiGig support in TH3 */
    660             TRUNK_CNTL(unit).ngroups_hg = 0;
    661         } else
    662 #endif
    663 #if defined(BCM_SABER2_SUPPORT)
    664         if (SOC_IS_SABER2(unit) && soc_sb2_5626x_devtype(unit)) {
    665             TRUNK_CNTL(unit).ngroups_fp = SABER2_5626X_NGROUPS_FP;
    666         } else
    667 #endif /* BCM_SABER2_SUPPORT */
    668         {
    669             TRUNK_CNTL(unit).ngroups_fp = soc_mem_index_count(unit, trunk_mem);
    670         }
    671 
    672 #ifdef BCM_WARM_BOOT_SUPPORT
    673 #ifdef BCM_XGS3_SWITCH_SUPPORT
    674         /* Record maximum HW size */
    675         ngroups_fp_max = TRUNK_CNTL(unit).ngroups_fp;
    676 #endif /* BCM_WARM_BOOT_SUPPORT */
    677 #endif
    678 
    679 #ifdef BCM_TOMAHAWK3_SUPPORT
    680         if (SOC_IS_TOMAHAWK3(unit)) {
    681             TRUNK_CNTL(unit).nports_fp = 1 << soc_mem_field_length(unit,
    682                     FAST_TRUNK_SIZEm, TG_SIZEf);
    683 
    684             /* No HiGig support in TH3 */
    685             TRUNK_CNTL(unit).nports_hg = 0;
    686         } else
    687 #endif
    688         if (soc_mem_field_valid(unit, trunk_mem, TG_SIZEf)) {
    689             soc_cm_get_id(unit, &dev_id, &rev_id);
    690 #if defined(BCM_SABER2_SUPPORT)
    691             if (SOC_IS_SABER2(unit) && soc_sb2_5626x_devtype(unit)) {
    692                 TRUNK_CNTL(unit).nports_fp = SABER2_5626X_NPORTS_FP;
    693             } else
    694 #endif /* BCM_SABER2_SUPPORT */
    695             if ((dev_id == BCM56830_DEVICE_ID)
    696                 || (dev_id == BCM56838_DEVICE_ID)
    697                 || (dev_id == BCM56831_DEVICE_ID)
    698                 || (dev_id == BCM56834_DEVICE_ID)) {
    699                 TRUNK_CNTL(unit).nports_fp = 16;
    700             } else if (dev_id == BCM56835_DEVICE_ID) {
    701                 TRUNK_CNTL(unit).nports_fp = 32;
    702             } else {
    703                 TRUNK_CNTL(unit).nports_fp = 1 << soc_mem_field_length(unit,
    704                         trunk_mem, TG_SIZEf);
    705             }
    706         } else {
    707             TRUNK_CNTL(unit).nports_fp = 8;
    708         }
    709 
    710 	if (!SOC_WARM_BOOT(unit) && !SOC_HW_RESET(unit)) {
    711 #ifdef BCM_TOMAHAWK3_SUPPORT
    712             if (SOC_IS_TOMAHAWK3(unit)) {
    713                 /* Tomahawk 3's Fast LAG ports are split into two memories,
    714                  * 32 in each, for a total of 64 possible ports per LAG */
    715                 rv = _bcm_esw_trunk_hwmem_clear(unit, FAST_TRUNK_PORTS_1m);
    716                 if (BCM_FAILURE(rv)) {
    717                     TRUNK_UNLOCK(unit);
    718                     return BCM_E_INTERNAL;
    719                 }
    720                 rv = _bcm_esw_trunk_hwmem_clear(unit, FAST_TRUNK_PORTS_2m);
    721                 if (BCM_FAILURE(rv)) {
    722                     TRUNK_UNLOCK(unit);
    723                     return BCM_E_INTERNAL;
    724                 }
    725                 rv = _bcm_esw_trunk_hwmem_clear(unit, FAST_TRUNK_SIZEm);
    726                 if (BCM_FAILURE(rv)) {
    727                     TRUNK_UNLOCK(unit);
    728                     return BCM_E_INTERNAL;
    729                 }
    730             } else
    731 #endif
    732             {
    733                 rv = _bcm_esw_trunk_hwmem_clear(unit, trunk_mem);
    734                 if (BCM_FAILURE(rv)) {
    735                     TRUNK_UNLOCK(unit);
    736                     return BCM_E_INTERNAL;
    737                 }
    738             }
    739 
    740             rv = _bcm_esw_trunk_hwmem_clear(unit, TRUNK_BITMAPm);
    741             if (BCM_FAILURE(rv)) {
    742                 TRUNK_UNLOCK(unit);
    743                 return BCM_E_INTERNAL;
    744             }
    745 
    746             if (soc_feature(unit, soc_feature_trunk_egress)) {
    747                 rv = _bcm_esw_trunk_hwmem_clear(unit, TRUNK_EGR_MASKm);
    748                 if (BCM_FAILURE(rv)) {
    749                     TRUNK_UNLOCK(unit);
    750                     return BCM_E_INTERNAL;
    751                 }
    752             }
    753 	}
    754 
    755 #if defined(BCM_XGS3_SWITCH_SUPPORT)
    756         if (SOC_IS_XGS3_SWITCH(unit)) {
    757             uint64 config64, oconfig64;
    758             soc_reg_t reg;
    759 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT)
    760             soc_reg_t hg_trunk_bmap;
    761 #if defined(BCM_GREYHOUND2_SUPPORT)
    762             soc_reg_t hg_trunk_bmap_hi = INVALIDr;
    763 #endif /* BCM_GREYHOUND2_SUPPORT */
    764 #endif
    765 
    766             if (SOC_WARM_BOOT(unit)) {
    767 
    768                 if (SOC_IS_FBX(unit)) {
    769 
    770 #if defined(BCM_TRX_SUPPORT)
    771                     reg = SOC_IS_TRX(unit) ? ING_CONFIG_64r : ING_CONFIGr;
    772 #else /* BCM_TRX_SUPPORT */
    773                     reg = ING_CONFIGr;
    774 #endif /* BCM_TRX_SUPPORT */
    775                     rv = soc_reg_get(unit, reg, REG_PORT_ANY, 0, &config64);
    776                     if (SOC_FAILURE(rv)) {
    777                         TRUNK_UNLOCK(unit);
    778                         return rv;
    779                     }
    780 
    781 #if defined(BCM_SABER2_SUPPORT)
    782                     if (SOC_IS_SABER2(unit) && soc_sb2_5626x_devtype(unit)) {
    783                         TRUNK_CNTL(unit).ngroups_hg =
    784                             SABER2_5626X_NGROUPS_HG;
    785                         TRUNK_CNTL(unit).nports_hg =
    786                             SABER2_5626X_NPORTS_HG;
    787                     } else
    788 #endif /* BCM_SABER2_SUPPORT */
    789 #if defined(BCM_HAWKEYE_SUPPORT)
    790                     if (SOC_IS_HAWKEYE(unit)) {
    791 		        TRUNK_CNTL(unit).ngroups_fp = 8;
    792                     } else
    793 #endif
    794                     /* TD3 only supports trunks 128 mode and not trunks 32 mode.
    795                      * The field to distinguish is hence not present */
    796                     if (!SOC_IS_TRIDENT3X(unit) && !(SOC_IS_TOMAHAWK3(unit))) {
    797                         if (!soc_reg64_field32_get(unit, reg, config64,
    798                                     TRUNKS128f)) {
    799                             TRUNK_CNTL(unit).ngroups_fp = 32;
    800                         }
    801                     }
    802 
    803                     if (SOC_IS_XGS3_FABRIC(unit)) {
    804                         TRUNK_CNTL(unit).ngroups_fp = 0;
    805                         TRUNK_CNTL(unit).nports_fp = 0;
    806                     }
    807 #if defined(BCM_HAWKEYE_SUPPORT)
    808                     if (SOC_IS_HAWKEYE(unit)) {
    809                         TRUNK_CNTL(unit).ngroups_hg = 0;
    810                         TRUNK_CNTL(unit).nports_hg = 0;
    811                     } else
    812 #endif
    813                     if (SOC_IS_FB_FX_HX(unit) || SOC_IS_RAVEN(unit)) {
    814                         TRUNK_CNTL(unit).ngroups_hg = 2;
    815                         TRUNK_CNTL(unit).nports_hg = 4;
    816                     }
    817 
    818 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT)
    819                     else if (SOC_IS_HB_GW(unit) || SOC_IS_TRX(unit)) {
    820                         if (soc_mem_is_valid(unit, HG_TRUNK_BITMAPm)) {
    821 
    822 #if defined(BCM_SABER2_SUPPORT)
    823                             if (SOC_IS_SABER2(unit) && soc_sb2_5626x_devtype(unit)) {
    824                                 TRUNK_CNTL(unit).ngroups_hg =
    825                                     SABER2_5626X_NGROUPS_HG;
    826                             } else
    827 #endif /* BCM_SABER2_SUPPORT */
    828                             {
    829                                 TRUNK_CNTL(unit).ngroups_hg =
    830                                     soc_mem_index_count(unit, HG_TRUNK_BITMAPm);
    831                             }
    832 #if defined(BCM_METROLITE_SUPPORT)
    833                             if (soc_feature(unit, soc_feature_hg_trunk_groups_max_2)) {
    834                               TRUNK_CNTL(unit).ngroups_hg = 2;
    835                             }
    836                             if (soc_feature(unit, soc_feature_hg_trunk_group_members_max_4)) {
    837                               TRUNK_CNTL(unit).nports_hg = 4;
    838                             }
    839 #endif /* BCM_METROLITE_SUPPORT */
    840                         } else {
    841 #if defined(BCM_TRIUMPH2_SUPPORT)
    842                             if (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) || 
    843                                 SOC_IS_VALKYRIE2(unit)) {
    844                                 hg_trunk_bmap = HG_TRUNK_BITMAP_64r;
    845                             } else 
    846 #endif /* BCM_TRIUMPH2_SUPPORT */
    847 #if defined(BCM_GREYHOUND2_SUPPORT)
    848                             if (SOC_IS_GREYHOUND2(unit)) {
    849                                 hg_trunk_bmap = HG_TRUNK_BITMAP_LOr;
    850                                 hg_trunk_bmap_hi = HG_TRUNK_BITMAP_HIr;
    851                             } else
    852 #endif /* BCM_GREYHOUND2_SUPPORT */
    853                             {
    854                                 hg_trunk_bmap = HG_TRUNK_BITMAPr;
    855                             }
    856 #if defined(BCM_TOMAHAWK3_SUPPORT)
    857                             /* TH3 doesn't support HG. ngroups_hg was set to 0
    858                              * above
    859                              */
    860                             if (!SOC_IS_TOMAHAWK3(unit))
    861 #endif
    862                             {
    863                                 TRUNK_CNTL(unit).ngroups_hg =
    864                                     SOC_REG_NUMELS(unit, hg_trunk_bmap);
    865                             }
    866                         }
    867 
    868 #if defined(BCM_HURRICANE3_SUPPORT)
    869                         if (SOC_IS_HURRICANE3(unit)) {
    870                             soc_cm_get_id(unit, &dev_id, &rev_id);
    871                             if ((dev_id == BCM56163_DEVICE_ID) ||
    872                                 (dev_id == BCM56164_DEVICE_ID) ||
    873                                 (dev_id == BCM56166_DEVICE_ID)) { /* Hurricane3Lite */
    874                                 TRUNK_CNTL(unit).ngroups_hg = 2;
    875                             }
    876                         }
    877 #endif /* BCM_HURRICANE3_SUPPORT */
    878 
    879 #if defined(BCM_TRIDENT_SUPPORT)
    880                         if (soc_mem_field_valid(unit, HG_TRUNK_GROUPm,
    881                                     TG_SIZEf)) {
    882                             soc_cm_get_id(unit, &dev_id, &rev_id);
    883 #if defined(BCM_SABER2_SUPPORT)
    884                             if (SOC_IS_SABER2(unit) && soc_sb2_5626x_devtype(unit)) {
    885                                 TRUNK_CNTL(unit).nports_hg =
    886                                     SABER2_5626X_NPORTS_HG;
    887                             } else
    888 #endif /* BCM_SABER2_SUPPORT */
    889                             if ((dev_id == BCM56838_DEVICE_ID)
    890                                 || (dev_id == BCM56831_DEVICE_ID)) {
    891                                 TRUNK_CNTL(unit).nports_hg = 16;
    892                             } else if (dev_id == BCM56835_DEVICE_ID) {
    893                                 TRUNK_CNTL(unit).nports_hg = 32;
    894                             } else {
    895 #if defined(BCM_METROLITE_SUPPORT)
    896                             if (soc_feature(unit, soc_feature_hg_trunk_group_members_max_4)) {
    897                               TRUNK_CNTL(unit).nports_hg = 4;
    898                             } else
    899 #endif /* BCM_METROLITE_SUPPORT */
    900                                 TRUNK_CNTL(unit).nports_hg =
    901                                     1 << soc_mem_field_length(unit,
    902                                             HG_TRUNK_GROUPm, TG_SIZEf);
    903                             }
    904                         } else
    905 #endif /* BCM_TRIDENT_SUPPORT */
    906 #if defined(BCM_SCORPION_SUPPORT)
    907                         if (SOC_IS_SC_CQ(unit)) {
    908                             TRUNK_CNTL(unit).nports_hg = 16;
    909                         } else 
    910 #endif /* BCM_SCORPION_SUPPORT */
    911 #if defined(BCM_HURRICANE3_SUPPORT)
    912                         if (soc_feature
    913                                 (unit,
    914                                  soc_feature_hg_trunk_group_members_max_4)) {
    915                             TRUNK_CNTL(unit).nports_hg = 4;
    916                         } else
    917 #endif /* BCM_HURRICANE3_SUPPORT */
    918                         {
    919 #if defined(BCM_TOMAHAWK3_SUPPORT)
    920                             if (!SOC_IS_TOMAHAWK3(unit))
    921 #endif
    922                             {
    923                                 TRUNK_CNTL(unit).nports_hg = 8;
    924                             }
    925                         }
    926                     }
    927 #endif /* BCM_BRADLEY_SUPPORT || BCM_TRX_SUPPORT */
    928                 }
    929 
    930             } else {
    931                 int trunk128;
    932                 int stm_index;
    933                 int size;
    934                 int min_idx, max_idx, cnt_idx;
    935                 source_trunk_map_table_entry_t *ent;
    936                 uint8 *mbuf;
    937                 soc_field_t tgid_fld = TGIDf;
    938 
    939                 trunk128 = soc_property_get(unit, spn_TRUNK_EXTEND, 1);
    940 
    941                 /* For Raptor and devices that support only the extended trunk
    942                  * mode, TRUNKS128 field should alwyas be programmed to 1 */
    943                 if (SOC_IS_RAPTOR(unit) || SOC_IS_RAVEN(unit) || 
    944                         soc_feature(unit, soc_feature_trunk_extended_only)) {
    945                     trunk128 = 1;
    946                 }
    947  
    948                 if (!trunk128) {
    949                     if (SOC_IS_HAWKEYE(unit)){
    950                         TRUNK_CNTL(unit).ngroups_fp = 8;
    951                     } else {
    952                         TRUNK_CNTL(unit).ngroups_fp = 32;
    953                     }
    954                 }
    955 
    956                 if (SOC_IS_XGS3_FABRIC(unit)) {
    957                     TRUNK_CNTL(unit).ngroups_fp = 0;
    958                     TRUNK_CNTL(unit).nports_fp = 0;
    959                 }
    960 
    961 #if defined(BCM_SABER2_SUPPORT)
    962                 if (SOC_IS_SABER2(unit) && soc_sb2_5626x_devtype(unit)) {
    963                     TRUNK_CNTL(unit).ngroups_hg =
    964                         SABER2_5626X_NGROUPS_HG;
    965                     TRUNK_CNTL(unit).nports_hg =
    966                         SABER2_5626X_NPORTS_HG;
    967                 }
    968 #endif /* BCM_SABER2_SUPPORT */
    969                 /* Reset SOURCE_TRUNK_MAP table */
    970                 min_idx = soc_mem_index_min(unit, SOURCE_TRUNK_MAP_TABLEm);
    971                 max_idx = soc_mem_index_max(unit, SOURCE_TRUNK_MAP_TABLEm);
    972                 cnt_idx = soc_mem_index_count(unit, SOURCE_TRUNK_MAP_TABLEm);
    973 
    974                 size = SOC_MEM_TABLE_BYTES(unit, SOURCE_TRUNK_MAP_TABLEm);
    975                 mbuf = soc_cm_salloc(unit, size, "source_trunk_map");
    976                 if (NULL == mbuf) {
    977                     TRUNK_UNLOCK(unit);
    978                     return BCM_E_MEMORY;
    979                 }
    980 
    981                 soc_mem_lock(unit, SOURCE_TRUNK_MAP_TABLEm);
    982 
    983 /* Tomahawk 3's memory is ADDR_SPLIT, so it cannot do soc_mem_read_range or 
    984  * soc_mem_write_range
    985  */
    986 #ifdef BCM_TOMAHAWK3_SUPPORT
    987                 /* Clear port type, which describes whether a normal port is
    988                  * being used or a trunk port, and trunk group id (TGID)
    989                  */
    990                 if (SOC_IS_TOMAHAWK3(unit)) {
    991                     si = &SOC_INFO(unit);
    992                     stm_entry_per_pipe = cnt_idx / _TH3_PIPES_PER_DEV;
    993                     for (stm_index = 0; stm_index < cnt_idx; stm_index++) {
    994                         pipe = stm_index / stm_entry_per_pipe;
    995 
    996                         /* Skip the memory if the pipe is not active */
    997                         if (SOC_PBMP_IS_NULL(si->pipe_pbm[pipe])) {
    998                             continue;
    999                         }
   1000 
   1001                         rv = READ_SOURCE_TRUNK_MAP_TABLEm(unit,
   1002                                 MEM_BLOCK_ANY, stm_index, &stm_ent);
   1003                         if (BCM_FAILURE(rv)) {
   1004                             soc_cm_sfree(unit, mbuf);
   1005                             soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm);
   1006                             TRUNK_UNLOCK(unit);
   1007                             return rv;
   1008                         }
   1009                         /* clear the PORT_TYPEf and TGIDf fields */
   1010                         soc_SOURCE_TRUNK_MAP_TABLEm_field32_set
   1011                             (unit, &stm_ent, PORT_TYPEf, 0);
   1012                         soc_SOURCE_TRUNK_MAP_TABLEm_field32_set
   1013                             (unit, &stm_ent, TGIDf, 0);
   1014 
   1015                         rv =  WRITE_SOURCE_TRUNK_MAP_TABLEm(unit,
   1016                                 MEM_BLOCK_ALL, stm_index, &stm_ent);
   1017                         if (BCM_FAILURE(rv)) {
   1018                             soc_cm_sfree(unit, mbuf);
   1019                             soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm);
   1020                             TRUNK_UNLOCK(unit);
   1021                             return rv;
   1022                         }
   1023 
   1024                     }
   1025                 } else
   1026 #endif
   1027                 {
   1028                 rv = soc_mem_read_range(unit, SOURCE_TRUNK_MAP_TABLEm, 
   1029                                         MEM_BLOCK_ANY, min_idx, max_idx, mbuf);
   1030                 if (BCM_FAILURE(rv)) {
   1031                     soc_cm_sfree(unit, mbuf);
   1032                     soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm);
   1033                     TRUNK_UNLOCK(unit);
   1034                     return rv;
   1035                 }
   1036                 if (SOC_MEM_FIELD_VALID(unit, SOURCE_TRUNK_MAP_TABLEm,
   1037                                         SRC_TGIDf)) {
   1038                     tgid_fld = SRC_TGIDf;
   1039                 }
   1040                 for (stm_index = 0; stm_index < cnt_idx; stm_index++) {
   1041                     ent = soc_mem_table_idx_to_pointer(unit,
   1042                                 SOURCE_TRUNK_MAP_TABLEm,
   1043                                 source_trunk_map_table_entry_t *,
   1044                                 mbuf, stm_index);
   1045                     soc_SOURCE_TRUNK_MAP_TABLEm_field32_set
   1046                         (unit, ent, PORT_TYPEf, 0);
   1047                     soc_SOURCE_TRUNK_MAP_TABLEm_field32_set
   1048                         (unit, ent, tgid_fld, 0);
   1049                 }
   1050                 rv = soc_mem_write_range(unit, SOURCE_TRUNK_MAP_TABLEm,
   1051                                          MEM_BLOCK_ANY, min_idx, max_idx,
   1052                                          mbuf);
   1053                 }
   1054                 soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm);
   1055                 soc_cm_sfree(unit, mbuf);
   1056                 if (BCM_FAILURE(rv)) {
   1057                     TRUNK_UNLOCK(unit);
   1058                     return rv;
   1059                 }
   1060 
   1061                 if (SOC_IS_FBX(unit) || SOC_IS_RAVEN(unit)) {
   1062 #if defined(BCM_TRX_SUPPORT)
   1063                     reg = SOC_IS_TRX(unit) ? ING_CONFIG_64r : ING_CONFIGr;
   1064 #else /* BCM_TRX_SUPPORT */
   1065                     reg = ING_CONFIGr;
   1066 #endif /* BCM_TRX_SUPPORT */
   1067                     if (SOC_REG_FIELD_VALID(unit, reg, TRUNKS128f)) {
   1068                         rv = soc_reg_get(unit, reg, REG_PORT_ANY, 0, &config64);
   1069                         if (SOC_FAILURE(rv)) {
   1070                             TRUNK_UNLOCK(unit);
   1071                             return rv;
   1072                         }
   1073                         oconfig64 = config64;
   1074                         soc_reg64_field32_set(unit, reg, &config64, TRUNKS128f,
   1075                                           trunk128 ? 1 : 0);
   1076                         if (COMPILER_64_NE(config64, oconfig64)) {
   1077                             rv = soc_reg_set(unit, reg, REG_PORT_ANY, 0, config64);
   1078                             if (SOC_FAILURE(rv)) {
   1079                                 TRUNK_UNLOCK(unit);
   1080                                 return rv;
   1081                             }
   1082                         }
   1083                     }
   1084 
   1085                     rv = soc_mem_clear(unit, NONUCAST_TRUNK_BLOCK_MASKm,
   1086                                         MEM_BLOCK_ALL, 0);
   1087 
   1088                     if (SOC_FAILURE(rv)) {
   1089                         TRUNK_UNLOCK(unit);
   1090                         return rv;
   1091                     }
   1092 
   1093 #if defined(BCM_TRIUMPH3_SUPPORT)
   1094                     if (soc_feature(unit, soc_feature_axp)) {
   1095                         if (soc_mem_is_valid(unit, AXP_WTX_TRUNK_GROUP_BITMAPm)) {
   1096                             rv = soc_mem_clear(unit, AXP_WTX_TRUNK_GROUP_BITMAPm,
   1097                                                MEM_BLOCK_ALL, 0);
   1098                             if (SOC_FAILURE(rv)) {
   1099                                 TRUNK_UNLOCK(unit);
   1100                                 return rv;
   1101                             }
   1102                         }
   1103                         if (soc_mem_is_valid(unit, AXP_WTX_TRUNK_BLOCK_MASKm)) {
   1104                             rv = soc_mem_clear(unit, AXP_WTX_TRUNK_BLOCK_MASKm,
   1105                                     MEM_BLOCK_ALL, 0);
   1106                             if (SOC_FAILURE(rv)) {
   1107                                 TRUNK_UNLOCK(unit);
   1108                                 return rv;
   1109                             }
   1110                         }
   1111                     }
   1112 #endif /* BCM_TRIUMPH3_SUPPORT */
   1113 
   1114                     if (soc_mem_is_valid(unit, TRUNK_MEMBERm)) {
   1115                         rv = soc_mem_clear(unit, TRUNK_MEMBERm, MEM_BLOCK_ALL, 0);
   1116                         if (SOC_FAILURE(rv)) {
   1117                             TRUNK_UNLOCK(unit);
   1118                             return rv;
   1119                         }
   1120                     }
   1121 
   1122                     if (soc_feature(unit, soc_feature_hg_trunking)) {
   1123                         if (soc_mem_is_valid(unit, HIGIG_TRUNK_CONTROLm)) {
   1124                             higig_trunk_control_entry_t entry;
   1125                             rv = soc_mem_read(unit, HIGIG_TRUNK_CONTROLm,
   1126                                               MEM_BLOCK_ANY, 0, &entry);
   1127                             if (SOC_FAILURE(rv)) {
   1128                                 TRUNK_UNLOCK(unit);
   1129                                 return rv;
   1130                             }
   1131 #if defined(BCM_KATANA2_SUPPORT)
   1132                             if (soc_feature(unit, soc_feature_linkphy_coe) ||
   1133                                 soc_feature(unit, soc_feature_subtag_coe)) {
   1134                                 _bcm_kt2_subport_pbmp_update(unit, &all_pbmp);
   1135                             }
   1136                             if (SOC_IS_KATANA2(unit) &&
   1137                                 soc_feature(unit, soc_feature_flex_port)) {
   1138                                 rv = _bcm_kt2_flexio_pbmp_update(unit,
   1139                                     &all_pbmp);
   1140                                 if (SOC_FAILURE(rv)) {
   1141                                     TRUNK_UNLOCK(unit);
   1142                                     return rv;
   1143                                 }
   1144                             }
   1145 #endif
   1146                             soc_mem_pbmp_field_set(unit, HIGIG_TRUNK_CONTROLm,
   1147                                     &entry, ACTIVE_PORT_BITMAPf, &all_pbmp);
   1148                             rv = soc_mem_write(unit, HIGIG_TRUNK_CONTROLm,
   1149                                                MEM_BLOCK_ALL, 0, &entry);
   1150                             if (SOC_FAILURE(rv)) {
   1151                                 TRUNK_UNLOCK(unit);
   1152                                 return rv;
   1153                             }
   1154                         } else {
   1155                             uint64 val, hg_cntl_entry;
   1156                             soc_reg_t hg_trunk_reg;
   1157 #if defined(BCM_GREYHOUND2_SUPPORT)
   1158                             soc_reg_t hg_trunk_reg_hi = INVALIDr;
   1159 #endif /* BCM_GREYHOUND2_SUPPORT */
   1160 
   1161                             COMPILER_REFERENCE(val);
   1162 
   1163 #if defined(BCM_TRIUMPH2_SUPPORT)
   1164                             if (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) || 
   1165                                     SOC_IS_VALKYRIE2(unit)) {
   1166                                 hg_trunk_reg = HIGIG_TRUNK_CONTROL_64r;
   1167                             } else  
   1168 #endif /* BCM_TRIUMPH2_SUPPORT */
   1169 #if defined(BCM_GREYHOUND2_SUPPORT)
   1170                             if (SOC_IS_GREYHOUND2(unit)) {
   1171                                 hg_trunk_reg = HIGIG_TRUNK_CONTROL_LOr;
   1172                                 hg_trunk_reg_hi = HIGIG_TRUNK_CONTROL_HIr;
   1173                             } else
   1174 #endif /* BCM_GREYHOUND2_SUPPORT */
   1175                             {
   1176                                 hg_trunk_reg = HIGIG_TRUNK_CONTROLr;
   1177                             }
   1178 
   1179                             rv = soc_reg_get(unit, hg_trunk_reg,
   1180                                               REG_PORT_ANY, 0,
   1181                                               &hg_cntl_entry);
   1182                             if (SOC_FAILURE(rv)) {
   1183                                 TRUNK_UNLOCK(unit);
   1184                                 return rv;
   1185                             }
   1186                             val = soc_reg64_field_get(unit, hg_trunk_reg,
   1187                                     hg_cntl_entry,
   1188                                     ACTIVE_PORT_BITMAPf);
   1189                             COMPILER_64_ZERO(hg_cntl_entry);
   1190                             soc_reg64_field_set(unit, hg_trunk_reg,
   1191                                     &hg_cntl_entry,
   1192                                     ACTIVE_PORT_BITMAPf, val);
   1193                             rv = soc_reg_set(unit, hg_trunk_reg,
   1194                                                REG_PORT_ANY, 0,
   1195                                                hg_cntl_entry);
   1196                             if (SOC_FAILURE(rv)) {
   1197                                 TRUNK_UNLOCK(unit);
   1198                                 return rv;
   1199                             }
   1200 #if defined(BCM_GREYHOUND2_SUPPORT)
   1201                             if (SOC_IS_GREYHOUND2(unit)) {
   1202                                 rv = soc_reg_get(unit, hg_trunk_reg_hi,
   1203                                                  REG_PORT_ANY, 0,
   1204                                                  &hg_cntl_entry);
   1205                                 if (SOC_FAILURE(rv)) {
   1206                                     TRUNK_UNLOCK(unit);
   1207                                     return rv;
   1208                                 }
   1209                                 val = soc_reg64_field_get(unit,
   1210                                                           hg_trunk_reg_hi,
   1211                                                           hg_cntl_entry,
   1212                                                           ACTIVE_PORT_BITMAPf);
   1213                                 COMPILER_64_ZERO(hg_cntl_entry);
   1214                                 soc_reg64_field_set(unit, hg_trunk_reg_hi,
   1215                                                     &hg_cntl_entry,
   1216                                                     ACTIVE_PORT_BITMAPf, val);
   1217                                 rv = soc_reg_set(unit, hg_trunk_reg_hi,
   1218                                                  REG_PORT_ANY, 0,
   1219                                                  hg_cntl_entry);
   1220                                 if (SOC_FAILURE(rv)) {
   1221                                     TRUNK_UNLOCK(unit);
   1222                                     return rv;
   1223                                 }
   1224                             }
   1225 #endif /* BCM_GREYHOUND2_SUPPORT */
   1226                         }
   1227                     }
   1228 
   1229                     if (SOC_IS_FB_FX_HX(unit) || SOC_IS_RAVEN(unit)) {
   1230                         if (soc_feature(unit, soc_feature_hg_trunking)) {
   1231                             TRUNK_CNTL(unit).ngroups_hg = 2;
   1232                             TRUNK_CNTL(unit).nports_hg = 4;
   1233                             rv = WRITE_HIGIG_TRUNK_GROUPr(unit, 0);
   1234                             if (SOC_FAILURE(rv)) {
   1235                                 TRUNK_UNLOCK(unit);
   1236                                 return rv;
   1237                             }
   1238                         }
   1239                     }
   1240 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT)
   1241                     else if ((SOC_IS_HB_GW(unit) || SOC_IS_TRX(unit))
   1242                              && !SOC_IS_TOMAHAWK3(unit)) {
   1243                         uint64      val64;
   1244 
   1245 #if defined(BCM_TRIDENT_SUPPORT)
   1246                         if (soc_mem_is_valid(unit, HG_TRUNK_BITMAPm) &&
   1247                                 soc_mem_is_valid(unit, HG_TRUNK_GROUPm) &&
   1248                                 soc_mem_is_valid(unit, HG_TRUNK_MEMBERm)) {
   1249 
   1250 #if defined(BCM_SABER2_SUPPORT)
   1251                             if (SOC_IS_SABER2(unit) && soc_sb2_5626x_devtype(unit)) {
   1252                                 TRUNK_CNTL(unit).ngroups_hg =
   1253                                     SABER2_5626X_NGROUPS_HG;
   1254                                 TRUNK_CNTL(unit).nports_hg =
   1255                                     SABER2_5626X_NPORTS_HG;
   1256                             } else
   1257 #endif /* BCM_SABER2_SUPPORT */
   1258                             {
   1259                                 TRUNK_CNTL(unit).ngroups_hg =
   1260                                     soc_mem_index_count(unit, HG_TRUNK_BITMAPm);
   1261                                 TRUNK_CNTL(unit).nports_hg =
   1262                                     1 << soc_mem_field_length(unit, HG_TRUNK_GROUPm,
   1263                                             TG_SIZEf);
   1264                             }
   1265 
   1266 #if defined(BCM_METROLITE_SUPPORT)
   1267                             if (soc_feature(unit, soc_feature_hg_trunk_groups_max_2)) {
   1268                                 TRUNK_CNTL(unit).ngroups_hg = 2;
   1269                             }
   1270                             if (soc_feature(unit, soc_feature_hg_trunk_group_members_max_4)) {
   1271                                 TRUNK_CNTL(unit).nports_hg = 4;
   1272                             }
   1273 #endif /* BCM_METROLITE_SUPPORT */
   1274 
   1275                             rv = soc_mem_clear(unit, HG_TRUNK_BITMAPm,
   1276                                                MEM_BLOCK_ALL, TRUE);
   1277                             if (SOC_FAILURE(rv)) {
   1278                                 TRUNK_UNLOCK(unit);
   1279                                 return rv;
   1280                             }
   1281                             rv = soc_mem_clear(unit, HG_TRUNK_GROUPm,
   1282                                                MEM_BLOCK_ALL, TRUE);
   1283                             if (SOC_FAILURE(rv)) {
   1284                                 TRUNK_UNLOCK(unit);
   1285                                 return rv;
   1286                             }
   1287                             rv = soc_mem_clear(unit, HG_TRUNK_MEMBERm,
   1288                                                MEM_BLOCK_ALL, TRUE);
   1289 
   1290                             if (SOC_FAILURE(rv)) {
   1291                                 TRUNK_UNLOCK(unit);
   1292                                 return rv;
   1293                             }
   1294                         } else
   1295 #endif /* BCM_TRIDENT_SUPPORT */
   1296                         {
   1297 
   1298 #if defined(BCM_TRIUMPH2_SUPPORT)
   1299                             if (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) || 
   1300                                     SOC_IS_VALKYRIE2(unit)) {
   1301                                 hg_trunk_bmap = HG_TRUNK_BITMAP_64r;
   1302                             } else 
   1303 #endif /* BCM_TRIUMPH2_SUPPORT */
   1304 #if defined(BCM_GREYHOUND2_SUPPORT)
   1305                             if (SOC_IS_GREYHOUND2(unit)) {
   1306                                 hg_trunk_bmap = HG_TRUNK_BITMAP_LOr;
   1307                                 hg_trunk_bmap_hi = HG_TRUNK_BITMAP_HIr;
   1308                             } else
   1309 #endif /* BCM_GREYHOUND2_SUPPORT */
   1310                             {
   1311                                 hg_trunk_bmap = HG_TRUNK_BITMAPr;
   1312                             }
   1313 
   1314                             TRUNK_CNTL(unit).ngroups_hg =
   1315                                 SOC_REG_NUMELS(unit, hg_trunk_bmap);
   1316 
   1317 #if defined(BCM_HURRICANE3_SUPPORT)
   1318                             if (SOC_IS_HURRICANE3(unit)) {
   1319                                 soc_cm_get_id(unit, &dev_id, &rev_id);
   1320                                 if ((dev_id == BCM56163_DEVICE_ID) ||
   1321                                     (dev_id == BCM56164_DEVICE_ID) ||
   1322                                     (dev_id == BCM56166_DEVICE_ID)) { /* Hurricane3Lite */
   1323                                     TRUNK_CNTL(unit).ngroups_hg = 2;
   1324                                 }
   1325                             }
   1326 #endif /* BCM_HURRICANE3_SUPPORT */
   1327 
   1328 #if defined(BCM_SCORPION_SUPPORT)
   1329                             if (SOC_IS_SC_CQ(unit)) {
   1330                                 TRUNK_CNTL(unit).nports_hg = 16;
   1331                             } else 
   1332 #endif /* BCM_SCORPION_SUPPORT */
   1333 #if defined(BCM_HURRICANE3_SUPPORT)
   1334                             if (soc_feature
   1335                                     (unit,
   1336                                      soc_feature_hg_trunk_group_members_max_4)) {
   1337                                 TRUNK_CNTL(unit).nports_hg = 4;
   1338                             } else
   1339 #endif /* BCM_HURRICANE3_SUPPORT */
   1340                             {
   1341                                 TRUNK_CNTL(unit).nports_hg = 8;
   1342                             }
   1343 
   1344                             COMPILER_64_ZERO(val64);
   1345                             for (tid = 0; tid < TRUNK_CNTL(unit).ngroups_hg; tid++) {
   1346 #if defined(BCM_GREYHOUND2_SUPPORT)
   1347                                 if (SOC_IS_GREYHOUND2(unit)) {
   1348                                     rv = soc_reg_set(unit, hg_trunk_bmap_hi,
   1349                                                      REG_PORT_ANY, tid, val64);
   1350                                     if (SOC_FAILURE(rv)) {
   1351                                         TRUNK_UNLOCK(unit);
   1352                                         return rv;
   1353                                     }
   1354                                 }
   1355 #endif /* BCM_GREYHOUND2_SUPPORT */
   1356                                 rv = soc_reg_set(unit, hg_trunk_bmap, REG_PORT_ANY,
   1357                                                  tid, val64);
   1358                                 if (SOC_FAILURE(rv)) {
   1359                                     TRUNK_UNLOCK(unit);
   1360                                     return rv;
   1361                                 }
   1362 
   1363                                 rv = WRITE_HG_TRUNK_GROUPr(unit, tid, val64);
   1364                                 if (SOC_FAILURE(rv)) {
   1365                                     TRUNK_UNLOCK(unit);
   1366                                     return rv;
   1367                                 }
   1368                             }
   1369                         }
   1370                     }
   1371 #endif /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */
   1372                 }
   1373             }
   1374 #ifdef BCM_TOMAHAWK3_SUPPORT
   1375             if (SOC_IS_TOMAHAWK3(unit)) {
   1376                 rv = _bcm_th3_trunk_init(unit);
   1377                 if (BCM_FAILURE(rv)) {
   1378                     TRUNK_UNLOCK(unit);
   1379                     return rv;
   1380                 }
   1381             } else
   1382 #endif
   1383 #ifdef BCM_TRIDENT_SUPPORT
   1384             if (soc_feature(unit, soc_feature_shared_trunk_member_table)) {
   1385                 rv = _bcm_trident_trunk_init(unit);
   1386                 if (BCM_FAILURE(rv)) {
   1387                     TRUNK_UNLOCK(unit);
   1388                     return rv;
   1389                 }
   1390             } else 
   1391 #endif /* BCM_TRIDENT_SUPPORT */
   1392             {
   1393                 rv = _bcm_xgs3_trunk_member_init(unit);
   1394                 if (BCM_FAILURE(rv)) {
   1395                     TRUNK_UNLOCK(unit);
   1396                     _bcm_esw_trunk_deinit(unit);
   1397                     return rv;
   1398                 }
   1399                 rv = _bcm_xgs3_trunk_swfailover_init(unit);
   1400                 if (BCM_FAILURE(rv)) {
   1401                     TRUNK_UNLOCK(unit);
   1402                     _bcm_esw_trunk_deinit(unit);
   1403                     return rv;
   1404                 }
   1405                 rv = _bcm_xgs3_trunk_mod_port_map_init(unit);
   1406                 if (BCM_FAILURE(rv)) {
   1407                     TRUNK_UNLOCK(unit);
   1408                     _bcm_esw_trunk_deinit(unit);
   1409                     return rv;
   1410                 }
   1411 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT)
   1412                 if (soc_feature(unit, soc_feature_hg_trunk_failover) ||
   1413                     soc_feature(unit, soc_feature_port_lag_failover)) {
   1414                     rv = _bcm_xgs3_trunk_hwfailover_init(unit);
   1415                     if (BCM_FAILURE(rv)) {
   1416                         TRUNK_UNLOCK(unit);
   1417                         _bcm_esw_trunk_deinit(unit);
   1418                         return rv;
   1419                     }
   1420                 }
   1421 #endif /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */
   1422             }
   1423 
   1424 #ifdef BCM_APACHE_SUPPORT
   1425             if (soc_feature(unit, soc_feature_apache_round_robin_fp_lag)) {
   1426                 int num_groups_rr_fp = 2;
   1427                 TRUNK_CNTL(unit).ngroups_rr_fp = num_groups_rr_fp;
   1428 
   1429                 if (NULL == TRUNK_CNTL(unit).fp_rr_lag_bmp) {
   1430                     TRUNK_CNTL(unit).fp_rr_lag_bmp =
   1431                     sal_alloc(SHR_BITALLOCSIZE(num_groups_rr_fp), "fp rr lags used bitmap");
   1432                     if (NULL == TRUNK_CNTL(unit).fp_rr_lag_bmp) {
   1433                         TRUNK_UNLOCK(unit);
   1434                         _bcm_esw_trunk_deinit(unit);
   1435                         return BCM_E_MEMORY;
   1436                     }
   1437                 }
   1438                 sal_memset(TRUNK_CNTL(unit).fp_rr_lag_bmp, 0, SHR_BITALLOCSIZE(num_groups_rr_fp));
   1439             }
   1440 #endif /* BCM_APACHE_SUPPORT */
   1441 
   1442 #ifdef BCM_WARM_BOOT_SUPPORT
   1443             TRUNK_CNTL(unit).trunk_bmp_alloc =
   1444                 SHR_BITALLOCSIZE(ngroups_fp_max +
   1445                                  TRUNK_CNTL(unit).ngroups_hg);
   1446 
   1447             /* Num FP trunks, num fabric trunks, bitmap of defined trunks */
   1448             trunk_scache_size = sizeof(uint32) + sizeof(uint32) +
   1449                 TRUNK_CNTL(unit).trunk_bmp_alloc;
   1450 
   1451             if (NULL == TRUNK_CNTL(unit).trunk_bmp_ptr) {
   1452                     TRUNK_CNTL(unit).trunk_bmp_ptr =
   1453                         sal_alloc( TRUNK_CNTL(unit).trunk_bmp_alloc, "trunk used bitmap");
   1454                     if (NULL == TRUNK_CNTL(unit).trunk_bmp_ptr) {
   1455                         _bcm_esw_trunk_deinit(unit);
   1456                         TRUNK_UNLOCK(unit);
   1457                         return BCM_E_MEMORY;
   1458                 }
   1459             }
   1460 
   1461 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT)
   1462             trunk_fp_hwf_flags_alloc_size = 0;
   1463             trunk_hg_hwf_flags_alloc_size = 0;
   1464             if (soc_feature(unit, soc_feature_port_lag_failover)) {
   1465                 /* FP trunk failover flags */
   1466 #if defined(BCM_TRIDENT_SUPPORT)
   1467                 if (soc_feature(unit, soc_feature_shared_trunk_member_table)) {
   1468                     /* For Trident, ngproups_fp_max = 1024, nports_fp = 256,
   1469                      * while the maximum number of front-panel trunk ports is 
   1470                      * limited by the number of entries in
   1471                      * SOURCE_TRUNK_MAP_TABLE, which is 4096. To efficiently 
   1472                      * utilize scache space, for each trunk group, 1 byte of
   1473                      * BCM_TRUNK_FLAG_xxx flags, 2 bytes of trunk size, and
   1474                      * trunk-size bytes of hardware failover flags are stored.
   1475                      */
   1476                     trunk_fp_hwf_flags_alloc_size +=
   1477                         (ngroups_fp_max * 3 +
   1478                          soc_mem_index_count(unit, SOURCE_TRUNK_MAP_TABLEm)) * 
   1479                         sizeof(uint8);
   1480                 } else
   1481 #if defined(BCM_TOMAHAWK3_SUPPORT)
   1482                 if (SOC_IS_TOMAHAWK3(unit)) {
   1483                 /*
   1484                  * For TH3, soc_mem_index_count(unit, SOURCE_TRUNK_MAP_TABLEm)
   1485                  * evaluates to 160
   1486                  */
   1487                     trunk_fp_hwf_flags_alloc_size +=
   1488                         (ngroups_fp_max * 3 +
   1489                          soc_mem_index_count(unit, SOURCE_TRUNK_MAP_TABLEm)) * 
   1490                         sizeof(uint8);
   1491                 } else
   1492 #endif /* BCM_TOMAHAWK3_SUPPORT */
   1493 #endif /* BCM_TRIDENT_SUPPORT */
   1494                 {
   1495                     trunk_fp_hwf_flags_alloc_size +=
   1496                         (ngroups_fp_max * (TRUNK_CNTL(unit).nports_fp + 1)) *
   1497                         sizeof(uint8);
   1498                 }
   1499             }
   1500 
   1501             if (soc_feature(unit, soc_feature_hg_trunk_failover)) {
   1502                 /* HG trunk failover flags */
   1503                 trunk_hg_hwf_flags_alloc_size +=
   1504                     (TRUNK_CNTL(unit).ngroups_hg *
   1505                      (TRUNK_CNTL(unit).nports_hg + 1)) *
   1506                     sizeof(uint8);
   1507             }
   1508 
   1509             if (0 != trunk_fp_hwf_flags_alloc_size) {
   1510                 if (NULL == TRUNK_CNTL(unit).fp_hwf_flags) {
   1511                     TRUNK_CNTL(unit).fp_hwf_flags =
   1512                         sal_alloc(trunk_fp_hwf_flags_alloc_size, "trunk fp hwf flags");
   1513                 }
   1514                 if (NULL == TRUNK_CNTL(unit).fp_hwf_flags) {
   1515                     _bcm_esw_trunk_deinit(unit);
   1516                     return BCM_E_MEMORY;
   1517                 }
   1518                 TRUNK_CNTL(unit).fp_hwf_alloc =
   1519                     trunk_fp_hwf_flags_alloc_size;
   1520                 trunk_scache_size += trunk_fp_hwf_flags_alloc_size;
   1521             }
   1522 
   1523             if (0 != trunk_hg_hwf_flags_alloc_size) {
   1524                 if (NULL == TRUNK_CNTL(unit).hg_hwf_flags) {
   1525                     TRUNK_CNTL(unit).hg_hwf_flags =
   1526                         sal_alloc(trunk_hg_hwf_flags_alloc_size, "trunk hg hwf flags");
   1527                 }
   1528                 if (NULL == TRUNK_CNTL(unit).hg_hwf_flags) {
   1529                     _bcm_esw_trunk_deinit(unit);
   1530                     return BCM_E_MEMORY;
   1531                 }
   1532                 TRUNK_CNTL(unit).hg_hwf_alloc =
   1533                     trunk_hg_hwf_flags_alloc_size;
   1534                 trunk_scache_size += trunk_hg_hwf_flags_alloc_size;
   1535             }
   1536 #endif /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */
   1537 
   1538             /* Allocate scache space for BCM_TRUNK_FLAG_IPMC_CLEAVE flag */
   1539             trunk_scache_size += (ngroups_fp_max * sizeof(uint8));
   1540 
   1541             /* Allocate scache space for ipmc_psc */
   1542             trunk_scache_size += (ngroups_fp_max * sizeof(int));
   1543 
   1544             /*allocate scache space for dlf_index */
   1545             trunk_scache_size += (ngroups_fp_max * sizeof(int));
   1546 
   1547 
   1548             /* Allocate scache space to store trunk membership */
   1549 #if defined(BCM_TRIDENT_SUPPORT)
   1550             if (soc_feature(unit, soc_feature_shared_trunk_member_table)) {
   1551                 /* For each front-panel trunk group, store the following info:
   1552                  * - 2 bytes containing the number of members, which can be
   1553                  *   up to 256.
   1554                  * - 2 bytes per member, containing the module and port IDs.
   1555                  * - 1 byte per member, containing member flags.
   1556                  *
   1557                  * Trident can support up to 1k trunk groups. It's not 
   1558                  * necessary to allocate space for 256 members per trunk group,
   1559                  * since the maximum number of members Trident can support is
   1560                  * limited by the TRUNK_MEMBER table.
   1561                  */
   1562                 trunk_scache_size += (ngroups_fp_max * 2 +
   1563                         soc_mem_index_count(unit, TRUNK_MEMBERm) * 3) *
   1564                         sizeof(uint8);
   1565             } else
   1566 #if defined(BCM_TOMAHAWK3_SUPPORT)
   1567             if (SOC_IS_TOMAHAWK3(unit)) {
   1568                 /* For each front-panel trunk group, store the following info:
   1569                  * - 2 byte containing the number of members, which can be
   1570                  *   up to 64.
   1571                  * - 1 bytes per member, containing the port IDs. Mod Id is 0 always.
   1572                  * - 1 byte per member, containing member flags.
   1573                  */
   1574                 trunk_scache_size += (ngroups_fp_max * 2 +
   1575                         soc_mem_index_count(unit, SOURCE_TRUNK_MAP_TABLEm) * 2) *
   1576                         sizeof(uint8);
   1577             } else
   1578 #endif /* BCM_TOMAHAWK3_SUPPORT */
   1579 #endif /* BCM_TRIDENT_SUPPORT */
   1580             {
   1581                 /* For each front-panel trunk group, store the following info:
   1582                  * - 1 byte containing the number of members.
   1583                  * - 2 bytes per member, containing the module and port IDs.
   1584                  * - 1 byte per member, containing member flags.
   1585                  */
   1586                 trunk_scache_size += 
   1587                     (ngroups_fp_max * (1 + 3 * TRUNK_CNTL(unit).nports_fp))
   1588                     * sizeof(uint8);
   1589             }
   1590 
   1591             /* Allocate scache space for Higig dynamic load balancing info */
   1592 #ifdef BCM_TRIDENT_SUPPORT
   1593             if (soc_feature(unit, soc_feature_hg_dlb) &&
   1594                 !soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) {
   1595                 int hg_dlb_scache_size;
   1596                 rv = bcm_trident_hg_dlb_wb_alloc_size_get(unit,
   1597                             &hg_dlb_scache_size);
   1598                 if (SOC_FAILURE(rv)) {
   1599                     TRUNK_UNLOCK(unit);
   1600                     return rv;
   1601                 }
   1602                 trunk_scache_size += hg_dlb_scache_size;
   1603             }
   1604 #endif /* BCM_TRIDENT_SUPPORT */
   1605 
   1606             /* Allocate scache space for LAG dynamic load balancing info */
   1607 #ifdef BCM_TRIUMPH3_SUPPORT
   1608             if (soc_feature(unit, soc_feature_lag_dlb) &&
   1609                 !soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) {
   1610                 int lag_dlb_scache_size;
   1611                 rv = bcm_tr3_lag_dlb_wb_alloc_size_get(unit,
   1612                             &lag_dlb_scache_size);
   1613                 if (SOC_FAILURE(rv)) {
   1614                     TRUNK_UNLOCK(unit);
   1615                     return rv;
   1616                 }
   1617                 trunk_scache_size += lag_dlb_scache_size;
   1618             }
   1619 #endif /* BCM_TRIUMPH3_SUPPORT */
   1620 
   1621 #ifdef BCM_TOMAHAWK2_SUPPORT
   1622             if (soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) {
   1623                 int hgt_lag_dlb_scache_size;
   1624                 BCM_IF_ERROR_RETURN(bcm_th2_hgt_lag_dlb_wb_alloc_size_get(unit,
   1625                             &hgt_lag_dlb_scache_size));
   1626                 trunk_scache_size += hgt_lag_dlb_scache_size;
   1627             }
   1628 #endif /* BCM_TOMAHAWK2_SUPPORT */
   1629 
   1630             /* Allocate scache space for psc */
   1631 #if defined(BCM_TRIDENT_SUPPORT)
   1632             if (soc_feature(unit, soc_feature_shared_trunk_member_table)) {
   1633                 trunk_scache_size += (ngroups_fp_max * sizeof(int));
   1634             }
   1635 #endif /* BCM_TRIDENT_SUPPORT */
   1636 
   1637             /*
   1638              * Allocate scache space for saving TRUNK_MEMBER table property.
   1639              */
   1640 #if defined(BCM_TRIDENT_SUPPORT)
   1641             if (soc_feature(unit, soc_feature_shared_trunk_member_table)) {
   1642                 trunk_scache_size += (sizeof(int));
   1643             }
   1644 #endif /* BCM_TRIDENT_SUPPORT */
   1645 
   1646             /* Limited scache mode unsupported */
   1647             if (!SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit)) {
   1648                 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_TRUNK, 0);
   1649                 rv = _bcm_esw_scache_ptr_get(unit, scache_handle,
   1650                         (0 == SOC_WARM_BOOT(unit)),
   1651                         trunk_scache_size,
   1652                         &trunk_scache, 
   1653                         BCM_WB_DEFAULT_VERSION, NULL);
   1654                 if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) {
   1655                     TRUNK_UNLOCK(unit);
   1656                     _bcm_esw_trunk_deinit(unit);
   1657                     return rv;
   1658                 }
   1659             }
   1660 #endif /* BCM_WARM_BOOT_SUPPORT */
   1661         }
   1662 #endif /* BCM_XGS3_SWITCH_SUPPORT */
   1663     }
   1664 #endif	/* BCM_XGS_SWITCH_SUPPORT */
   1665 
   1666 #ifdef	BCM_XGS12_FABRIC_SUPPORT
   1667     if (SOC_IS_XGS12_FABRIC(unit)) {
   1668 	bcm_port_t	port;
   1669 
   1670     TRUNK_CNTL(unit).ngroups_hg = SOC_REG_NUMELS(unit, ING_HGTRUNKr);
   1671     TRUNK_CNTL(unit).nports_hg = 8;
   1672 
   1673         if (!SOC_WARM_BOOT(unit)) {
   1674             for (tid = 0; tid < TRUNK_CNTL(unit).ngroups_hg; tid++) {
   1675                 PBMP_PORT_ITER(unit, port) {
   1676                     rv = WRITE_ING_HGTRUNKr(unit, port, tid, 0);
   1677                     if (SOC_FAILURE(rv)) {
   1678                         TRUNK_UNLOCK(unit);
   1679                         return rv;
   1680                     }
   1681                 }
   1682             }
   1683         }
   1684     }
   1685 #endif	/* BCM_XGS12_FABRIC_SUPPORT */
   1686 
   1687     if (TRUNK_CNTL(unit).t_info != NULL) {
   1688         sal_free(TRUNK_CNTL(unit).t_info);
   1689         TRUNK_CNTL(unit).t_info = NULL;
   1690 
   1691     }
   1692 
   1693     if (TRUNK_NUM_GROUPS(unit) > 0) {
   1694         TRUNK_CNTL(unit).t_info = 
   1695             sal_alloc(TRUNK_NUM_GROUPS(unit) * sizeof(trunk_private_t),
   1696                       "trunk_priv");
   1697         if (NULL == TRUNK_CNTL(unit).t_info) {
   1698             TRUNK_UNLOCK(unit);
   1699             _bcm_esw_trunk_deinit(unit);
   1700             return (BCM_E_MEMORY);
   1701         }
   1702 
   1703 	t_info = TRUNK_CNTL(unit).t_info;
   1704 
   1705         /* Clear the state for Cold or Warm Boot.
   1706          * Warm Boot will update below. */
   1707         for (tid = 0; tid < TRUNK_NUM_GROUPS(unit); tid++) {
   1708             t_info->tid = BCM_TRUNK_INVALID;
   1709             t_info->in_use = FALSE;
   1710 #ifdef BCM_TOMAHAWK3_SUPPORT
   1711             if (SOC_IS_TOMAHAWK3(unit)) {
   1712                 t_info->psc = BCM_TRUNK_PSC_PORTFLOW;
   1713             } else
   1714 #endif
   1715             {
   1716                 t_info->psc = BCM_TRUNK_PSC_DEFAULT;
   1717             }
   1718             t_info->ipmc_psc = 0;
   1719             t_info->rtag = 0;
   1720             t_info->flags = 0;
   1721             t_info->dlf_index_spec = -1;
   1722             t_info->dlf_index_used = -1;
   1723             t_info->dlf_port_used = 0;
   1724             t_info->mc_index_spec = -1;
   1725             t_info->mc_index_used = -1;
   1726             t_info->mc_port_used = 0;
   1727             t_info->ipmc_index_spec = -1;
   1728             t_info->ipmc_index_used = -1;
   1729             t_info->ipmc_port_used = 0;
   1730             t_info->dynamic_size = 0;
   1731             t_info->dynamic_age = 0;
   1732             t_info->dynamic_load_exponent = 0;
   1733             t_info->dynamic_expected_load_exponent = 0;
   1734             t_info++;
   1735         }
   1736     }
   1737 
   1738 #if defined(BCM_TRIDENT2_SUPPORT) && defined(INCLUDE_L3)
   1739     if (soc_feature(unit, soc_feature_vp_lag)) {
   1740         rv = bcm_td2_vp_lag_init(unit);
   1741         if (BCM_FAILURE(rv)) {
   1742             TRUNK_UNLOCK(unit);
   1743             return rv;
   1744         }
   1745 
   1746     }
   1747 #endif /* BCM_TRIDENT2_SUPPORT && INCLUDE_L3 */
   1748 
   1749 #if defined(BCM_XGS_FABRIC_SUPPORT) || defined(BCM_FIREBOLT_SUPPORT)
   1750     if (SOC_WARM_BOOT(unit)) {
   1751       if (/*!SOC_IS_TOMAHAWK3(unit)*/ 1) {
   1752         rv = _bcm_trunk_reinit(unit);
   1753         if (BCM_FAILURE(rv)) {
   1754             TRUNK_UNLOCK(unit);
   1755             return rv;
   1756         }
   1757       }
   1758 
   1759     }
   1760 #endif
   1761 
   1762     TRUNK_UNLOCK(unit);
   1763 
   1764     return BCM_E_NONE;
   1765 }
   1766 
   1767 
   1768 /*
   1769  * Function:
   1770  *	bcm_trunk_detach
   1771  * Purpose:
   1772  *	Cleans up the trunk tables.
   1773  * Parameters:
   1774  *      unit - StrataSwitch PCI device unit number (driver internal).
   1775  * Returns:
   1776  *      BCM_E_NONE              Success.
   1777  *      BCM_E_XXX
   1778  */
   1779 
   1780 int
   1781 bcm_esw_trunk_detach(int unit)
   1782 {
   1783     /* Return if trunk was not initialized. */
   1784     if (NULL == TRUNK_CNTL(unit).t_info) {
   1785         return (BCM_E_NONE);
   1786     }
   1787 
   1788     sal_free(TRUNK_CNTL(unit).t_info);
   1789     /* Destroy protection mutex. */
   1790     if (NULL != TRUNK_CNTL(unit).lock) {
   1791         sal_mutex_destroy(TRUNK_CNTL(unit).lock);
   1792         TRUNK_CNTL(unit).lock = NULL;
   1793     }
   1794     _bcm_esw_trunk_deinit(unit);
   1795     sal_memset(&TRUNK_CNTL(unit), 0, sizeof(trunk_cntl_t));
   1796 
   1797     return BCM_E_NONE;
   1798 }
   1799 
   1800 /*
   1801  * Function:
   1802  *      _bcm_esw_trunk_chip_info_vp_resource_get
   1803  * Purpose:
   1804  *      Get the VP related information.
   1805  *      Be called internally for forward compatibility.
   1806  * Parameters:
   1807  *      unit         - StrataSwitch PCI device unit number.
   1808  *      vp_id_min    - Minimum virtual port trunk ID number. 
   1809  *      vp_id_max    - Maximum virtual port trunk ID number. 
   1810  *      vp_ports_max - Maximum number of virtual ports per virtual
   1811  *                     port trunk group.
   1812  * Returns:
   1813  *      BCM_E_NONE     Success.
   1814  * Notes:
   1815  *      None.
   1816  */
   1817 int
   1818 _bcm_esw_trunk_chip_info_vp_resource_get(int unit, int *vp_id_min, 
   1819                                          int *vp_id_max, int *vp_ports_max)
   1820 {
   1821     /* Initialize the VP LAG information */
   1822     if (vp_id_min != NULL) {
   1823         *vp_id_min = -1;
   1824     }
   1825 
   1826     if (vp_id_max != NULL) {
   1827         *vp_id_max = -1;
   1828     }
   1829 
   1830     if (vp_ports_max != NULL) {
   1831         *vp_ports_max = 0;
   1832     }
   1833 
   1834 #if defined(BCM_TRIDENT2_SUPPORT) && defined(INCLUDE_L3)
   1835     if (soc_feature(unit, soc_feature_vp_lag)) {
   1836         int ngroups_vp_lag = 0, nports_vp_lag = 0;
   1837 
   1838         BCM_IF_ERROR_RETURN(bcm_td2_vp_lag_info_get(unit, &ngroups_vp_lag,
   1839                                                     &nports_vp_lag));
   1840         if (ngroups_vp_lag > 0) {
   1841 
   1842             if (vp_id_min != NULL) {
   1843                 *vp_id_min = TRUNK_CNTL(unit).ngroups_fp +
   1844                     TRUNK_CNTL(unit).ngroups_hg;
   1845             }
   1846 
   1847             if (vp_id_max != NULL) {
   1848                 *vp_id_max = TRUNK_CNTL(unit).ngroups_fp +
   1849                     TRUNK_CNTL(unit).ngroups_hg + ngroups_vp_lag - 1;
   1850             }
   1851 
   1852             if (vp_ports_max != NULL) {
   1853                 *vp_ports_max = nports_vp_lag;
   1854             }
   1855         }
   1856     }
   1857 #endif /* BCM_TRIDENT2_SUPPORT && INCLUDE_L3 */
   1858 
   1859     return BCM_E_NONE;
   1860 }
   1861 
   1862 /*
   1863  * Function:
   1864  *	_bcm_esw_trunk_id_is_vp_lag
   1865  * Purpose:
   1866  *      Determine if trunk ID is a VP LAG.
   1867  * Parameters:
   1868  *      unit  - SOC unit number
   1869  *      tid   - Trunk ID
   1870  *      tid_is_vp_lag - (OUT) Indicates if trun ID is a VP LAG
   1871  * Returns:
   1872  *      BCM_E_xxx
   1873  */
   1874 int
   1875 _bcm_esw_trunk_id_is_vp_lag(int unit, bcm_trunk_t tid, int *tid_is_vp_lag)
   1876 {
   1877     int vp_id_min = -1, vp_id_max = -1;
   1878 
   1879     if (tid < 0) {
   1880         return BCM_E_PARAM;
   1881     }
   1882 
   1883     BCM_IF_ERROR_RETURN(
   1884         _bcm_esw_trunk_chip_info_vp_resource_get(unit, &vp_id_min,
   1885                                                  &vp_id_max, NULL));
   1886 
   1887     if (tid >= vp_id_min && tid <= vp_id_max) {
   1888         *tid_is_vp_lag = TRUE;
   1889     } else {
   1890         *tid_is_vp_lag = FALSE;
   1891     }
   1892 
   1893     return BCM_E_NONE;
   1894 }
   1895 
   1896 /*
   1897  * Function:
   1898  *	_bcm_esw_trunk_tid_to_vp_lag_vp
   1899  * Purpose:
   1900  *      Convert trunk ID to the VP value representing VP LAG.
   1901  * Parameters:
   1902  *      unit  - SOC unit number
   1903  *      tid   - Trunk ID
   1904  *      vp_lag_vp - (OUT) VP value
   1905  * Returns:
   1906  *      BCM_E_xxx
   1907  */
   1908 int
   1909 _bcm_esw_trunk_tid_to_vp_lag_vp(int unit, bcm_trunk_t tid, int *vp_lag_vp)
   1910 {
   1911     int tid_is_vp_lag;
   1912 
   1913     BCM_IF_ERROR_RETURN(_bcm_esw_trunk_id_is_vp_lag(unit, tid, &tid_is_vp_lag));
   1914 
   1915     if (tid_is_vp_lag) {
   1916 #if defined(BCM_TRIDENT2_SUPPORT) && defined(INCLUDE_L3)
   1917         if (soc_feature(unit, soc_feature_vp_lag)) {
   1918             return bcm_td2_tid_to_vp_lag_vp(unit, tid, vp_lag_vp);
   1919         } else
   1920 #endif /* BCM_TRIDENT2_SUPPORT && INCLUDE_L3 */
   1921         {
   1922             return BCM_E_PARAM;
   1923         }
   1924     } else {
   1925         return BCM_E_PARAM;
   1926     }
   1927 }
   1928 
   1929 /*
   1930  * Function:
   1931  *	_bcm_esw_trunk_vp_lag_vp_to_tid
   1932  * Purpose:
   1933  *      Convert the VP value representing a VP LAG to trunk ID.
   1934  * Parameters:
   1935  *      unit      - SOC unit number
   1936  *      vp_lag_vp - VP value
   1937  *      tid       - (OUT) Trunk ID
   1938  * Returns:
   1939  *      BCM_E_xxx
   1940  */
   1941 int
   1942 _bcm_esw_trunk_vp_lag_vp_to_tid(int unit, int vp_lag_vp, bcm_trunk_t *tid)
   1943 {
   1944 #if defined(BCM_TRIDENT2_SUPPORT) && defined(INCLUDE_L3)
   1945     if (soc_feature(unit, soc_feature_vp_lag)) {
   1946         return bcm_td2_vp_lag_vp_to_tid(unit, vp_lag_vp, tid);
   1947     }
   1948 #endif /* BCM_TRIDENT2_SUPPORT && INCLUDE_L3 */
   1949 
   1950     return BCM_E_UNAVAIL;
   1951 }
   1952 
   1953 /*
   1954  * Function:
   1955  *	_bcm_trunk_create_id
   1956  * Purpose:
   1957  *      Create the software data structure for the specified trunk ID.
   1958  *      This function does not update any hardware tables,
   1959  *      must call bcm_trunk_set() to finish trunk setting.
   1960  * Parameters:
   1961  *      unit - StrataSwitch PCI device unit number (driver internal).
   1962  *      tid - The trunk ID.
   1963  * Returns:
   1964  *      BCM_E_NONE   - Success.
   1965  *      BCM_E_INIT   - trunking software not initialized
   1966  *      BCM_E_EXISTS - TID already used
   1967  *      BCM_E_BADID  - TID out of range
   1968  */
   1969 STATIC int
   1970 _bcm_esw_trunk_create_id(int unit, bcm_trunk_t tid)
   1971 {
   1972     trunk_private_t *t_info;
   1973     int rv;
   1974 
   1975     TRUNK_CHECK(unit, tid);
   1976 
   1977     TRUNK_LOCK(unit);
   1978 
   1979     t_info = &TRUNK_INFO(unit, tid);
   1980 
   1981     if (t_info->tid == BCM_TRUNK_INVALID) {
   1982         t_info->tid = tid;
   1983 #ifdef BCM_TOMAHAWK3_SUPPORT
   1984     if (SOC_IS_TOMAHAWK3(unit)) {
   1985         t_info->psc = BCM_TRUNK_PSC_PORTFLOW;
   1986     } else
   1987 #endif
   1988     {
   1989         t_info->psc = BCM_TRUNK_PSC_DEFAULT;
   1990     }
   1991         t_info->in_use = FALSE;
   1992 #ifdef BCM_APACHE_SUPPORT
   1993         t_info->rr_lag_select = -1;
   1994 #endif /* BCM_APACHE_SUPPORT */
   1995         rv = BCM_E_NONE;
   1996     } else {
   1997 	rv = BCM_E_EXISTS;
   1998     }
   1999 
   2000 #ifdef BCM_WARM_BOOT_SUPPORT
   2001     SOC_CONTROL_LOCK(unit);
   2002     SOC_CONTROL(unit)->scache_dirty = 1;
   2003     SOC_CONTROL_UNLOCK(unit);
   2004 #endif
   2005 
   2006     TRUNK_UNLOCK(unit);
   2007 
   2008     return rv;
   2009 }
   2010 
   2011 /*
   2012  * Function:
   2013  *	bcm_trunk_vplag_get
   2014  * Purpose:
   2015  *      GET VPLAG port Id for VPLAG trunk.
   2016  * Parameters:
   2017  *      unit - (IN) StrataSwitch PCI device unit number (driver internal).
   2018  *      tid - (IN) The trunk ID.
   2019  *      vplag_port_id - (OUT) VPLAG Port Id
   2020  * Returns:
   2021  *      BCM_E_NONE      - Success.
   2022  *      BCM_E_PARAM     - Incorrect LAG Id
   2023  *      BCM_E_NOT_FOUND - LAG Id not used
   2024  */
   2025 int
   2026 bcm_esw_trunk_vplag_get(int unit, bcm_trunk_t tid, bcm_gport_t *vplag_port_id)
   2027 {
   2028     int rv = BCM_E_NONE;
   2029 
   2030     if (!soc_feature(unit, soc_feature_vp_lag)) {
   2031         return BCM_E_UNAVAIL;
   2032 
   2033     } else {
   2034 #if defined(BCM_TRIDENT2_SUPPORT) && defined(INCLUDE_L3)
   2035         int vp_id;
   2036         rv = bcm_td2_tid_to_vp_lag_vp(unit, tid, &vp_id);
   2037         if (BCM_SUCCESS(rv)) {
   2038             BCM_GPORT_VPLAG_PORT_ID_SET(*vplag_port_id, vp_id);
   2039         }
   2040 #endif /* BCM_TRIDENT2_SUPPORT && INCLUDE_L3 */
   2041     }
   2042 
   2043     return rv;
   2044 }
   2045 
   2046 /*
   2047  * Function:
   2048  *	bcm_trunk_vplag_create
   2049  * Purpose:
   2050  *      Create VPLAG trunk.
   2051  * Parameters:
   2052  *      unit - (IN) StrataSwitch PCI device unit number (driver internal).
   2053  *      flags - (IN) Flags.
   2054  *      tid - (IN/OUT) The trunk ID.
   2055  *      vplag_port_id - (IN/OUT) VPLAG Port Id
   2056  * Returns:
   2057  *      BCM_E_NONE     - Success.
   2058  *      BCM_E_FULL - run out of TIDs
   2059  */
   2060 int
   2061 bcm_esw_trunk_with_vplag_create(int unit, uint32 flags, bcm_trunk_t *tid,
   2062                            bcm_gport_t *vplag_port_id)
   2063 {
   2064     int rv = BCM_E_NONE;
   2065 
   2066     TRUNK_INIT(unit);
   2067 
   2068     if (NULL == tid) {
   2069         return BCM_E_PARAM;
   2070     }
   2071 
   2072     if (!soc_feature(unit, soc_feature_vp_lag)) {
   2073         return BCM_E_UNAVAIL;
   2074     }
   2075 
   2076 #if defined(BCM_TRIDENT2_SUPPORT) && defined(INCLUDE_L3)
   2077     if (flags & BCM_TRUNK_FLAG_WITH_ID) {
   2078         int tid_is_vp_lag = 0;
   2079         BCM_IF_ERROR_RETURN
   2080             (_bcm_esw_trunk_id_is_vp_lag(unit, *tid, &tid_is_vp_lag));
   2081 
   2082         if (!(tid_is_vp_lag)) {
   2083             return BCM_E_PARAM;
   2084         }
   2085     }
   2086 
   2087     VPLAG_LOCK(unit);
   2088     rv = bcm_td2_vp_lag_create(unit, flags, tid, vplag_port_id);
   2089     VPLAG_UNLOCK(unit);
   2090 #endif /* BCM_TRIDENT2_SUPPORT && INCLUDE_L3 */
   2091 
   2092     return rv;
   2093 }
   2094 
   2095 /*
   2096  * Function:
   2097  *	bcm_trunk_create
   2098  * Purpose:
   2099  *      Create the software data structure for a trunk ID.
   2100  *      This function does not update any hardware tables,
   2101  *      must call bcm_trunk_set() to finish trunk setting.
   2102  * Parameters:
   2103  *      unit - StrataSwitch PCI device unit number (driver internal).
   2104  *      flags - Flags.
   2105  *      tid - (Out), The trunk ID.
   2106  * Returns:
   2107  *      BCM_E_NONE     - Success.
   2108  *      BCM_E_FULL - run out of TIDs
   2109  */
   2110 
   2111 int
   2112 bcm_esw_trunk_create(int unit, uint32 flags, bcm_trunk_t *tid)
   2113 {
   2114     trunk_private_t *t_info;
   2115     int rv, i;
   2116     bcm_trunk_t max_tid;
   2117     int tid_is_vp_lag = 0;
   2118 
   2119     TRUNK_INIT(unit);
   2120 
   2121     if (NULL == tid) {
   2122         return BCM_E_PARAM;
   2123     }
   2124 
   2125     if (flags & BCM_TRUNK_FLAG_WITH_ID) {
   2126         BCM_IF_ERROR_RETURN
   2127             (_bcm_esw_trunk_id_is_vp_lag(unit, *tid, &tid_is_vp_lag));
   2128     }
   2129 
   2130     if (tid_is_vp_lag || (flags & BCM_TRUNK_FLAG_VP)) {
   2131 #if defined(BCM_TRIDENT2_SUPPORT) && defined(INCLUDE_L3)
   2132         if (soc_feature(unit, soc_feature_vp_lag)) {
   2133             VPLAG_LOCK(unit);
   2134             rv = bcm_td2_vp_lag_create(unit, flags, tid, NULL);
   2135             VPLAG_UNLOCK(unit);
   2136             return rv;
   2137         } else
   2138 #endif /* BCM_TRIDENT2_SUPPORT && INCLUDE_L3 */
   2139         {
   2140             return BCM_E_PARAM;
   2141         }
   2142     }
   2143 
   2144     if (flags & BCM_TRUNK_FLAG_WITH_ID) {
   2145         return _bcm_esw_trunk_create_id(unit, *tid);
   2146     }
   2147 
   2148     TRUNK_LOCK(unit);
   2149 
   2150     rv = BCM_E_FULL;
   2151 
   2152     t_info = TRUNK_CNTL(unit).t_info;
   2153 
   2154     if (NULL == t_info) {
   2155         return BCM_E_PARAM;
   2156     }
   2157 
   2158     if (TRUNK_CNTL(unit).ngroups_fp == 0) {
   2159         max_tid = TRUNK_CNTL(unit).ngroups_hg - 1;
   2160     }
   2161     else {
   2162         max_tid = TRUNK_CNTL(unit).ngroups_fp - 1;
   2163     }
   2164 
   2165     for (i = 0; i <= max_tid; i++) {
   2166         if (t_info->tid == BCM_TRUNK_INVALID) {
   2167             t_info->tid = i;
   2168             t_info->in_use = FALSE;
   2169 #ifdef BCM_TOMAHAWK3_SUPPORT
   2170         if (SOC_IS_TOMAHAWK3(unit)) {
   2171             t_info->psc = BCM_TRUNK_PSC_PORTFLOW;
   2172         } else
   2173 #endif
   2174         {
   2175             t_info->psc = BCM_TRUNK_PSC_DEFAULT;
   2176         }
   2177             *tid = i;
   2178             rv = BCM_E_NONE;
   2179             break;
   2180         }
   2181         t_info++;
   2182     }
   2183 
   2184 #ifdef BCM_WARM_BOOT_SUPPORT
   2185     SOC_CONTROL_LOCK(unit);
   2186     SOC_CONTROL(unit)->scache_dirty = 1;
   2187     SOC_CONTROL_UNLOCK(unit);
   2188 #endif
   2189 
   2190     TRUNK_UNLOCK(unit);
   2191 
   2192     return rv;
   2193 }
   2194 
   2195 /*
   2196  * Function:
   2197  *	_bcm_trunk_id_validate
   2198  * Purpose:
   2199  *  Service routine to validate validity of trunk id.
   2200  * Parameters:
   2201  *      unit - StrataSwitch PCI device unit number (driver internal).
   2202  *      tid - The trunk ID.
   2203  * Returns:
   2204  *      BCM_E_NONE    - Success.
   2205  *      BCM_E_INIT    - trunking software not initialized
   2206  *      BCM_E_BADID   - TID out of range
   2207  */
   2208 int
   2209 _bcm_trunk_id_validate(int unit, bcm_trunk_t tid)
   2210 {
   2211 #if defined(BCM_TRIDENT2_SUPPORT) && defined(INCLUDE_L3)
   2212     if (soc_feature(unit, soc_feature_vp_lag)) {
   2213         int tid_is_vp_lag;
   2214 
   2215         BCM_IF_ERROR_RETURN
   2216             (_bcm_esw_trunk_id_is_vp_lag(unit, tid, &tid_is_vp_lag));
   2217         if (tid_is_vp_lag) {
   2218             return BCM_E_NONE;
   2219         }
   2220     }
   2221 #endif /* BCM_TRIDENT2_SUPPORT && INCLUDE_L3 */
   2222 
   2223     TRUNK_CHECK(unit, tid);
   2224 
   2225     return (BCM_E_NONE);
   2226 }
   2227 
   2228 
   2229 /*
   2230  * Function:
   2231  *      bcm_trunk_psc_get
   2232  * Purpose:
   2233  *      Get the trunk selection criteria.
   2234  * Parameters:
   2235  *      unit - StrataSwitch PCI device unit number (driver internal).
   2236  *      tid - The trunk ID to be used.
   2237  *      psc - (OUT) Identify the trunk selection criteria.
   2238  * Returns:
   2239  *      BCM_E_NONE              Success.
   2240  *      BCM_E_XXX
   2241  */
   2242 
   2243 int
   2244 bcm_esw_trunk_psc_get(int unit, bcm_trunk_t tid, int *psc)
   2245 {
   2246     trunk_private_t *t_info;
   2247     int rv;
   2248 
   2249     TRUNK_INIT(unit);
   2250     TRUNK_CHECK(unit, tid);
   2251 
   2252     t_info = &TRUNK_INFO(unit, tid);
   2253 
   2254     if (t_info->tid == BCM_TRUNK_INVALID) {
   2255 	*psc = 0;
   2256         rv = BCM_E_NOT_FOUND;
   2257     } else {
   2258 	*psc = t_info->psc;
   2259 	rv = BCM_E_NONE;
   2260     }
   2261 
   2262     return rv;
   2263 }
   2264 
   2265 /*
   2266  * Function:
   2267  *	bcm_trunk_chip_info_get
   2268  * Purpose:
   2269  *      Get the trunk information.
   2270  * Parameters:
   2271  *      unit - StrataSwitch PCI device unit number (driver internal).
   2272  *      t_info - (OUT) Identify the trunk selection criteria.
   2273  * Returns:
   2274  *      BCM_E_NONE              Success.
   2275  * Notes:
   2276  *      None.
   2277  */
   2278 
   2279 int
   2280 bcm_esw_trunk_chip_info_get(int unit, bcm_trunk_chip_info_t *ta_info)
   2281 {
   2282     TRUNK_INIT(unit);
   2283 
   2284     ta_info->trunk_group_count = TRUNK_CNTL(unit).ngroups_fp;
   2285 
   2286     if (TRUNK_CNTL(unit).ngroups_fp > 0) {
   2287         ta_info->trunk_id_min = 0;
   2288 	ta_info->trunk_id_max = TRUNK_CNTL(unit).ngroups_fp - 1;
   2289     }
   2290     else {
   2291         ta_info->trunk_id_min = -1;
   2292 	ta_info->trunk_id_max = -1;
   2293     }
   2294     ta_info->trunk_ports_max = TRUNK_CNTL(unit).nports_fp;
   2295 
   2296     if (TRUNK_CNTL(unit).ngroups_hg > 0) {
   2297         ta_info->trunk_fabric_id_min = TRUNK_CNTL(unit).ngroups_fp;
   2298 	ta_info->trunk_fabric_id_max =
   2299 	  TRUNK_CNTL(unit).ngroups_fp + TRUNK_CNTL(unit).ngroups_hg - 1;
   2300     }
   2301     else {
   2302         ta_info->trunk_fabric_id_min = -1;
   2303 	ta_info->trunk_fabric_id_max = -1;
   2304     }
   2305     ta_info->trunk_fabric_ports_max = TRUNK_CNTL(unit).nports_hg;
   2306 
   2307     ta_info->vp_id_min = -1;
   2308     ta_info->vp_id_max = -1;
   2309     ta_info->vp_ports_max = 0;
   2310 
   2311     BCM_IF_ERROR_RETURN(
   2312         _bcm_esw_trunk_chip_info_vp_resource_get(unit, &(ta_info->vp_id_min),
   2313                                                  &(ta_info->vp_id_max),
   2314                                                  &(ta_info->vp_ports_max)));
   2315     /* Get available VP LAG resource ONLY for API return */
   2316     if (soc_feature(unit, soc_feature_reserve_vp_lag_resource_index_zero)) {
   2317         /*
   2318          * Since entry 0 of VP LAG releated resource (such as EGR_VPLAG_GROUP,
   2319          * EGR_VPLAG_MEMBER table) are reserved, so the maximum number
   2320          * of VP LAGs which are capable of performing VP LAG resolution should
   2321          * be decreased by 1, and the initial tunnel id of VG LAG usage should
   2322          * be increased by 1.
   2323          */
   2324         if (ta_info->vp_id_max > ta_info->vp_id_min) {
   2325             ta_info->vp_id_min += 1;
   2326         } else {
   2327             /* Reset the vp resource */
   2328             ta_info->vp_id_min = -1;
   2329             ta_info->vp_id_max = -1;
   2330             ta_info->vp_ports_max = 0;
   2331         }
   2332     }
   2333 
   2334     return BCM_E_NONE;
   2335 }
   2336 
   2337 /*
   2338  * Function:
   2339  *      _bcm_esw_trunk_member_compar
   2340  * Purpose:
   2341  *      Internal utility routine for sorting on trunk member gport.
   2342  * Parameters:
   2343  *      a - Pointer to trunk member.
   2344  *      b - Pointer to trunk member.
   2345  * Returns:
   2346  *      -1 - a is less than b.
   2347  *      0 - a equals b.
   2348  *      1 - a is more than b.
   2349  */
   2350 
   2351 STATIC int
   2352 _bcm_esw_trunk_member_compar(void *a, void *b)
   2353 {
   2354     bcm_trunk_member_t *d1 = a;
   2355     bcm_trunk_member_t *d2 = b;
   2356 
   2357     return (d1->gport < d2->gport ? -1 :
   2358             d1->gport > d2->gport ? 1 : 0);
   2359 }
   2360 
   2361 /*
   2362  * Function:
   2363  *      bcm_esw_trunk_sort
   2364  * Purpose:
   2365  *      Sort members in a trunk group.
   2366  * Parameters:
   2367  *      member_count - Number of trunk members.
   2368  *      member_array - Array of trunk members.
   2369  * Returns:
   2370  *      BCM_E_XXX
   2371  */
   2372  
   2373 STATIC int
   2374 _bcm_esw_trunk_sort(int member_count, bcm_trunk_member_t **member_array)
   2375 {
   2376     if (member_count > 0) {
   2377         if (NULL == *member_array) {
   2378             return BCM_E_PARAM;
   2379         }
   2380     } else {
   2381         return BCM_E_NONE;
   2382     }
   2383 
   2384     /* Sort members in the accending order */
   2385     _shr_sort(*member_array, member_count, sizeof (bcm_trunk_member_t), _bcm_esw_trunk_member_compar);
   2386 
   2387     return BCM_E_NONE;
   2388 }
   2389 
   2390 /*
   2391  * Function:
   2392  *	_bcm_esw_trunk_modify
   2393  * Purpose:
   2394  *      Set, add, or delete members to/from a trunk group.
   2395  * Parameters:
   2396  *      unit - StrataSwitch PCI device unit number (driver internal).
   2397  *      tid - The trunk ID to be affected.
   2398  *      trunk_info - Information on the trunk group.
   2399  *      member_count - Number of trunk members.
   2400  *      member_array - Array of trunk members.
   2401  *      op - Type of operation: TRUNK_MEMBER_OP_SET, ADD, or DELETE.
   2402  *      member - The member to add or delete.
   2403  * Returns:
   2404  *      BCM_E_XXX
   2405  */
   2406 STATIC int
   2407 _bcm_esw_trunk_modify(int unit, bcm_trunk_t tid,
   2408         bcm_trunk_info_t *trunk_info, int member_count,
   2409         bcm_trunk_member_t *member_array, int op,
   2410         bcm_trunk_member_t *member)
   2411 {
   2412     int rv;
   2413     trunk_private_t  *t_info;
   2414     bcm_trunk_info_t local_trunk_info;
   2415     int tid_is_vp_lag;
   2416     bcm_module_t modid;
   2417     bcm_port_t port;
   2418     bcm_trunk_t tgid;
   2419     int id;
   2420     int i;
   2421 
   2422     TRUNK_INIT(unit);
   2423 
   2424     BCM_IF_ERROR_RETURN
   2425         (_bcm_esw_trunk_id_is_vp_lag(unit, tid, &tid_is_vp_lag));
   2426     if (tid_is_vp_lag) {
   2427 #if defined(BCM_TRIDENT2_SUPPORT) && defined(INCLUDE_L3)
   2428         if (soc_feature(unit, soc_feature_vp_lag)) {
   2429             VPLAG_LOCK(unit);
   2430             rv = bcm_td2_vp_lag_set(unit, tid, trunk_info, member_count,
   2431                     member_array);
   2432             VPLAG_UNLOCK(unit);
   2433             return rv;
   2434         } else
   2435 #endif /* BCM_TRIDENT2_SUPPORT && INCLUDE_L3 */
   2436         {
   2437             return BCM_E_PARAM;
   2438         }
   2439     }
   2440 
   2441     TRUNK_CHECK(unit, tid);
   2442 
   2443     t_info = &TRUNK_INFO(unit, tid);
   2444 
   2445     if (t_info->tid == BCM_TRUNK_INVALID) {
   2446         return BCM_E_NOT_FOUND;
   2447     }
   2448 
   2449     if (NULL == trunk_info) {
   2450         return BCM_E_PARAM;
   2451     }
   2452 
   2453     if (member_count > 0) {
   2454         if (NULL == member_array) {
   2455             return BCM_E_PARAM;
   2456         }
   2457     } else {
   2458         if (NULL != member_array) {
   2459             return BCM_E_PARAM;
   2460         }
   2461     }
   2462 
   2463     /* Sort trunk members */
   2464     if ((trunk_info->flags & BCM_TRUNK_FLAG_MEMBER_SORT)) {
   2465         for (i = 0; i < member_count; i++) {
   2466             BCM_IF_ERROR_RETURN
   2467                 (_bcm_esw_gport_resolve(unit, member_array[i].gport,
   2468                                         &modid, &port, &tgid, &id));
   2469             SOC_GPORT_MODPORT_SET(member_array[i].gport, modid, port);  
   2470         }
   2471         rv = _bcm_esw_trunk_sort(member_count, &member_array);
   2472         if (BCM_FAILURE(rv)) {
   2473             return rv;
   2474         }
   2475     }
   2476     
   2477     /* Check number of ports in trunk group */
   2478     if ((TRUNK_FP_TID(unit, tid) &&
   2479          (member_count > TRUNK_CNTL(unit).nports_fp)) ||
   2480         (TRUNK_FABRIC_TID(unit, tid) &&
   2481          (member_count > TRUNK_CNTL(unit).nports_hg))) {
   2482         return BCM_E_PARAM;
   2483     }
   2484 
   2485 #if defined (BCM_APACHE_SUPPORT)
   2486     if (soc_feature(unit, soc_feature_apache_round_robin_fp_lag)) {
   2487         int rr_lag_sel;
   2488         soc_reg_t rr_counter_reg[] = {RR_COUNTER_1r, RR_COUNTER_2r};
   2489 
   2490         if ((t_info->psc != trunk_info->psc) &&
   2491             (trunk_info->psc == BCM_TRUNK_PSC_ROUND_ROBIN)) {
   2492             /* If PSC is changed to RR Lag, reserve RR_LAG_SELECT */
   2493 
   2494             for (rr_lag_sel = 0; rr_lag_sel < TRUNK_CNTL(unit).ngroups_rr_fp; rr_lag_sel++) {
   2495                 if (!SHR_BITGET(TRUNK_CNTL(unit).fp_rr_lag_bmp, rr_lag_sel)) {
   2496                     t_info->rr_lag_select = rr_lag_sel;
   2497                     break;
   2498                 }
   2499             }
   2500             if (rr_lag_sel == TRUNK_CNTL(unit).ngroups_rr_fp) {
   2501                 return BCM_E_RESOURCE;
   2502             }
   2503             SHR_BITSET(TRUNK_CNTL(unit).fp_rr_lag_bmp, rr_lag_sel);
   2504             soc_reg32_set(unit, rr_counter_reg[rr_lag_sel], REG_PORT_ANY, 0, 0);
   2505 
   2506         } else if ((t_info->psc != trunk_info->psc) &&
   2507                    (t_info->psc == BCM_TRUNK_PSC_ROUND_ROBIN)) {
   2508             /* If PSC is changed from RR Lag, unreserve RR_LAG_SELECT */
   2509 
   2510             rr_lag_sel = t_info->rr_lag_select;
   2511             t_info->rr_lag_select = -1;
   2512             SHR_BITCLR(TRUNK_CNTL(unit).fp_rr_lag_bmp, rr_lag_sel);
   2513             soc_reg32_set(unit, rr_counter_reg[rr_lag_sel], REG_PORT_ANY, 0, 0);
   2514         }
   2515     }
   2516 #endif /* BCM_APACHE_SUPPORT */
   2517 
   2518     bcm_trunk_info_t_init(&local_trunk_info);
   2519     sal_memcpy(&local_trunk_info, trunk_info, sizeof(bcm_trunk_info_t));
   2520 
   2521     TRUNK_LOCK(unit);
   2522 
   2523     rv = mbcm_driver[unit]->mbcm_trunk_modify(unit, tid, &local_trunk_info,
   2524             member_count, member_array, t_info, op, member);
   2525     if (BCM_SUCCESS(rv)) {
   2526         t_info->flags = trunk_info->flags;
   2527         t_info->psc = trunk_info->psc;
   2528         t_info->ipmc_psc = trunk_info->ipmc_psc;
   2529         if (member_count > 0) {
   2530             t_info->in_use = TRUE;
   2531         }
   2532     }
   2533 
   2534     TRUNK_UNLOCK(unit);
   2535 
   2536 #if defined(BCM_XGS3_SWITCH_SUPPORT)
   2537     /* reconcile Mirror to Port programming with trunk member ports. */
   2538     if (SOC_IS_XGS3_SWITCH(unit) && BCM_SUCCESS(rv)
   2539             && !SOC_IS_TOMAHAWK3(unit)) {
   2540         rv = _bcm_xgs3_mirror_trunk_update(unit, tid);
   2541     }
   2542 #endif /* BCM_XGS3_SWITCH_SUPPORT */
   2543 
   2544     return rv;
   2545 }
   2546 
   2547 /*
   2548  * Function:
   2549  *      _bcm_esw_trunk_set
   2550  * Purpose:
   2551  *      Adds ports to a trunk group.
   2552  * Parameters:
   2553  *      unit - StrataSwitch PCI device unit number (driver internal).
   2554  *      tid - The trunk ID to be affected.
   2555  *      trunk_info - Information on the trunk group.
   2556  *      member_count - Number of trunk members.
   2557  *      member_array - Array of trunk members.
   2558  * Returns:
   2559  *      BCM_E_NONE              Success.
   2560  *      BCM_E_XXX
   2561  * Notes:
   2562         helper function callable by both bcm_esw_trunk_set()
   2563  *      and bcm_esw_trunk_psc_set()
   2564  */
   2565 STATIC int
   2566 _bcm_esw_trunk_set(int unit, bcm_trunk_t tid, bcm_trunk_info_t *trunk_info,
   2567         int member_count, bcm_trunk_member_t *member_array)
   2568 {
   2569     int rv = BCM_E_NONE;
   2570 
   2571 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_HELIX4_SUPPORT)
   2572     if (soc_feature(unit, soc_feature_epc_linkflap_recover)) {
   2573         int  index, i = 0, count = 0, status;
   2574         bcm_trunk_member_t *temp_member_array;
   2575 
   2576         temp_member_array = sal_alloc(
   2577             sizeof(bcm_trunk_member_t) * member_count, "TR3 trunk WAR");
   2578         if (temp_member_array == NULL) {
   2579             return BCM_E_MEMORY;
   2580         }
   2581         for (index = 0; index < member_count; index++) {
   2582              status = 1;
   2583              SOC_LINKSCAN_MODPORT_MAP_LOCK(unit);
   2584              rv =  _bcm_td_stk_modport_map_member_link_handler(unit,
   2585                    member_array[index].gport, tid, 0, &status);
   2586              SOC_LINKSCAN_MODPORT_MAP_UNLOCK(unit);
   2587              if (BCM_FAILURE(rv)) {
   2588                  sal_free(temp_member_array);
   2589                  return (rv);
   2590              }
   2591              if (status == 0) {
   2592                  count++;
   2593              } else {
   2594                  temp_member_array[i] = member_array[index];
   2595                  i++;
   2596              }
   2597         }
   2598         if ((count != 0) && (count != member_count)) {
   2599             rv =  _bcm_esw_trunk_modify(unit, tid, trunk_info,
   2600                                         member_count - count,
   2601                                         temp_member_array,
   2602                                         TRUNK_MEMBER_OP_SET, NULL);
   2603         } else {
   2604             rv = _bcm_esw_trunk_modify(unit, tid, trunk_info,
   2605                                        member_count,
   2606                                        member_array,
   2607                                        TRUNK_MEMBER_OP_SET, NULL);
   2608         }
   2609         sal_free(temp_member_array);
   2610      } else
   2611 #endif /* #(BCM_TRIUMPH3_SUPPORT) || defined(BCM_HELIX4_SUPPORT) */
   2612         {
   2613          rv =  _bcm_esw_trunk_modify(unit, tid, trunk_info,
   2614                                      member_count,
   2615                                      member_array,
   2616                                      TRUNK_MEMBER_OP_SET, NULL);
   2617         }
   2618      return rv;
   2619 }
   2620 
   2621 #ifdef BCM_TOMAHAWK3_SUPPORT
   2622 /*
   2623  * Function:
   2624  *      _bcm_th3_trunk_psc_validate
   2625  * Purpose:
   2626  *      Set the trunk selection criteria.
   2627  * Parameters:
   2628  *      unit - StrataSwitch PCI device unit number (driver internal).
   2629  *      tid - The trunk ID to be affected.
   2630  *      psc - Identify the trunk selection criteria.
   2631  * Returns:
   2632  *      BCM_E_NONE              Success.
   2633  *      BCM_E_XXX
   2634  * Notes: th3 helper function callable by both bcm_esw_trunk_set()
   2635  *      and bcm_esw_trunk_psc_set() for th3
   2636  */
   2637 STATIC int
   2638 _bcm_th3_trunk_psc_validate(int unit, bcm_trunk_t tid, int psc)
   2639                     
   2640 {
   2641     trunk_private_t  *t_info;
   2642 
   2643     TRUNK_INIT(unit);
   2644     TRUNK_CHECK(unit, tid);
   2645 
   2646     t_info = &TRUNK_INFO(unit, tid);
   2647 
   2648     if ((psc == 0) || (t_info->psc == psc)) {
   2649         return BCM_E_NONE;
   2650     }
   2651 
   2652     /* If the new psc is one of the dynamic load balancing modes, but the old
   2653      * psc is not, then return BCM_E_PARAM, since dynamic_size and dynamic_age
   2654      * parameters are not available when calling bcm_trunk_set.
   2655      */
   2656     if (!((psc == BCM_TRUNK_PSC_PORTFLOW) ||
   2657           (psc == BCM_TRUNK_PSC_RANDOMIZED))) {
   2658         return BCM_E_UNAVAIL;
   2659     }
   2660     return BCM_E_NONE;
   2661 }
   2662 #endif
   2663 
   2664 /*
   2665  * Function:
   2666  *      bcm_trunk_psc_set
   2667  * Purpose:
   2668  *      Set the trunk selection criteria.
   2669  * Parameters:
   2670  *      unit - StrataSwitch PCI device unit number (driver internal).
   2671  *      tid - The trunk ID to be affected.
   2672  *      psc - Identify the trunk selection criteria.
   2673  * Returns:
   2674  *      BCM_E_NONE              Success.
   2675  *      BCM_E_XXX
   2676  */
   2677 
   2678 int
   2679 bcm_esw_trunk_psc_set(int unit, bcm_trunk_t tid, int psc)
   2680 {
   2681     trunk_private_t  *t_info;
   2682     bcm_trunk_info_t trunk_info;
   2683     bcm_trunk_member_t *member_array = NULL;
   2684     int member_count = 0, unused_count;
   2685     int rv = BCM_E_NONE;
   2686 
   2687     TRUNK_INIT(unit);
   2688     TRUNK_CHECK(unit, tid);
   2689 
   2690     t_info = &TRUNK_INFO(unit, tid);
   2691 
   2692     if (t_info->tid == BCM_TRUNK_INVALID) {
   2693             return BCM_E_NOT_FOUND;
   2694     }
   2695     if (psc <= 0) {
   2696         if (!SOC_IS_TOMAHAWK3(unit)) {
   2697             psc = BCM_TRUNK_PSC_DEFAULT;
   2698         } else {
   2699             psc = BCM_TRUNK_PSC_PORTFLOW;
   2700         }
   2701     }
   2702     if (t_info->psc == psc) {
   2703             return BCM_E_NONE;
   2704     }
   2705     /* upto above is common for Legacy and TH3 */
   2706 #ifdef BCM_TOMAHAWK3_SUPPORT
   2707     if (SOC_IS_TOMAHAWK3(unit)) {
   2708         rv = _bcm_th3_trunk_psc_validate(unit, tid, psc);
   2709         if (BCM_FAILURE(rv)) {
   2710             return rv;
   2711         }
   2712         BCM_IF_ERROR_RETURN(bcm_esw_trunk_get(unit, tid, &trunk_info, 0, NULL,
   2713                               &member_count));
   2714     } else 
   2715 #endif
   2716     {
   2717         if (!t_info->in_use) {
   2718             t_info->psc = psc;
   2719             return BCM_E_NONE;
   2720         }
   2721         BCM_IF_ERROR_RETURN(bcm_esw_trunk_get(unit, tid, &trunk_info, 0, NULL,
   2722                     &member_count));
   2723     
   2724         /* If the new psc is one of the dynamic load balancing modes, but the old
   2725          * psc is not, then return BCM_E_PARAM, since dynamic_size and dynamic_age
   2726          * parameters are not available when calling bcm_trunk_set.
   2727          */
   2728         if ((psc == BCM_TRUNK_PSC_DYNAMIC) ||
   2729             (psc == BCM_TRUNK_PSC_DYNAMIC_ASSIGNED) ||
   2730             (psc == BCM_TRUNK_PSC_DYNAMIC_OPTIMAL)) {
   2731             if ((trunk_info.psc != BCM_TRUNK_PSC_DYNAMIC) &&
   2732                 (trunk_info.psc != BCM_TRUNK_PSC_DYNAMIC_ASSIGNED) &&
   2733                 (trunk_info.psc != BCM_TRUNK_PSC_DYNAMIC_OPTIMAL)) {
   2734                 return BCM_E_PARAM;
   2735             }
   2736         }
   2737     
   2738         /* If the new psc is the resilient hashing mode, but the old
   2739          * psc is not, then return BCM_E_PARAM, since the dynamic_size
   2740          * parameter is not available when calling bcm_trunk_set.
   2741          */
   2742         if (psc == BCM_TRUNK_PSC_DYNAMIC_RESILIENT) {
   2743             if (trunk_info.psc != BCM_TRUNK_PSC_DYNAMIC_RESILIENT) {
   2744                 return BCM_E_PARAM;
   2745             }
   2746         }
   2747     }
   2748 
   2749     if (member_count > 0) {
   2750         member_array = sal_alloc(sizeof(bcm_trunk_member_t) * member_count,
   2751                 "trunk member array");
   2752         if (NULL == member_array) {
   2753             return BCM_E_MEMORY;
   2754         }
   2755         rv = bcm_esw_trunk_get(unit, tid, &trunk_info, member_count,
   2756                 member_array, &unused_count);
   2757         if (BCM_FAILURE(rv)) {
   2758             sal_free(member_array);
   2759             return rv;
   2760         }
   2761     } 
   2762     trunk_info.psc = psc;
   2763     trunk_info.flags = 0; /* Don't change failover config */
   2764     rv = _bcm_esw_trunk_set(unit, tid, &trunk_info, member_count, member_array);
   2765     if (NULL != member_array) {
   2766         sal_free(member_array);
   2767     }
   2768     return rv;
   2769 }
   2770 
   2771 /*
   2772  * Function:
   2773  *	bcm_trunk_set
   2774  * Purpose:
   2775  *      Adds ports to a trunk group.
   2776  * Parameters:
   2777  *      unit - StrataSwitch PCI device unit number (driver internal).
   2778  *      tid - The trunk ID to be affected.
   2779  *      trunk_info - Information on the trunk group.
   2780  *      member_count - Number of trunk members.
   2781  *      member_array - Array of trunk members.
   2782  * Returns:
   2783  *      BCM_E_NONE              Success.
   2784  *      BCM_E_XXX
   2785  * Notes:
   2786  *      The existing ports in the trunk group will be replaced with new ones.
   2787  */
   2788 int
   2789 bcm_esw_trunk_set(int unit, bcm_trunk_t tid, bcm_trunk_info_t *trunk_info,
   2790         int member_count, bcm_trunk_member_t *member_array)
   2791 {
   2792     int rv;
   2793 #ifdef BCM_TOMAHAWK3_SUPPORT
   2794     if (SOC_IS_TOMAHAWK3(unit)) {
   2795         if (trunk_info->psc < 0) {
   2796             trunk_info->psc = BCM_TRUNK_PSC_PORTFLOW;
   2797         }
   2798         rv = _bcm_th3_trunk_psc_validate(unit, tid, trunk_info->psc);
   2799         if (BCM_FAILURE(rv)) {
   2800             return rv;
   2801         }
   2802     }
   2803 #endif
   2804     rv =  _bcm_esw_trunk_set(unit, tid, trunk_info,
   2805                                    member_count, member_array);
   2806     return rv;
   2807 }
   2808 
   2809 /*
   2810  * Function:
   2811  *	bcm_esw_trunk_destroy
   2812  * Purpose:
   2813  *	Removes a trunk group.
   2814  * Parameters:
   2815  *      unit - StrataSwitch PCI device unit number (driver internal).
   2816  *      tid - Trunk Id.
   2817  * Returns:
   2818  *      BCM_E_NONE     Success.
   2819  *      BCM_E_XXX
   2820  */
   2821 
   2822 int
   2823 bcm_esw_trunk_destroy(int unit, bcm_trunk_t tid)
   2824 {
   2825     trunk_private_t *t_info;
   2826     int rv = BCM_E_NONE;
   2827     int tid_is_vp_lag;
   2828     bcm_trunk_chip_info_t chip_info;
   2829 
   2830     TRUNK_INIT(unit);
   2831 
   2832     BCM_IF_ERROR_RETURN
   2833         (_bcm_esw_trunk_id_is_vp_lag(unit, tid, &tid_is_vp_lag));
   2834     if (tid_is_vp_lag) {
   2835 #if defined(BCM_TRIDENT2_SUPPORT) && defined(INCLUDE_L3)
   2836         if (soc_feature(unit, soc_feature_vp_lag)) {
   2837             VPLAG_LOCK(unit);
   2838             rv = bcm_td2_vp_lag_destroy(unit, tid);
   2839             VPLAG_UNLOCK(unit);
   2840             return rv;
   2841         } else
   2842 #endif /* BCM_TRIDENT2_SUPPORT && INCLUDE_L3 */
   2843         {
   2844             return BCM_E_PARAM;
   2845         }
   2846     }
   2847 
   2848     TRUNK_CHECK(unit, tid);
   2849 
   2850     t_info = &TRUNK_INFO(unit, tid);
   2851 
   2852     if (t_info->tid == BCM_TRUNK_INVALID) {
   2853         return (BCM_E_NOT_FOUND);
   2854     }
   2855 
   2856     TRUNK_LOCK(unit);
   2857 
   2858     if (t_info->in_use) {
   2859         rv = mbcm_driver[unit]->mbcm_trunk_destroy(unit, tid, t_info);
   2860     } else {
   2861         /* Trunk ID is valid but there are no members.
   2862          * Need to clear resilient hashing state in hardware.
   2863          */
   2864         rv = bcm_esw_trunk_chip_info_get(unit, &chip_info);
   2865         if (BCM_FAILURE(rv)) {
   2866             TRUNK_UNLOCK(unit);
   2867             return rv;
   2868         }
   2869         if (chip_info.trunk_fabric_id_min >= 0 &&
   2870                 tid >= chip_info.trunk_fabric_id_min) {
   2871 #ifdef BCM_TRIDENT2_SUPPORT
   2872             int hgtid;
   2873             hgtid = tid - chip_info.trunk_fabric_id_min;
   2874             if (soc_feature(unit, soc_feature_hg_resilient_hash)) {
   2875                 /* Clear Higig resilient hashing configuration */
   2876                 rv = bcm_td2_hg_rh_free_resource(unit, hgtid);
   2877             }
   2878 #endif /* BCM_TRIDENT2_SUPPORT */
   2879         } else {
   2880 #ifdef BCM_TRIDENT2_SUPPORT
   2881             if (soc_feature(unit, soc_feature_lag_resilient_hash)) {
   2882                 /* Clear LAG resilient hashing configuration */
   2883                 rv = bcm_td2_lag_rh_free_resource(unit, tid);
   2884             }
   2885 #endif /* BCM_TRIDENT2_SUPPORT */
   2886         }
   2887         if (BCM_FAILURE(rv)) {
   2888             TRUNK_UNLOCK(unit);
   2889             return rv;
   2890         }
   2891     }
   2892 
   2893 #ifdef BCM_APACHE_SUPPORT
   2894     if (soc_feature(unit, soc_feature_apache_round_robin_fp_lag)) {
   2895         if (t_info->rr_lag_select != -1) {
   2896             SHR_BITCLR(TRUNK_CNTL(unit).fp_rr_lag_bmp, t_info->rr_lag_select);
   2897             t_info->rr_lag_select = -1;
   2898         }
   2899     }
   2900 #endif /* BCM_APACHE_SUPPORT */
   2901 
   2902     t_info->tid = BCM_TRUNK_INVALID;
   2903     t_info->in_use = FALSE;
   2904     t_info->psc = BCM_TRUNK_PSC_DEFAULT;
   2905     t_info->ipmc_psc = 0;
   2906     t_info->rtag = 0;
   2907     t_info->flags = 0;
   2908     t_info->dlf_index_spec = -1;
   2909     t_info->dlf_index_used = -1;
   2910     t_info->dlf_port_used = 0;
   2911     t_info->mc_index_spec = -1;
   2912     t_info->mc_index_used = -1;
   2913     t_info->mc_port_used = 0;
   2914     t_info->ipmc_index_spec = -1;
   2915     t_info->ipmc_index_used = -1;
   2916     t_info->ipmc_port_used = 0;
   2917     t_info->dynamic_size = 0;
   2918     t_info->dynamic_age = 0;
   2919     t_info->dynamic_load_exponent = 0;
   2920     t_info->dynamic_expected_load_exponent = 0;
   2921 
   2922 #ifdef BCM_WARM_BOOT_SUPPORT
   2923     SOC_CONTROL_LOCK(unit);
   2924     SOC_CONTROL(unit)->scache_dirty = 1;
   2925     SOC_CONTROL_UNLOCK(unit);
   2926 #endif
   2927 
   2928     TRUNK_UNLOCK(unit);
   2929 
   2930     return rv;
   2931 }
   2932 
   2933 /*
   2934  * Function:
   2935  *      _bcm_esw_trunk_match_multi_get
   2936  * Purpose:
   2937  *      Get all the matches for an existing tid.
   2938  * Parameters:
   2939  *      unit -        (IN) Unit number.
   2940  *      tid -         (IN) Trunk Id
   2941  *      size -        (IN) Number of elements in match array
   2942  *      match_array - (OUT) Match array
   2943  *      count -       (OUT) Match count
   2944  * Returns:
   2945  *      BCM_X_XXX
   2946  */
   2947 int
   2948 _bcm_esw_trunk_match_multi_get(
   2949     int unit,
   2950     bcm_trunk_t tid,
   2951     int size,
   2952     bcm_port_match_info_t *match_array,
   2953     int *count)
   2954 {
   2955     int              tid_is_vp_lag;
   2956     int              rv = BCM_E_UNAVAIL;
   2957 
   2958     TRUNK_INIT(unit);
   2959 
   2960     BCM_IF_ERROR_RETURN
   2961         (_bcm_esw_trunk_id_is_vp_lag(unit, tid, &tid_is_vp_lag));
   2962     if (tid_is_vp_lag) {
   2963 #if defined(BCM_TRIDENT2_SUPPORT) && defined(INCLUDE_L3)
   2964         if (soc_feature(unit, soc_feature_vp_lag)) {
   2965             VPLAG_LOCK(unit);
   2966             rv = _bcm_td2_vp_lag_match_multi_get(unit, tid, size,
   2967                                                  match_array, count);
   2968             VPLAG_UNLOCK(unit);
   2969             return rv;
   2970         } else
   2971 #endif /* BCM_TRIDENT2_SUPPORT && INCLUDE_L3 */
   2972         {
   2973             return BCM_E_PARAM;
   2974         }
   2975     }
   2976     return rv;
   2977 }
   2978 
   2979 /*
   2980  * Function:
   2981  *	bcm_esw_trunk_get
   2982  * Purpose:
   2983  *      Return a port information of given trunk ID.
   2984  * Parameters:
   2985  *      unit   - StrataSwitch PCI device unit number (driver internal).
   2986  *      tid    - Trunk ID.
   2987  *      trunk_info   - (OUT) Place to store returned trunk info.
   2988  *      member_max   - (IN) Size of member_array.
   2989  *      member_array - (OUT) Place to store returned trunk members.
   2990  *      member_count - (OUT) Place to store returned number of trunk members.
   2991  * Returns:
   2992  *      BCM_E_NONE              Success.
   2993  *      BCM_E_XXX
   2994  */
   2995 int
   2996 bcm_esw_trunk_get(int unit, bcm_trunk_t tid, bcm_trunk_info_t *trunk_info,
   2997         int member_max, bcm_trunk_member_t *member_array, int *member_count)
   2998 {
   2999     trunk_private_t  *t_info;
   3000     int              rv;
   3001     bcm_trunk_info_t local_trunk_info;
   3002     int              local_member_count;
   3003     int              tid_is_vp_lag;
   3004 
   3005     TRUNK_INIT(unit);
   3006 
   3007     BCM_IF_ERROR_RETURN
   3008         (_bcm_esw_trunk_id_is_vp_lag(unit, tid, &tid_is_vp_lag));
   3009     if (tid_is_vp_lag) {
   3010 #if defined(BCM_TRIDENT2_SUPPORT) && defined(INCLUDE_L3)
   3011         if (soc_feature(unit, soc_feature_vp_lag)) {
   3012             VPLAG_LOCK(unit);
   3013             rv = bcm_td2_vp_lag_get(unit, tid, trunk_info, member_max,
   3014                     member_array, member_count);
   3015             VPLAG_UNLOCK(unit);
   3016             return rv;
   3017         } else
   3018 #endif /* BCM_TRIDENT2_SUPPORT && INCLUDE_L3 */
   3019         {
   3020             return BCM_E_PARAM;
   3021         }
   3022     }
   3023 
   3024     TRUNK_CHECK(unit, tid);
   3025 
   3026     t_info = &TRUNK_INFO(unit, tid);
   3027 
   3028     if (t_info->tid == BCM_TRUNK_INVALID) {
   3029         return (BCM_E_NOT_FOUND);
   3030     }
   3031 
   3032     if ((member_max > 0) && (NULL == member_array)) {
   3033         return BCM_E_PARAM;
   3034     }
   3035 
   3036     if ((member_max > 0) && (NULL == member_count)) {
   3037         return BCM_E_PARAM;
   3038     }
   3039 
   3040     bcm_trunk_info_t_init(&local_trunk_info);
   3041 
   3042     TRUNK_LOCK(unit);
   3043     rv = mbcm_driver[unit]->mbcm_trunk_get(unit, tid, &local_trunk_info,
   3044             member_max, member_array, &local_member_count, t_info);
   3045     TRUNK_UNLOCK(unit);
   3046 
   3047     if (NULL != trunk_info) {
   3048         *trunk_info = local_trunk_info;
   3049     }
   3050     if (NULL != member_count) {
   3051         *member_count = local_member_count;
   3052     }
   3053 
   3054     return rv;
   3055 }
   3056 
   3057 /*
   3058  * Function:
   3059  *	bcm_trunk_mcast_join
   3060  * Purpose:
   3061  *	Add the trunk group to existing MAC multicast entry.
   3062  * Parameters:
   3063  *      unit - StrataSwitch PCI device unit number (driver internal).
   3064  *      tid - Trunk Id.
   3065  *      vid - Vlan ID.
   3066  *      mac - MAC address.
   3067  * Returns:
   3068  *	BCM_E_XXX
   3069  * Notes:
   3070  *      Applications have to remove the MAC multicast entry and re-add in with
   3071  *      new port bitmap to remove the trunk group from MAC multicast entry.
   3072  */
   3073 
   3074 int
   3075 bcm_esw_trunk_mcast_join(int unit, bcm_trunk_t tid, bcm_vlan_t vid, sal_mac_addr_t mac)
   3076 {
   3077     trunk_private_t *t_info;
   3078     int	rv;
   3079 
   3080     TRUNK_INIT(unit);
   3081     TRUNK_CHECK(unit, tid);
   3082 
   3083     t_info = &TRUNK_INFO(unit, tid);
   3084     if (t_info->tid == BCM_TRUNK_INVALID) {
   3085         return (BCM_E_NOT_FOUND);
   3086     }
   3087 
   3088     if (!t_info->in_use) {
   3089         return (BCM_E_NONE);
   3090     }
   3091 
   3092     TRUNK_LOCK(unit);
   3093     rv = mbcm_driver[unit]->mbcm_trunk_mcast_join(unit, tid, vid, mac, t_info);
   3094     TRUNK_UNLOCK(unit);
   3095 
   3096     return rv;
   3097 }
   3098 
   3099 /*
   3100  * Function:
   3101  *	bcm_trunk_bitmap_expand
   3102  * Purpose:
   3103  *      Given a port bitmap, if any of the ports are in a trunk,
   3104  *      add all of the ports of that trunk to the bitmap.
   3105  * Parameters:
   3106  *      unit - StrataSwitch PCI device unit number (driver internal).
   3107  *      pbmp_ptr - Input/output port bitmap
   3108  * Returns:
   3109  *      BCM_E_NONE              Success.
   3110  *      BCM_E_INTERNAL          Chip access failure.
   3111  * Notes:
   3112  *      Port bitmaps in the vtable and ptable must contain only one of
   3113  *      the trunk ports when multiple ports are aggregated in a trunk.
   3114  *      This is so DLF flooding, etc. goes out only one trunk port.
   3115  */
   3116 
   3117 int
   3118 bcm_esw_trunk_bitmap_expand(int unit, pbmp_t *pbmp_ptr)
   3119 {
   3120     int		    rv = BCM_E_NONE;
   3121     bcm_trunk_t     tid;
   3122     pbmp_t          tports, tpbm;
   3123 
   3124     TRUNK_LOCK(unit);
   3125 
   3126 #ifdef	BCM_XGS_SWITCH_SUPPORT
   3127     if (SOC_IS_XGS_SWITCH(unit)) {
   3128         pbmp_t    hg_pbmp, nonhg_pbmp;
   3129         int       hg_trunk = FALSE;
   3130 #if defined(BCM_TRIUMPH2_SUPPORT) || defined(BCM_TRX_SUPPORT) || \
   3131     defined(BCM_BRADLEY_SUPPORT) || defined(BCM_GREYHOUND2_SUPPORT)
   3132         soc_reg_t hg_trunk_bmap;
   3133 #endif
   3134         pbmp_t    in_pbm;
   3135         int       trident_trunk_arch = FALSE;
   3136 
   3137         SOC_PBMP_ASSIGN(in_pbm, *pbmp_ptr);
   3138 
   3139 #ifdef BCM_TRIUMPH2_SUPPORT
   3140         hg_trunk_bmap = (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) ||
   3141                          SOC_IS_VALKYRIE2(unit)) ? HG_TRUNK_BITMAP_64r :
   3142                                                    HG_TRUNK_BITMAPr;
   3143 #else
   3144 
   3145 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT)
   3146         hg_trunk_bmap = HG_TRUNK_BITMAPr;
   3147 #endif
   3148 #endif
   3149 #ifdef BCM_GREYHOUND2_SUPPORT
   3150         if (SOC_IS_GREYHOUND2(unit)) {
   3151             hg_trunk_bmap = HG_TRUNK_BITMAP_LOr;
   3152         }
   3153 #endif /* BCM_GREYHOUND2_SUPPORT */
   3154 
   3155         SOC_PBMP_ASSIGN(hg_pbmp, PBMP_ST_ALL(unit));
   3156         SOC_PBMP_NEGATE(nonhg_pbmp, hg_pbmp);
   3157         SOC_PBMP_AND(hg_pbmp, *pbmp_ptr);
   3158         SOC_PBMP_AND(nonhg_pbmp, *pbmp_ptr);
   3159         if (SOC_PBMP_NOT_NULL(hg_pbmp) && SOC_PBMP_NOT_NULL(nonhg_pbmp)) {
   3160             TRUNK_UNLOCK(unit);
   3161             return BCM_E_PARAM;
   3162         } else if (SOC_PBMP_NOT_NULL(hg_pbmp)) {
   3163             hg_trunk = TRUE;
   3164         }
   3165 
   3166         if (hg_trunk && SOC_IS_FBX(unit)) {
   3167             uint32     val;
   3168 
   3169             if ((SOC_IS_FB_FX_HX(unit) || SOC_IS_RAVEN(unit))  && 
   3170                 soc_feature(unit, soc_feature_hg_trunking)) {
   3171                 rv = READ_HIGIG_TRUNK_CONTROLr(unit, &val);
   3172                 if (rv >= 0) {
   3173                     SOC_PBMP_CLEAR(tports);
   3174                     SOC_PBMP_WORD_SET(tports, 0, soc_reg_field_get(unit,
   3175                                                  HIGIG_TRUNK_CONTROLr, val,
   3176                                                  HIGIG_TRUNK_BITMAP0f)<<24);
   3177                     SOC_PBMP_ASSIGN(tpbm, *pbmp_ptr);
   3178                     SOC_PBMP_AND(tpbm, tports);
   3179                     if (SOC_PBMP_NOT_NULL(tpbm)) {
   3180                         SOC_PBMP_OR(*pbmp_ptr, tports);
   3181                     }
   3182 
   3183                     SOC_PBMP_CLEAR(tports);
   3184                     SOC_PBMP_WORD_SET(tports, 0, soc_reg_field_get(unit,
   3185                                                  HIGIG_TRUNK_CONTROLr, val,
   3186                                                  HIGIG_TRUNK_BITMAP1f)<<24);
   3187                     SOC_PBMP_ASSIGN(tpbm, *pbmp_ptr);
   3188                     SOC_PBMP_AND(tpbm, tports);
   3189                     if (SOC_PBMP_NOT_NULL(tpbm)) {
   3190                         SOC_PBMP_OR(*pbmp_ptr, tports);
   3191                     }
   3192                 }
   3193             }
   3194 #if defined(BCM_TRIUMPH2_SUPPORT)
   3195             else if (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) ||
   3196                 SOC_IS_VALKYRIE2(unit)) {
   3197                 uint64 val64;
   3198                 for (tid = 0; tid < TRUNK_CNTL(unit).ngroups_hg; tid++) {
   3199                     uint64    hg_trunk_bmap_f;
   3200                     rv = soc_reg_get(unit, hg_trunk_bmap, REG_PORT_ANY, tid, &val64);
   3201                     if (rv < 0) {
   3202                         break;
   3203                     }
   3204                     SOC_PBMP_CLEAR(tports);
   3205                     hg_trunk_bmap_f = soc_reg64_field_get(unit,
   3206                                                           hg_trunk_bmap,
   3207                                                           val64,
   3208                                                           HIGIG_TRUNK_BITMAPf);
   3209                     SOC_PBMP_WORD_SET(tports,
   3210                                       0,
   3211                                       COMPILER_64_LO(hg_trunk_bmap_f));
   3212                     SOC_PBMP_WORD_SET(tports,
   3213                                       1,
   3214                                       COMPILER_64_HI(hg_trunk_bmap_f));
   3215                     SOC_PBMP_ASSIGN(tpbm, *pbmp_ptr);
   3216                     SOC_PBMP_AND(tpbm, tports);
   3217                     if (SOC_PBMP_NOT_NULL(tpbm)) {
   3218                         SOC_PBMP_OR(*pbmp_ptr, tports);
   3219                     }
   3220                 }
   3221             }
   3222 #endif /* BCM_TRIUMPH2_SUPPORT */
   3223 #if defined(BCM_GREYHOUND2_SUPPORT)
   3224             else if (SOC_IS_GREYHOUND2(unit)) {
   3225                 uint64 val64;
   3226                 for (tid = 0; tid < TRUNK_CNTL(unit).ngroups_hg; tid++) {
   3227                     uint64 hg_trunk_bmap_f;
   3228                     rv = soc_reg_get(unit, hg_trunk_bmap,
   3229                                      REG_PORT_ANY, tid, &val64);
   3230                     if (rv < 0) {
   3231                         break;
   3232                     }
   3233                     SOC_PBMP_CLEAR(tports);
   3234                     hg_trunk_bmap_f = soc_reg64_field_get(unit,
   3235                                                           hg_trunk_bmap,
   3236                                                           val64,
   3237                                                           HIGIG_TRUNK_BITMAPf);
   3238                     SOC_PBMP_WORD_SET(tports,
   3239                                       0,
   3240                                       COMPILER_64_LO(hg_trunk_bmap_f));
   3241                     SOC_PBMP_WORD_SET(tports,
   3242                                       1,
   3243                                       COMPILER_64_HI(hg_trunk_bmap_f));
   3244 
   3245                     /* The maximum port number for Greyhound2 is 66 */
   3246                     rv = soc_reg_get(unit, HG_TRUNK_BITMAP_HIr,
   3247                                      REG_PORT_ANY, tid, &val64);
   3248                     if (rv < 0) {
   3249                         break;
   3250                     }
   3251                     hg_trunk_bmap_f = soc_reg64_field_get(unit,
   3252                                                           HG_TRUNK_BITMAP_HIr,
   3253                                                           val64,
   3254                                                           HIGIG_TRUNK_BITMAPf);
   3255                     SOC_PBMP_WORD_SET(tports,
   3256                                       2,
   3257                                       COMPILER_64_LO(hg_trunk_bmap_f));
   3258 
   3259                     SOC_PBMP_ASSIGN(tpbm, *pbmp_ptr);
   3260                     SOC_PBMP_AND(tpbm, tports);
   3261                     if (SOC_PBMP_NOT_NULL(tpbm)) {
   3262                         SOC_PBMP_OR(*pbmp_ptr, tports);
   3263                     }
   3264                 }
   3265             }
   3266 #endif /* BCM_GREYHOUND2_SUPPORT */
   3267 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT)
   3268             else if (SOC_REG_IS_VALID(unit, hg_trunk_bmap)) {
   3269                 uint64 val64;
   3270                 for (tid = 0; tid < TRUNK_CNTL(unit).ngroups_hg; tid++) {
   3271                     uint64    hg_trunk_bmap_f;
   3272                     rv = soc_reg_get(unit, hg_trunk_bmap, REG_PORT_ANY, tid, &val64);
   3273                     if (rv < 0) {
   3274                         break;
   3275                     }
   3276                     SOC_PBMP_CLEAR(tports);
   3277                     hg_trunk_bmap_f = soc_reg64_field_get(unit,
   3278                                                           hg_trunk_bmap,    
   3279                                                           val64,
   3280                                                           HIGIG_TRUNK_BITMAPf);
   3281                     SOC_PBMP_WORD_SET(tports,
   3282                                       0,
   3283                                       COMPILER_64_LO(hg_trunk_bmap_f));
   3284                     soc_xgs3_higig_bitmap_to_bitmap(unit, tports, &tports);
   3285                     SOC_PBMP_ASSIGN(tpbm, *pbmp_ptr);
   3286                     SOC_PBMP_AND(tpbm, tports);
   3287                     if (SOC_PBMP_NOT_NULL(tpbm)) {
   3288                         SOC_PBMP_OR(*pbmp_ptr, tports);
   3289                     }
   3290                 }
   3291             }
   3292 #endif /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */
   3293 #ifdef BCM_TRIDENT_SUPPORT
   3294             else if (soc_mem_is_valid(unit, HG_TRUNK_BITMAPm)) {
   3295                 hg_trunk_bitmap_entry_t hg_trunk_bitmap_entry;
   3296 
   3297                 for (tid = 0; tid < TRUNK_CNTL(unit).ngroups_hg; tid++) {
   3298                     rv = READ_HG_TRUNK_BITMAPm(unit, MEM_BLOCK_ANY, tid, &hg_trunk_bitmap_entry);
   3299                     if (SOC_FAILURE(rv)) {
   3300                         TRUNK_UNLOCK(unit);
   3301                         return (rv);
   3302                     }
   3303                     SOC_PBMP_CLEAR(tports);
   3304                     soc_mem_pbmp_field_get(unit, HG_TRUNK_BITMAPm, &hg_trunk_bitmap_entry,
   3305                             HIGIG_TRUNK_BITMAPf, &tports);
   3306 
   3307                     SOC_PBMP_ASSIGN(tpbm, in_pbm);
   3308                     SOC_PBMP_AND(tpbm, tports);
   3309                     if (SOC_PBMP_NOT_NULL(tpbm)) {
   3310                         SOC_PBMP_OR(*pbmp_ptr, tports);
   3311                     }
   3312                 }
   3313             }
   3314 #endif /* BCM_TRIDENT_SUPPORT */
   3315         }
   3316 #if defined(BCM_TRIDENT_SUPPORT)
   3317         if (soc_feature(unit, soc_feature_shared_trunk_member_table)) {
   3318             trident_trunk_arch = TRUE;
   3319         }
   3320 #endif /* BCM_TRIDENT_SUPPORT */
   3321         if (!(hg_trunk && SOC_IS_FBX(unit)) || trident_trunk_arch) {
   3322             trunk_bitmap_entry_t trunk_bitmap_entry;
   3323 
   3324             for (tid = 0; tid < TRUNK_CNTL(unit).ngroups_fp; tid++) {
   3325                 rv = READ_TRUNK_BITMAPm(unit, MEM_BLOCK_ANY, tid,
   3326                                 &trunk_bitmap_entry);
   3327                 if (rv < 0) {
   3328                     break;
   3329                 }
   3330 
   3331                 SOC_PBMP_CLEAR(tports);
   3332 
   3333                 soc_mem_pbmp_field_get(unit, TRUNK_BITMAPm, &trunk_bitmap_entry,
   3334                                            TRUNK_BITMAPf, &tports);
   3335 
   3336                 SOC_PBMP_ASSIGN(tpbm, in_pbm);
   3337                 SOC_PBMP_AND(tpbm, tports);
   3338                 if (SOC_PBMP_NOT_NULL(tpbm)) {
   3339                     SOC_PBMP_OR(*pbmp_ptr, tports);
   3340                 }
   3341             }
   3342         }
   3343     }
   3344 #endif	/* BCM_XGS_SWITCH_SUPPORT */
   3345 
   3346 #ifdef	BCM_XGS12_FABRIC_SUPPORT
   3347     if (SOC_IS_XGS12_FABRIC(unit)) {
   3348         uint32     val;
   3349         bcm_port_t    port;
   3350 
   3351         for (tid = 0; tid < TRUNK_CNTL(unit).ngroups_hg; tid++) {
   3352              PBMP_HG_ITER(unit, port) {
   3353                  rv = READ_ING_HGTRUNKr(unit, port, tid, &val);
   3354                  break;
   3355              }
   3356              if (rv < 0) {
   3357                  break;
   3358              }
   3359             SOC_PBMP_CLEAR(tports);
   3360     /*    coverity[uninit_use_in_call : FALSE]    */
   3361             SOC_PBMP_WORD_SET(tports, 0, soc_reg_field_get(unit,
   3362                               ING_HGTRUNKr, val, BMAPf));
   3363             SOC_PBMP_ASSIGN(tpbm, *pbmp_ptr);
   3364             SOC_PBMP_AND(tpbm, tports);
   3365             if (SOC_PBMP_NOT_NULL(tpbm)) {
   3366                 SOC_PBMP_OR(*pbmp_ptr, tports);
   3367             }
   3368         }
   3369     }
   3370 #endif	/* BCM_XGS_FABRIC_SUPPORT */
   3371 
   3372     TRUNK_UNLOCK(unit);
   3373 
   3374     return rv;
   3375 }
   3376 
   3377 /*
   3378  * Function:
   3379  *	bcm_trunk_egress_set
   3380  * Description:
   3381  *	Set switching only to indicated ports from given trunk.
   3382  * Parameters:
   3383  *	unit - StrataSwitch PCI device unit number (driver internal).
   3384  *      tid - Trunk Id.  Negative trunk id means set all trunks.
   3385  *	pbmp - bitmap of ports to allow egress.
   3386  * Returns:
   3387  *      BCM_E_xxxx
   3388  */
   3389 int
   3390 bcm_esw_trunk_egress_set(int unit, bcm_trunk_t tid, bcm_pbmp_t pbmp)
   3391 {
   3392     trunk_egr_mask_entry_t    tem_entry;
   3393     bcm_trunk_t               tid_min, tid_max;
   3394 
   3395     TRUNK_INIT(unit);
   3396     if (soc_feature(unit,soc_feature_trunk_egress)) {
   3397         if (tid >= TRUNK_CNTL(unit).ngroups_fp) {
   3398             return BCM_E_BADID;
   3399         }
   3400 
   3401         if (!SOC_IS_XGS_SWITCH(unit)) {
   3402             if (BCM_PBMP_EQ(pbmp, PBMP_ALL(unit))) {
   3403                 return BCM_E_NONE;
   3404             } else {
   3405                 return BCM_E_UNAVAIL;
   3406             }
   3407         }
   3408 
   3409         sal_memset(&tem_entry, 0, sizeof(trunk_egr_mask_entry_t));
   3410 
   3411         BCM_PBMP_NEGATE(pbmp, pbmp);
   3412         BCM_PBMP_AND(pbmp, PBMP_ALL(unit));
   3413         BCM_PBMP_REMOVE(pbmp, PBMP_LB(unit));
   3414         soc_mem_pbmp_field_set(unit, TRUNK_EGR_MASKm, &tem_entry,
   3415                                TRUNK_EGRESS_MASKf, &pbmp);
   3416 
   3417         if (tid < 0) {
   3418             tid_min = 0;
   3419             tid_max = TRUNK_CNTL(unit).ngroups_fp - 1;
   3420         } else if (TRUNK_INFO(unit, tid).tid == BCM_TRUNK_INVALID) {
   3421             return BCM_E_NOT_FOUND;
   3422         } else {
   3423             tid_min = tid_max = tid;
   3424         }
   3425 
   3426         for (tid = tid_min; tid <= tid_max; tid++) {
   3427             if (TRUNK_INFO(unit, tid).tid == BCM_TRUNK_INVALID) {
   3428                 continue;
   3429             }
   3430             BCM_IF_ERROR_RETURN
   3431                 (WRITE_TRUNK_EGR_MASKm(unit, MEM_BLOCK_ALL, tid, &tem_entry));
   3432 
   3433         }
   3434     } else {
   3435         return BCM_E_UNAVAIL;
   3436     }
   3437     return BCM_E_NONE;
   3438 }
   3439 
   3440 /*
   3441  * Function:
   3442  *	bcm_trunk_egress_get
   3443  * Description:
   3444  *	Retrieve bitmap of ports for which switching is enabled for trunk.
   3445  * Parameters:
   3446  *	unit - StrataSwitch PCI device unit number (driver internal).
   3447  *      tid - Trunk Id.  Negative trunk id means choose any trunk.
   3448  *	pbmp - (OUT) bitmap of ports where egress allowed.
   3449  * Returns:
   3450  *      BCM_E_xxxx
   3451  */
   3452 int
   3453 bcm_esw_trunk_egress_get(int unit, bcm_trunk_t tid, bcm_pbmp_t *pbmp)
   3454 {
   3455     trunk_egr_mask_entry_t    tem_entry;
   3456     bcm_pbmp_t                tem_pbmp;
   3457 
   3458     TRUNK_INIT(unit);
   3459     if (soc_feature(unit,soc_feature_trunk_egress)) {
   3460         if (tid >= TRUNK_CNTL(unit).ngroups_fp) {
   3461             return BCM_E_BADID;
   3462         }
   3463 
   3464         if (!SOC_IS_XGS_SWITCH(unit)) {
   3465             BCM_PBMP_ASSIGN(*pbmp, PBMP_ALL(unit));
   3466             return BCM_E_NONE;
   3467         }
   3468 
   3469         if (tid < 0) {
   3470     	tid = 0;
   3471         }
   3472 
   3473         if (TRUNK_INFO(unit, tid).tid == BCM_TRUNK_INVALID) {
   3474             return BCM_E_NOT_FOUND;
   3475         }
   3476 
   3477         BCM_PBMP_CLEAR(tem_pbmp);
   3478 
   3479         BCM_IF_ERROR_RETURN
   3480             (READ_TRUNK_EGR_MASKm(unit, MEM_BLOCK_ANY, tid, &tem_entry));
   3481 
   3482         soc_mem_pbmp_field_get(unit, TRUNK_EGR_MASKm, &tem_entry,
   3483                                TRUNK_EGRESS_MASKf, &tem_pbmp);
   3484 
   3485         BCM_PBMP_ASSIGN(*pbmp, PBMP_ALL(unit));
   3486         BCM_PBMP_REMOVE(*pbmp, PBMP_LB(unit));
   3487         BCM_PBMP_XOR(*pbmp, tem_pbmp);
   3488     } else{
   3489         return BCM_E_UNAVAIL;
   3490     }
   3491 
   3492     return BCM_E_NONE;
   3493 }
   3494 
   3495 #if defined(BCM_HERCULES15_SUPPORT) || defined(BCM_FIREBOLT_SUPPORT)
   3496 #define _TRUNK_OVERRIDE_CHECK(_u, _p, _tid) \
   3497         TRUNK_INIT(_u); \
   3498         if (!SOC_IS_HERCULES15(_u) && (!SOC_IS_FBX(_u) || \
   3499         !soc_feature(_u, soc_feature_hg_trunk_override)))  \
   3500            { return (BCM_E_UNAVAIL); } \
   3501         if (!TRUNK_FABRIC_TID(_u, _tid)) \
   3502            { return (BCM_E_PARAM); } \
   3503         if ((_p >= 0) && !IS_PORT(_u, _p)) \
   3504            { return (BCM_E_PARAM); }
   3505 #ifdef BCM_HERCULES15_SUPPORT
   3506 #define _UCAST_RANGE_CHECK(_u, _id) \
   3507         if (SOC_IS_HERCULES15(_u)) { \
   3508             if ((_id < soc_mem_index_min(_u, MEM_UCm) || \
   3509                 _id > soc_mem_index_max(_u, MEM_UCm))) \
   3510             { return (BCM_E_PARAM); } \
   3511          } else if (soc_mem_is_valid(_u, MODPORT_MAPm)) { \
   3512             if ((_id < soc_mem_index_min(_u, MODPORT_MAPm) || \
   3513                 _id > soc_mem_index_max(_u, MODPORT_MAPm))) \
   3514              { return (BCM_E_PARAM); } \
   3515          } else if (soc_mem_is_valid(_u, MODPORT_MAP_SWm)) { \
   3516             if ((_id < soc_mem_index_min(_u, MODPORT_MAP_SWm) || \
   3517                 _id > soc_mem_index_max(_u, MODPORT_MAP_SWm))) \
   3518              { return (BCM_E_PARAM); }}
   3519 #define _MCAST_RANGE_CHECK(_u, _id) \
   3520         if (SOC_IS_HERCULES15(_u)) { \
   3521             if ((_id < soc_mem_index_min(_u, MEM_MCm) || \
   3522                 _id > soc_mem_index_max(_u, MEM_MCm))) \
   3523             { return (BCM_E_PARAM); } \
   3524         } else { \
   3525             if ((_id < soc_mem_index_min(_u, L2MCm) || \
   3526                 _id > soc_mem_index_max(_u, L2MCm))) \
   3527              { return (BCM_E_PARAM); }}
   3528 #define _IPMC_RANGE_CHECK(_u, _id) \
   3529         if (SOC_IS_HERCULES15(_u)) { \
   3530             if ((_id < soc_mem_index_min(_u, MEM_IPMCm) || \
   3531                 _id > soc_mem_index_max(_u, MEM_IPMCm))) \
   3532             { return (BCM_E_PARAM); } \
   3533         } else { \
   3534 	    if ((_id < soc_mem_index_min(_u, L3_IPMCm) || \
   3535                 _id > soc_mem_index_max(_u, L3_IPMCm))) \
   3536             { return (BCM_E_PARAM); }}
   3537 #define _VLAN_RANGE_CHECK(_u, _id) \
   3538         if (SOC_IS_HERCULES15(_u)) { \
   3539             if ((_id < soc_mem_index_min(_u, MEM_VIDm) || \
   3540                 _id > soc_mem_index_max(_u, MEM_VIDm))) \
   3541             { return (BCM_E_PARAM); } \
   3542         } else { \
   3543             if ((_id < soc_mem_index_min(_u, VLAN_TABm) || \
   3544                 _id > soc_mem_index_max(_u, VLAN_TABm))) \
   3545              { return (BCM_E_PARAM); }}
   3546 #else  /* BCM_HERCULES15_SUPPORT */
   3547 #define _UCAST_RANGE_CHECK(_u, _id) \
   3548          if (soc_mem_is_valid(_u, MODPORT_MAPm)) { \
   3549             if ((_id < soc_mem_index_min(_u, MODPORT_MAPm) || \
   3550                 _id > soc_mem_index_max(_u, MODPORT_MAPm))) \
   3551              { return (BCM_E_PARAM); } \
   3552          } else if (soc_mem_is_valid(_u, MODPORT_MAP_SWm)) { \
   3553             if ((_id < soc_mem_index_min(_u, MODPORT_MAP_SWm) || \
   3554                 _id > soc_mem_index_max(_u, MODPORT_MAP_SWm))) \
   3555              { return (BCM_E_PARAM); }}
   3556 #define _MCAST_RANGE_CHECK(_u, _id) \
   3557         { \
   3558             if ((_id < soc_mem_index_min(_u, L2MCm) || \
   3559                 _id > soc_mem_index_max(_u, L2MCm))) \
   3560              { return (BCM_E_PARAM); }}
   3561 #define _IPMC_RANGE_CHECK(_u, _id) \
   3562         { \
   3563 	    if ((_id < soc_mem_index_min(_u, L3_IPMCm) || \
   3564                 _id > soc_mem_index_max(_u, L3_IPMCm))) \
   3565             { return (BCM_E_PARAM); }}
   3566 #define _VLAN_RANGE_CHECK(_u, _id) \
   3567         { \
   3568             if ((_id < soc_mem_index_min(_u, VLAN_TABm) || \
   3569                 _id > soc_mem_index_max(_u, VLAN_TABm))) \
   3570              { return (BCM_E_PARAM); }}
   3571 #endif  /* BCM_HERCULES15_SUPPORT */
   3572 #endif  /* BCM_HERCULES15_SUPPORT  || BCM_FIREBOLT_SUPPORT */
   3573 
   3574 /*
   3575  * Function:
   3576  *      bcm_trunk_override_ucast_set
   3577  * Description:
   3578  *      Set the trunk override over UC.
   3579  * Parameters:
   3580  *      unit   - StrataSwitch PCI device unit number (driver internal).
   3581  *      port   - Port number, -1 to all ports.
   3582  *      tid    - Trunk id.
   3583  *      modid  - Module id.
   3584  *      enable - TRUE if enabled, FALSE if disabled.
   3585  * Returns:
   3586  *      BCM_E_xxxx
   3587  */
   3588 
   3589 int
   3590 bcm_esw_trunk_override_ucast_set(int unit, bcm_port_t port,
   3591                              bcm_trunk_t tid, int modid, int enable)
   3592 {
   3593 #if defined(BCM_HERCULES15_SUPPORT) || defined(BCM_FIREBOLT_SUPPORT)
   3594     int rv=BCM_E_NONE;
   3595 
   3596     if (port >= 0) {
   3597         if (BCM_GPORT_IS_SET(port)) {
   3598             bcm_trunk_t     tgid;
   3599             int             id;
   3600 
   3601             BCM_IF_ERROR_RETURN(
   3602                 _bcm_esw_gport_resolve(unit, port, &modid, &port, &tgid, &id));
   3603             if ((-1 != id) || (-1 != tgid)){
   3604                 return BCM_E_PARAM;
   3605             }
   3606         } else {
   3607             if (!SOC_PORT_VALID(unit, port)) {
   3608                 return BCM_E_PORT;
   3609             }
   3610         }
   3611     }
   3612     _TRUNK_OVERRIDE_CHECK(unit, port, tid);
   3613     _UCAST_RANGE_CHECK(unit, modid);
   3614 
   3615 #ifdef  BCM_HERCULES15_SUPPORT
   3616     if (SOC_IS_HERCULES15(unit)) {
   3617         mem_uc_entry_t      uc;
   3618         soc_field_t tf[] = {TRUNK0_OVER_UCf,TRUNK1_OVER_UCf,
   3619                             TRUNK2_OVER_UCf,TRUNK3_OVER_UCf};
   3620         int bk=-1, blk;
   3621 
   3622         if (port >= 0) {
   3623             bk = SOC_PORT_BLOCK(unit, port);
   3624         }
   3625 
   3626         soc_mem_lock(unit, MEM_UCm);
   3627         SOC_MEM_BLOCK_ITER(unit, MEM_UCm, blk) {
   3628             if ((port >= 0) && (bk != blk)) {
   3629                 continue;
   3630             }
   3631             rv = READ_MEM_UCm(unit, blk, modid, &uc);
   3632             if (rv >= 0) {
   3633                 soc_MEM_UCm_field32_set(unit, &uc,
   3634                                         tf[tid], enable ? 1: 0);
   3635                 rv = WRITE_MEM_UCm(unit, blk, modid, &uc);
   3636             }
   3637         }
   3638         soc_mem_unlock(unit, MEM_UCm);
   3639     }
   3640 #endif /* BCM_HERCULES15_SUPPORT */
   3641 
   3642 #ifdef BCM_FIREBOLT_SUPPORT
   3643 
   3644     if ((SOC_IS_FBX(unit) || SOC_IS_RAVEN(unit)) && 
   3645         (soc_feature(unit,soc_feature_hg_trunk_override)) ) { 
   3646         modport_map_entry_t uc;
   3647         uint32 val, hgo_bit;
   3648         int i, min, max, idx, modid_count;
   3649         soc_mem_t modport_map_mem;
   3650 
   3651         modid_count = SOC_MODID_MAX(unit) + 1;
   3652         if (soc_mem_is_valid(unit, MODPORT_MAP_SWm)) {
   3653             modport_map_mem = MODPORT_MAP_SWm;
   3654         } else { 
   3655             modport_map_mem = MODPORT_MAPm;
   3656         }
   3657         min = soc_mem_index_min(unit, modport_map_mem) / modid_count;
   3658         max = soc_mem_index_max(unit, modport_map_mem) / modid_count;
   3659         if (SOC_IS_HBX(unit)) {
   3660             if (port >= min && port <= max) {
   3661                 min = max = port;
   3662             }
   3663         }
   3664 
   3665 #ifdef BCM_TRIUMPH_SUPPORT
   3666         if (soc_feature(unit, soc_feature_modport_map_profile)) {
   3667             bcm_port_t ing_port;
   3668             bcm_trunk_t hgtid;
   3669             bcm_pbmp_t all_pbmp;
   3670 
   3671             BCM_PBMP_CLEAR(all_pbmp);
   3672             BCM_PBMP_ASSIGN(all_pbmp, PBMP_ALL(unit));
   3673 #if defined(BCM_KATANA2_SUPPORT)
   3674             if (soc_feature(unit, soc_feature_linkphy_coe) ||
   3675                 soc_feature(unit, soc_feature_subtag_coe)) {
   3676                 _bcm_kt2_subport_pbmp_update(unit, &all_pbmp);
   3677             }
   3678             if (SOC_IS_KATANA2(unit) &&
   3679                 soc_feature(unit, soc_feature_flex_port)) {
   3680                 BCM_IF_ERROR_RETURN(
   3681                     _bcm_kt2_flexio_pbmp_update(unit,
   3682                     &all_pbmp));
   3683             }
   3684 #endif
   3685 
   3686             hgtid = tid - TRUNK_CNTL(unit).ngroups_fp;
   3687             if (port == BCM_GPORT_INVALID) {
   3688                 PBMP_ITER(all_pbmp, ing_port) {
   3689 #ifdef BCM_TRIDENT_SUPPORT
   3690                     if (soc_feature(unit,
   3691                                 soc_feature_modport_map_dest_is_port_or_trunk)) {
   3692                         BCM_IF_ERROR_RETURN
   3693                             (bcm_td_stk_trunk_override_ucast_set(unit,
   3694                                 ing_port, hgtid, modid, enable));
   3695                     } else
   3696 #endif /* BCM_TRIDENT_SUPPORT */
   3697                     {
   3698                         BCM_IF_ERROR_RETURN
   3699                             (_bcm_esw_tr_trunk_override_ucast_set(unit,
   3700                                 ing_port, hgtid, modid, enable));
   3701                     }
   3702                 }
   3703             } else {
   3704 #ifdef BCM_TRIDENT_SUPPORT
   3705                 if (soc_feature(unit,
   3706                             soc_feature_modport_map_dest_is_port_or_trunk)) {
   3707                     BCM_IF_ERROR_RETURN
   3708                         (bcm_td_stk_trunk_override_ucast_set(unit,
   3709                             port, hgtid, modid, enable));
   3710                 } else
   3711 #endif /* BCM_TRIDENT_SUPPORT */
   3712                 {
   3713                     BCM_IF_ERROR_RETURN
   3714                         (_bcm_esw_tr_trunk_override_ucast_set(unit,
   3715                             port, hgtid, modid, enable));
   3716                 }
   3717             }
   3718         } else 
   3719 #endif /* BCM_TRIUMPH_SUPPORT */
   3720         {
   3721             soc_mem_lock(unit, MODPORT_MAPm);
   3722             for (i = min; i <= max; i++) {
   3723                 idx = i * modid_count + modid;
   3724                 rv = READ_MODPORT_MAPm(unit, MEM_BLOCK_ANY, idx, &uc);
   3725                 if (rv >= 0) {
   3726                     hgo_bit = 1 << (tid - TRUNK_CNTL(unit).ngroups_fp);
   3727                     val = soc_MODPORT_MAPm_field32_get(unit, &uc,
   3728                             HIGIG_TRUNK_OVERRIDEf);
   3729                     if (enable) {
   3730                         val |= hgo_bit;
   3731                     } else {
   3732                         val &= ~hgo_bit;
   3733                     }
   3734                     soc_MODPORT_MAPm_field32_set(unit, &uc,
   3735                             HIGIG_TRUNK_OVERRIDEf, val);
   3736                     rv = WRITE_MODPORT_MAPm(unit, MEM_BLOCK_ALL, idx, &uc);
   3737                 }
   3738             }
   3739             soc_mem_unlock(unit, MODPORT_MAPm);
   3740         }
   3741     }
   3742 #endif /* BCM_FIREBOLT_SUPPORT */
   3743 
   3744     return rv;
   3745 #else
   3746     return BCM_E_UNAVAIL;
   3747 #endif  /* BCM_HERCULES15_SUPPORT  || BCM_FIREBOLT_SUPPORT */
   3748 }
   3749 
   3750 /*
   3751  * Function:
   3752  *      bcm_trunk_override_ucast_get
   3753  * Description:
   3754  *      Get the trunk override over UC.
   3755  * Parameters:
   3756  *      unit   - StrataSwitch PCI device unit number (driver internal).
   3757  *      port   - Port number.
   3758  *      tid    - Trunk id.
   3759  *      modid  - Module id.
   3760  *      enable - (OUT) TRUE if enabled, FALSE if disabled.
   3761  * Returns:
   3762  *      BCM_E_xxxx
   3763  */
   3764 
   3765 int
   3766 bcm_esw_trunk_override_ucast_get(int unit, bcm_port_t port,
   3767                              bcm_trunk_t tid, int modid, int *enable)
   3768 {
   3769 #if defined(BCM_HERCULES15_SUPPORT) || defined(BCM_FIREBOLT_SUPPORT)
   3770     int rv=BCM_E_NONE;
   3771 
   3772     if (BCM_GPORT_IS_SET(port)) {
   3773         bcm_trunk_t     tgid;
   3774         int             id;
   3775 
   3776         BCM_IF_ERROR_RETURN(
   3777             _bcm_esw_gport_resolve(unit, port, &modid, &port, &tgid, &id));
   3778         if ((-1 != id) || (-1 != tgid)){
   3779             return BCM_E_PARAM;
   3780         }
   3781     } else {
   3782         if (!SOC_PORT_VALID(unit, port)) {
   3783             return BCM_E_PORT;
   3784         }
   3785     }
   3786     
   3787     _TRUNK_OVERRIDE_CHECK(unit, port, tid);
   3788     _UCAST_RANGE_CHECK(unit, modid);
   3789 
   3790 #ifdef  BCM_HERCULES15_SUPPORT
   3791     if (SOC_IS_HERCULES15(unit)) {
   3792         mem_uc_entry_t      uc;
   3793         soc_field_t tf[] = {TRUNK0_OVER_UCf,TRUNK1_OVER_UCf,
   3794                             TRUNK2_OVER_UCf,TRUNK3_OVER_UCf};
   3795         int blk;
   3796 
   3797         *enable = 0;
   3798 
   3799         blk = SOC_PORT_BLOCK(unit, port);
   3800         rv = READ_MEM_UCm(unit, blk, modid, &uc);
   3801         if (rv >= 0) {
   3802             *enable = soc_MEM_UCm_field32_get(unit, &uc, tf[tid]);
   3803         }
   3804     }
   3805 #endif /* BCM_HERCULES15_SUPPORT */
   3806 
   3807 #ifdef BCM_FIREBOLT_SUPPORT
   3808 
   3809     if ((SOC_IS_FBX(unit) || SOC_IS_RAVEN(unit)) && 
   3810         (soc_feature(unit,soc_feature_hg_trunk_override)) ) { 
   3811         modport_map_entry_t uc;
   3812         uint32 val, hgo_bit;
   3813         int idx;
   3814 
   3815         if (SOC_IS_FB_FX_HX(unit) || SOC_IS_TR_VL(unit)) {
   3816             idx = modid;
   3817         } else {
   3818             idx = (port * (SOC_MODID_MAX(unit) + 1)) + modid;
   3819         }
   3820 #ifdef BCM_TRIUMPH_SUPPORT
   3821         if (soc_feature(unit, soc_feature_modport_map_profile)) {
   3822             bcm_trunk_t hgtid;
   3823             hgtid = tid - TRUNK_CNTL(unit).ngroups_fp;
   3824 #ifdef BCM_TRIDENT_SUPPORT
   3825             if (soc_feature(unit, soc_feature_modport_map_dest_is_port_or_trunk)) {
   3826                 rv = bcm_td_stk_trunk_override_ucast_get(unit, port, hgtid,
   3827                         modid, enable);
   3828             } else
   3829 #endif /* BCM_TRIDENT_SUPPORT */
   3830             {
   3831                 rv = _bcm_esw_tr_trunk_override_ucast_get(unit, port, hgtid,
   3832                         modid, enable); 
   3833             }
   3834         } else 
   3835 #endif /* BCM_TRIUMPH_SUPPORT */
   3836         {
   3837             *enable = 0;
   3838 
   3839             rv = READ_MODPORT_MAPm(unit, MEM_BLOCK_ANY, idx, &uc);
   3840             if (rv >= 0) {
   3841                 val = soc_MODPORT_MAPm_field32_get(unit, &uc,
   3842                                                    HIGIG_TRUNK_OVERRIDEf);
   3843                 hgo_bit = 1 << (tid - TRUNK_CNTL(unit).ngroups_fp);
   3844                 *enable = (val & hgo_bit) ? 1 : 0;
   3845             }
   3846         }
   3847     }
   3848 #endif /* BCM_FIREBOLT_SUPPORT */
   3849 
   3850     return rv;
   3851 #else
   3852     return BCM_E_UNAVAIL;
   3853 #endif  /* BCM_HERCULES15_SUPPORT */
   3854 }
   3855 
   3856 /*
   3857  * Function:
   3858  *      bcm_trunk_override_mcast_set
   3859  * Description:
   3860  *      Set the trunk override over MC.
   3861  * Parameters:
   3862  *      unit   - StrataSwitch PCI device unit number (driver internal).
   3863  *      port   - Port number, -1 to all ports.
   3864  *      tid    - Trunk id.
   3865  *      idx    - MC index carried in HiGig header.
   3866  *      enable - TRUE if enabled, FALSE if disabled.
   3867  * Returns:
   3868  *      BCM_E_xxxx
   3869  */
   3870 
   3871 int
   3872 bcm_esw_trunk_override_mcast_set(int unit, bcm_port_t port,
   3873                                  bcm_trunk_t tid, int idx, int enable)
   3874 {
   3875 #if defined(BCM_HERCULES15_SUPPORT) || defined(BCM_FIREBOLT_SUPPORT)
   3876     int rv=BCM_E_NONE;
   3877 
   3878     /* Translate multicast group ID's */
   3879     if (_BCM_MULTICAST_IS_L2(idx)) {
   3880         idx = _BCM_MULTICAST_ID_GET(idx);
   3881     } else if (_BCM_MULTICAST_IS_SET(idx)) {
   3882         /* This is a non-L2 multicast group.
   3883          * Redirect to the IPMC version below */
   3884         idx = _BCM_MULTICAST_ID_GET(idx);
   3885         return bcm_esw_trunk_override_ipmc_set(unit, port, tid,
   3886                                                idx, enable);
   3887     }
   3888 
   3889     if (port >= 0) {
   3890         if (BCM_GPORT_IS_SET(port)) {
   3891             bcm_module_t    modid;
   3892             bcm_trunk_t     tgid;
   3893             int             id;
   3894 
   3895             BCM_IF_ERROR_RETURN(
   3896                 _bcm_esw_gport_resolve(unit, port, &modid, &port, &tgid, &id));
   3897             if ((-1 != id) || (-1 != tgid)){
   3898                 return BCM_E_PARAM;
   3899             }
   3900         } else {
   3901             if (!SOC_PORT_VALID(unit, port)) {
   3902                 return BCM_E_PORT;
   3903             }
   3904         }
   3905     }
   3906 
   3907     _TRUNK_OVERRIDE_CHECK(unit, port, tid);
   3908     _MCAST_RANGE_CHECK(unit, idx);
   3909 
   3910 #ifdef BCM_HERCULES15_SUPPORT
   3911     if (SOC_IS_HERCULES15(unit)) {
   3912         mem_mc_entry_t      mc;
   3913         soc_field_t tf[] = {TRUNK0_OVER_MCf,TRUNK1_OVER_MCf,
   3914                             TRUNK2_OVER_MCf,TRUNK3_OVER_MCf};
   3915         int  bk=-1, blk;
   3916 
   3917         if (port >= 0) {
   3918             bk = SOC_PORT_BLOCK(unit, port);
   3919         }
   3920 
   3921         soc_mem_lock(unit, MEM_MCm);
   3922         SOC_MEM_BLOCK_ITER(unit, MEM_MCm, blk) {
   3923             if ((port >= 0) && (bk != blk)) {
   3924                 continue;
   3925             }
   3926             rv = READ_MEM_MCm(unit, blk, idx, &mc);
   3927             if (rv >= 0) {
   3928                 soc_MEM_MCm_field32_set(unit, &mc,
   3929                                         tf[tid], enable ? 1: 0);
   3930                 rv = WRITE_MEM_MCm(unit, blk, idx, &mc);
   3931             }
   3932         }
   3933         soc_mem_unlock(unit, MEM_MCm);
   3934     }
   3935 #endif /* BCM_HERCULES15_SUPPORT */
   3936 
   3937 #ifdef BCM_FIREBOLT_SUPPORT
   3938 
   3939 
   3940     if ((SOC_IS_FBX(unit) || SOC_IS_RAVEN(unit)) && 
   3941         (soc_feature(unit,soc_feature_hg_trunk_override)) ) { 
   3942 
   3943 #ifdef BCM_TRIDENT_SUPPORT
   3944         if (soc_feature(unit, soc_feature_hg_trunk_override_profile)) {
   3945             bcm_trunk_t hgtid;
   3946 
   3947             hgtid = tid - TRUNK_CNTL(unit).ngroups_fp;
   3948             rv = _bcm_trident_trunk_override_mcast_set(unit, hgtid, idx, enable); 
   3949         } else 
   3950 #endif /* BCM_TRIDENT_SUPPORT */
   3951         {
   3952             l2mc_entry_t mc;
   3953             uint32 val, hgo_bit;
   3954 
   3955             soc_mem_lock(unit, L2MCm);
   3956             rv = READ_L2MCm(unit, MEM_BLOCK_ANY, idx, &mc);
   3957             if (rv >= 0) {
   3958                 val = soc_L2MCm_field32_get(unit, &mc,
   3959                         HIGIG_TRUNK_OVERRIDEf);
   3960                 hgo_bit = 1 << (tid - TRUNK_CNTL(unit).ngroups_fp);
   3961                 if (enable) {
   3962                     val |= hgo_bit;
   3963                 } else {
   3964                     val &= ~hgo_bit;
   3965                 }
   3966                 soc_L2MCm_field32_set(unit, &mc,
   3967                         HIGIG_TRUNK_OVERRIDEf, val);
   3968                 rv = WRITE_L2MCm(unit, MEM_BLOCK_ALL, idx, &mc);
   3969             }
   3970             soc_mem_unlock(unit, L2MCm);
   3971         }
   3972     }
   3973 #endif /* BCM_FIREBOLT_SUPPORT */
   3974 
   3975     return rv;
   3976 #else
   3977     return BCM_E_UNAVAIL;
   3978 #endif  /* BCM_HERCULES15_SUPPORT || BCM_FIREBOLT_SUPPORT */
   3979 }
   3980 
   3981 /*
   3982  * Function:
   3983  *      bcm_trunk_override_mcast_get
   3984  * Description:
   3985  *      Get the trunk override over MC.
   3986  * Parameters:
   3987  *      unit   - StrataSwitch PCI device unit number (driver internal).
   3988  *      port   - Port number.
   3989  *      tid    - Trunk id.
   3990  *      idx    - MC index carried in HiGig header.
   3991  *      enable - (OUT) TRUE if enabled, FALSE if disabled.
   3992  * Returns:
   3993  *      BCM_E_xxxx
   3994  */
   3995 
   3996 int
   3997 bcm_esw_trunk_override_mcast_get(int unit, bcm_port_t port,
   3998                                  bcm_trunk_t tid, int idx, int *enable)
   3999 {
   4000 #if defined(BCM_HERCULES15_SUPPORT) || defined(BCM_FIREBOLT_SUPPORT)
   4001     int rv=BCM_E_NONE;
   4002 
   4003     /* Translate multicast group ID's */
   4004     if (_BCM_MULTICAST_IS_L2(idx)) {
   4005         idx = _BCM_MULTICAST_ID_GET(idx);
   4006     } else if (_BCM_MULTICAST_IS_SET(idx)) {
   4007         /* This is a non-L2 multicast group.
   4008          * Redirect to the IPMC version below */
   4009         idx = _BCM_MULTICAST_ID_GET(idx);
   4010         return bcm_esw_trunk_override_ipmc_get(unit, port, tid,
   4011                                                idx, enable);
   4012     }
   4013 
   4014     if (BCM_GPORT_IS_SET(port)) {
   4015         bcm_module_t    modid;
   4016         bcm_trunk_t     tgid;
   4017         int             id;
   4018 
   4019         BCM_IF_ERROR_RETURN(
   4020             _bcm_esw_gport_resolve(unit, port, &modid, &port, &tgid, &id));
   4021         if ((-1 != id) || (-1 != tgid)){
   4022             return BCM_E_PARAM;
   4023         }
   4024     } else {
   4025         if (!SOC_PORT_VALID(unit, port)) {
   4026             return BCM_E_PORT;
   4027         }
   4028     }
   4029 
   4030     _TRUNK_OVERRIDE_CHECK(unit, port, tid);
   4031     _MCAST_RANGE_CHECK(unit, idx);
   4032 
   4033 #ifdef BCM_HERCULES15_SUPPORT
   4034     if (SOC_IS_HERCULES15(unit)) {
   4035         mem_mc_entry_t      mc;
   4036         soc_field_t tf[] = {TRUNK0_OVER_MCf,TRUNK1_OVER_MCf,
   4037                             TRUNK2_OVER_MCf,TRUNK3_OVER_MCf};
   4038         int blk;
   4039 
   4040         *enable = 0;
   4041 
   4042         blk = SOC_PORT_BLOCK(unit, port);
   4043         rv = READ_MEM_MCm(unit, blk, idx, &mc);
   4044         if (rv >= 0) {
   4045             *enable = soc_MEM_MCm_field32_get(unit, &mc, tf[tid]);
   4046         }
   4047     }
   4048 #endif /* SOC_IS_HERCULES15 */
   4049 
   4050 #ifdef BCM_FIREBOLT_SUPPORT
   4051 
   4052     if ((SOC_IS_FBX(unit) || SOC_IS_RAVEN(unit)) && 
   4053             (soc_feature(unit,soc_feature_hg_trunk_override))) { 
   4054 
   4055 #ifdef BCM_TRIDENT_SUPPORT
   4056         if (soc_feature(unit, soc_feature_hg_trunk_override_profile)) {
   4057             int hgtid;
   4058 
   4059             hgtid = tid - TRUNK_CNTL(unit).ngroups_fp;
   4060             rv = _bcm_trident_trunk_override_mcast_get(unit, hgtid, idx, enable); 
   4061         } else
   4062 #endif /* BCM_TRIDENT_SUPPORT */
   4063         {
   4064             l2mc_entry_t mc;
   4065             uint32 val, hgo_bit;
   4066 
   4067             *enable = 0;
   4068 
   4069             rv = READ_L2MCm(unit, MEM_BLOCK_ANY, idx, &mc);
   4070             if (rv >= 0) {
   4071                 val = soc_L2MCm_field32_get(unit, &mc,
   4072                         HIGIG_TRUNK_OVERRIDEf);
   4073                 hgo_bit = 1 << (tid - TRUNK_CNTL(unit).ngroups_fp);
   4074                 *enable = (val & hgo_bit) ? 1 : 0;
   4075             }
   4076         }
   4077     }
   4078 #endif /* BCM_FIREBOLT_SUPPORT */
   4079 
   4080     return rv;
   4081 #else
   4082     return BCM_E_UNAVAIL;
   4083 #endif  /* BCM_HERCULES15_SUPPORT  || BCM_FIREBOLT_SUPPORT */
   4084 }
   4085 
   4086 /*
   4087  * Function:
   4088  *      bcm_trunk_override_ipmc_set
   4089  * Description:
   4090  *      Set the trunk override over IPMC.
   4091  * Parameters:
   4092  *      unit   - StrataSwitch PCI device unit number (driver internal).
   4093  *      port   - Port number, -1 to all ports.
   4094  *      tid    - Trunk id.
   4095  *      idx    - IPMC index carried in HiGig header.
   4096  *      enable - TRUE if enabled, FALSE if disabled.
   4097  * Returns:
   4098  *      BCM_E_xxxx
   4099  */
   4100 
   4101 int
   4102 bcm_esw_trunk_override_ipmc_set(int unit, bcm_port_t port,
   4103                                 bcm_trunk_t tid, int idx, int enable)
   4104 {
   4105 #if defined(BCM_HERCULES15_SUPPORT) || defined(BCM_FIREBOLT_SUPPORT)
   4106     int rv=BCM_E_NONE;
   4107 
   4108     /* Translate multicast group ID's */
   4109     if (_BCM_MULTICAST_IS_L2(idx)) {
   4110         /* This is an L2 multicast group.
   4111          * Redirect to the mcast version above */
   4112         idx = _BCM_MULTICAST_ID_GET(idx);
   4113         return bcm_esw_trunk_override_mcast_set(unit, port, tid,
   4114                                                 idx, enable);
   4115     } else if (_BCM_MULTICAST_IS_SET(idx)) {
   4116         idx = _BCM_MULTICAST_ID_GET(idx);
   4117     }
   4118 
   4119     if (!soc_feature(unit, soc_feature_ip_mcast)) {
   4120         return BCM_E_UNAVAIL;
   4121     }
   4122 
   4123     if (port >= 0) {
   4124         if (BCM_GPORT_IS_SET(port)) {
   4125             bcm_module_t    modid;
   4126             bcm_trunk_t     tgid;
   4127             int             id;
   4128 
   4129             BCM_IF_ERROR_RETURN(
   4130                 _bcm_esw_gport_resolve(unit, port, &modid, &port, &tgid, &id));
   4131             if ((-1 != id) || (-1 != tgid)){
   4132                 return BCM_E_PARAM;
   4133             }
   4134         } else {
   4135             if (!SOC_PORT_VALID(unit, port)) {
   4136                 return BCM_E_PORT;
   4137             }
   4138         }
   4139     }
   4140 
   4141     _TRUNK_OVERRIDE_CHECK(unit, port, tid);
   4142     _IPMC_RANGE_CHECK(unit, idx);
   4143 
   4144 #ifdef  BCM_HERCULES15_SUPPORT
   4145     if (SOC_IS_HERCULES15(unit)) {
   4146         mem_ipmc_entry_t      ipmc;
   4147         soc_field_t tf[] = {TRUNK0_OVER_IPMCf,TRUNK1_OVER_IPMCf,
   4148                             TRUNK2_OVER_IPMCf,TRUNK3_OVER_IPMCf};
   4149         int bk=-1, blk;
   4150 
   4151         if (port >= 0) {
   4152             bk = SOC_PORT_BLOCK(unit, port);
   4153         }
   4154 
   4155         soc_mem_lock(unit, MEM_IPMCm);
   4156         SOC_MEM_BLOCK_ITER(unit, MEM_IPMCm, blk) {
   4157             if ((port >= 0) && (bk != blk)) {
   4158                 continue;
   4159             }
   4160             rv = READ_MEM_IPMCm(unit, blk, idx, &ipmc);
   4161             if (rv >= 0) {
   4162                 soc_MEM_IPMCm_field32_set(unit, &ipmc,
   4163                                           tf[tid], enable ? 1: 0);
   4164                 rv = WRITE_MEM_IPMCm(unit, blk, idx, &ipmc);
   4165             }
   4166         }
   4167         soc_mem_unlock(unit, MEM_IPMCm);
   4168     }
   4169 #endif /* BCM_HERCULES15_SUPPORT */
   4170 
   4171 #ifdef BCM_FIREBOLT_SUPPORT
   4172     if ((SOC_IS_FBX(unit) || SOC_IS_RAVEN(unit)) && 
   4173         (soc_feature(unit,soc_feature_hg_trunk_override)) ) { 
   4174 
   4175 #ifdef BCM_TRIDENT_SUPPORT 
   4176         if (soc_feature(unit, soc_feature_hg_trunk_override_profile)) {
   4177             bcm_trunk_t hgtid;
   4178 
   4179             hgtid = tid - TRUNK_CNTL(unit).ngroups_fp;
   4180             rv = _bcm_trident_trunk_override_ipmc_set(unit, hgtid, idx, enable); 
   4181         } else 
   4182 #endif /* BCM_TRIDENT_SUPPORT */
   4183         {
   4184             ipmc_entry_t ipmc;
   4185             uint32 val, hgo_bit;
   4186 
   4187             soc_mem_lock(unit, L3_IPMCm);
   4188             rv = READ_L3_IPMCm(unit, MEM_BLOCK_ANY, idx, &ipmc);
   4189             if (rv >= 0) {
   4190                 val = soc_L3_IPMCm_field32_get(unit, &ipmc,
   4191                         HIGIG_TRUNK_OVERRIDEf);
   4192                 hgo_bit = 1 << (tid - TRUNK_CNTL(unit).ngroups_fp);
   4193                 if (enable) {
   4194                     val |= hgo_bit;
   4195                 } else {
   4196                     val &= ~hgo_bit;
   4197                 }
   4198                 soc_L3_IPMCm_field32_set(unit, &ipmc,
   4199                         HIGIG_TRUNK_OVERRIDEf, val);
   4200                 rv = WRITE_L3_IPMCm(unit, MEM_BLOCK_ALL, idx, &ipmc);
   4201             }
   4202             soc_mem_unlock(unit, L3_IPMCm);
   4203 
   4204 #if defined(BCM_BRADLEY_SUPPORT)
   4205             if (SOC_IS_HBX(unit)) {
   4206                 l2mc_entry_t mc;
   4207                 uint32 val, hgo_bit;
   4208                 int	mc_base, mc_size, mc_index;
   4209 
   4210                 SOC_IF_ERROR_RETURN
   4211                     (soc_hbx_ipmc_size_get(unit, &mc_base, &mc_size));
   4212                 if (idx < 0 || idx > mc_size) {
   4213                     return BCM_E_PARAM;
   4214                 }
   4215                 mc_index = idx + mc_base;
   4216 
   4217                 soc_mem_lock(unit, L2MCm);
   4218                 rv = READ_L2MCm(unit, MEM_BLOCK_ANY, mc_index, &mc);
   4219                 if (rv >= 0) {
   4220                     val = soc_L2MCm_field32_get(unit, &mc,
   4221                             HIGIG_TRUNK_OVERRIDEf);
   4222                     hgo_bit = 1 << (tid - TRUNK_CNTL(unit).ngroups_fp);
   4223                     if (enable) {
   4224                         val |= hgo_bit;
   4225                     } else {
   4226                         val &= ~hgo_bit;
   4227                     }
   4228                     soc_L2MCm_field32_set(unit, &mc,
   4229                             HIGIG_TRUNK_OVERRIDEf, val);
   4230                     rv = WRITE_L2MCm(unit, MEM_BLOCK_ALL, mc_index, &mc);
   4231                 }
   4232                 soc_mem_unlock(unit, L2MCm);
   4233 
   4234                 
   4235             }
   4236 #endif /* BCM_BRADLEY_SUPPORT */
   4237         }
   4238     }
   4239 #endif /* BCM_FIREBOLT_SUPPORT */
   4240 
   4241     return rv;
   4242 #else
   4243     return BCM_E_UNAVAIL;
   4244 #endif  /* BCM_HERCULES15_SUPPORT || BCM_FIREBOLT_SUPPORT */
   4245 }
   4246 
   4247 /*
   4248  * Function:
   4249  *      bcm_trunk_override_ipmc_get
   4250  * Description:
   4251  *      Get the trunk override over IPMC.
   4252  * Parameters:
   4253  *      unit   - StrataSwitch PCI device unit number (driver internal).
   4254  *      port   - Port number.
   4255  *      tid    - Trunk id.
   4256  *      idx    - IPMC index carried in HiGig header.
   4257  *      enable - (OUT) TRUE if enabled, FALSE if disabled.
   4258  * Returns:
   4259  *      BCM_E_xxxx
   4260  */
   4261 
   4262 int
   4263 bcm_esw_trunk_override_ipmc_get(int unit, bcm_port_t port,
   4264                                 bcm_trunk_t tid, int idx, int *enable)
   4265 {
   4266 #if defined(BCM_HERCULES15_SUPPORT) || defined(BCM_FIREBOLT_SUPPORT)
   4267     int rv=BCM_E_NONE;
   4268 
   4269     /* Translate multicast group ID's */
   4270     if (_BCM_MULTICAST_IS_L2(idx)) {
   4271         /* This is an L2 multicast group.
   4272          * Redirect to the mcast version above */
   4273         idx = _BCM_MULTICAST_ID_GET(idx);
   4274         return bcm_esw_trunk_override_mcast_get(unit, port, tid,
   4275                                                 idx, enable);
   4276     } else if (_BCM_MULTICAST_IS_SET(idx)) {
   4277         idx = _BCM_MULTICAST_ID_GET(idx);
   4278     }
   4279 
   4280     if (!soc_feature(unit, soc_feature_ip_mcast)) {
   4281         return BCM_E_UNAVAIL;
   4282     }
   4283 
   4284     if (BCM_GPORT_IS_SET(port)) {
   4285         bcm_module_t    modid;
   4286         bcm_trunk_t     tgid;
   4287         int             id;
   4288 
   4289         BCM_IF_ERROR_RETURN(
   4290             _bcm_esw_gport_resolve(unit, port, &modid, &port, &tgid, &id));
   4291         if ((-1 != id) || (-1 != tgid)){
   4292             return BCM_E_PARAM;
   4293         }
   4294     } else {
   4295         if (!SOC_PORT_VALID(unit, port)) {
   4296             return BCM_E_PORT;
   4297         }
   4298     }
   4299 
   4300     _TRUNK_OVERRIDE_CHECK(unit, port, tid);
   4301     _IPMC_RANGE_CHECK(unit, idx);
   4302 
   4303 #ifdef  BCM_HERCULES15_SUPPORT
   4304     if (SOC_IS_HERCULES15(unit)) {
   4305         mem_ipmc_entry_t      ipmc;
   4306         soc_field_t tf[] = {TRUNK0_OVER_IPMCf,TRUNK1_OVER_IPMCf,
   4307                             TRUNK2_OVER_IPMCf,TRUNK3_OVER_IPMCf};
   4308         int blk;
   4309 
   4310         *enable = 0;
   4311 
   4312         blk = SOC_PORT_BLOCK(unit, port);
   4313         rv = READ_MEM_IPMCm(unit, blk, idx, &ipmc);
   4314         if (rv >= 0) {
   4315             *enable = soc_MEM_IPMCm_field32_get(unit, &ipmc, tf[tid]);
   4316         }
   4317     }
   4318 #endif /* BCM_HERCULES15_SUPPORT */
   4319 
   4320 #ifdef BCM_FIREBOLT_SUPPORT
   4321 
   4322     if ((SOC_IS_FBX(unit) || SOC_IS_RAVEN(unit)) && 
   4323             (soc_feature(unit,soc_feature_hg_trunk_override)) ) { 
   4324 
   4325 #ifdef BCM_TRIDENT_SUPPORT 
   4326         if (soc_feature(unit, soc_feature_hg_trunk_override_profile)) {
   4327             bcm_trunk_t hgtid;
   4328 
   4329             hgtid = tid - TRUNK_CNTL(unit).ngroups_fp;
   4330             rv = _bcm_trident_trunk_override_ipmc_get(unit, hgtid, idx, enable); 
   4331         } else 
   4332 #endif /* BCM_TRIDENT_SUPPORT */
   4333         {
   4334             ipmc_entry_t ipmc;
   4335             uint32 val, hgo_bit;
   4336 
   4337             *enable = 0;
   4338 
   4339             rv = READ_L3_IPMCm(unit, MEM_BLOCK_ANY, idx, &ipmc);
   4340             if (rv >= 0) {
   4341                 val = soc_L3_IPMCm_field32_get(unit, &ipmc,
   4342                         HIGIG_TRUNK_OVERRIDEf);
   4343                 hgo_bit = 1 << (tid - TRUNK_CNTL(unit).ngroups_fp);
   4344                 *enable = (val & hgo_bit) ? 1 : 0;
   4345             }
   4346         }
   4347     }
   4348 #endif /* BCM_FIREBOLT_SUPPORT */
   4349 
   4350     return rv;
   4351 #else
   4352     return BCM_E_UNAVAIL;
   4353 #endif  /* BCM_HERCULES15_SUPPORT  || BCM_FIREBOLT_SUPPORT */
   4354 }
   4355 
   4356 /*
   4357  * Function:
   4358  *      bcm_trunk_override_vlan_set
   4359  * Description:
   4360  *      Set the trunk override over VLAN.
   4361  * Parameters:
   4362  *      unit   - StrataSwitch PCI device unit number (driver internal).
   4363  *      port   - Port number, -1 to all ports.
   4364  *      tid    - Trunk id.
   4365  *      vid    - VLAN id.
   4366  *      enable - TRUE if enabled, FALSE if disabled.
   4367  * Returns:
   4368  *      BCM_E_xxxx
   4369  */
   4370 
   4371 int
   4372 bcm_esw_trunk_override_vlan_set(int unit, bcm_port_t port,
   4373                             bcm_trunk_t tid, bcm_vlan_t vid, int enable)
   4374 {
   4375 #if defined(BCM_HERCULES15_SUPPORT) || defined(BCM_FIREBOLT_SUPPORT)
   4376     int rv=BCM_E_NONE;
   4377 
   4378     if (port >= 0) {
   4379         if (BCM_GPORT_IS_SET(port)) {
   4380             bcm_module_t    modid;
   4381             bcm_trunk_t     tgid;
   4382             int             id;
   4383 
   4384             BCM_IF_ERROR_RETURN(
   4385                 _bcm_esw_gport_resolve(unit, port, &modid, &port, &tgid, &id));
   4386             if ((-1 != id) || (-1 != tgid)){
   4387                 return BCM_E_PARAM;
   4388             }
   4389         } else {
   4390             if (!SOC_PORT_VALID(unit, port)) {
   4391                 return BCM_E_PORT;
   4392             }
   4393         }
   4394     }
   4395 
   4396     _TRUNK_OVERRIDE_CHECK(unit, port, tid);
   4397     _VLAN_RANGE_CHECK(unit, vid);
   4398 
   4399 #ifdef  BCM_HERCULES15_SUPPORT
   4400     if (SOC_IS_HERCULES15(unit)) {
   4401         mem_vid_entry_t      ve;
   4402         soc_field_t tf[] = {TRUNK0_OVER_VIDf,TRUNK1_OVER_VIDf,
   4403                             TRUNK2_OVER_VIDf,TRUNK3_OVER_VIDf};
   4404         int blk, bk = -1;
   4405 
   4406         if (port >= 0) {
   4407             bk = SOC_PORT_BLOCK(unit, port);
   4408         }
   4409 
   4410         soc_mem_lock(unit, MEM_VIDm);
   4411         SOC_MEM_BLOCK_ITER(unit, MEM_VIDm, blk) {
   4412             if ((port >= 0) && (bk != blk)) {
   4413                 continue;
   4414             }
   4415             rv = READ_MEM_VIDm(unit, blk, vid, &ve);
   4416             if (rv >= 0) {
   4417                 soc_MEM_VIDm_field32_set(unit, &ve,
   4418                                          tf[tid], enable ? 1: 0);
   4419                 rv = WRITE_MEM_VIDm(unit, blk, vid, &ve);
   4420             }
   4421         }
   4422         soc_mem_unlock(unit, MEM_VIDm);
   4423     }
   4424 #endif /* BCM_HERCULES15_SUPPORT */
   4425 
   4426 #ifdef BCM_FIREBOLT_SUPPORT
   4427 
   4428     if ((SOC_IS_FBX(unit) || SOC_IS_RAVEN(unit)) && 
   4429             (soc_feature(unit,soc_feature_hg_trunk_override)) ) { 
   4430 
   4431 #ifdef BCM_TRIDENT_SUPPORT 
   4432         if (soc_feature(unit, soc_feature_hg_trunk_override_profile)) {
   4433             bcm_trunk_t hgtid;
   4434 
   4435             hgtid = tid - TRUNK_CNTL(unit).ngroups_fp;
   4436             rv = _bcm_trident_trunk_override_vlan_set(unit, hgtid, vid, enable); 
   4437         } else 
   4438 #endif /* BCM_TRIDENT_SUPPORT */
   4439         {
   4440             vlan_tab_entry_t ve;
   4441             uint32 val, hgo_bit;
   4442 
   4443             soc_mem_lock(unit, VLAN_TABm);
   4444             rv = READ_VLAN_TABm(unit, MEM_BLOCK_ANY, vid, &ve);
   4445             if (rv >= 0) {
   4446                 val = soc_VLAN_TABm_field32_get(unit, &ve,
   4447                         HIGIG_TRUNK_OVERRIDEf);
   4448                 hgo_bit = 1 << (tid - TRUNK_CNTL(unit).ngroups_fp);
   4449                 if (enable) {
   4450                     val |= hgo_bit;
   4451                 } else {
   4452                     val &= ~hgo_bit;
   4453                 }
   4454                 soc_VLAN_TABm_field32_set(unit, &ve,
   4455                         HIGIG_TRUNK_OVERRIDEf, val);
   4456                 rv = WRITE_VLAN_TABm(unit, MEM_BLOCK_ALL, vid, &ve);
   4457             }
   4458             soc_mem_unlock(unit, VLAN_TABm);
   4459         }
   4460     }
   4461 #endif /* BCM_FIREBOLT_SUPPORT */
   4462 
   4463     return rv;
   4464 #else
   4465     return BCM_E_UNAVAIL;
   4466 #endif  /* BCM_HERCULES15_SUPPORT || BCM_FIREBOLT_SUPPORT */
   4467 }
   4468 
   4469 /*
   4470  * Function:
   4471  *      bcm_trunk_override_vlan_get
   4472  * Description:
   4473  *      Get the trunk override over VLAN.
   4474  * Parameters:
   4475  *      unit   - StrataSwitch PCI device unit number (driver internal).
   4476  *      port   - Port number.
   4477  *      tid    - Trunk id.
   4478  *      vid    - VLAN id.
   4479  *      enable - (OUT) TRUE if enabled, FALSE if disabled.
   4480  * Returns:
   4481  *      BCM_E_xxxx
   4482  */
   4483 
   4484 int
   4485 bcm_esw_trunk_override_vlan_get(int unit, bcm_port_t port,
   4486                             bcm_trunk_t tid, bcm_vlan_t vid, int *enable)
   4487 {
   4488 #if defined(BCM_HERCULES15_SUPPORT) || defined(BCM_FIREBOLT_SUPPORT)
   4489     int rv=BCM_E_NONE;
   4490 
   4491     if (BCM_GPORT_IS_SET(port)) {
   4492         bcm_module_t    modid;
   4493         bcm_trunk_t     tgid;
   4494         int             id;
   4495 
   4496         BCM_IF_ERROR_RETURN(
   4497             _bcm_esw_gport_resolve(unit, port, &modid, &port, &tgid, &id));
   4498         if ((-1 != id) || (-1 != tgid)){
   4499             return BCM_E_PARAM;
   4500         }
   4501     } else {
   4502         if (!SOC_PORT_VALID(unit, port)) {
   4503             return BCM_E_PORT;
   4504         }
   4505     }
   4506 
   4507     _TRUNK_OVERRIDE_CHECK(unit, port, tid);
   4508     _VLAN_RANGE_CHECK(unit, vid);
   4509 
   4510 #ifdef  BCM_HERCULES15_SUPPORT
   4511     if (SOC_IS_HERCULES15(unit)) {
   4512         mem_vid_entry_t      ve;
   4513         soc_field_t tf[] = {TRUNK0_OVER_VIDf,TRUNK1_OVER_VIDf,
   4514                             TRUNK2_OVER_VIDf,TRUNK3_OVER_VIDf};
   4515         int blk;
   4516 
   4517         *enable = 0;
   4518 
   4519         blk = SOC_PORT_BLOCK(unit, port);
   4520         rv = READ_MEM_VIDm(unit, blk, vid, &ve);
   4521         if (rv >= 0) {
   4522             *enable = soc_MEM_VIDm_field32_get(unit, &ve, tf[tid]);
   4523         }
   4524     }
   4525 #endif /* BCM_HERCULES15_SUPPORT */
   4526 
   4527 #ifdef BCM_FIREBOLT_SUPPORT
   4528 
   4529     if ((SOC_IS_FBX(unit) || SOC_IS_RAVEN(unit)) && 
   4530             (soc_feature(unit,soc_feature_hg_trunk_override)) ) {         
   4531 
   4532 #ifdef BCM_TRIDENT_SUPPORT 
   4533         if (soc_feature(unit, soc_feature_hg_trunk_override_profile)) {
   4534             bcm_trunk_t hgtid;
   4535 
   4536             hgtid = tid - TRUNK_CNTL(unit).ngroups_fp;
   4537             rv = _bcm_trident_trunk_override_vlan_get(unit, hgtid, vid, enable); 
   4538         } else 
   4539 #endif /* BCM_TRIDENT_SUPPORT */
   4540         {
   4541             vlan_tab_entry_t ve;
   4542             uint32 val, hgo_bit;
   4543 
   4544             *enable = 0;
   4545 
   4546             rv = READ_VLAN_TABm(unit, MEM_BLOCK_ANY, vid, &ve);
   4547             if (rv >= 0) {
   4548                 val = soc_VLAN_TABm_field32_get(unit, &ve,
   4549                         HIGIG_TRUNK_OVERRIDEf);
   4550                 hgo_bit = 1 << (tid - TRUNK_CNTL(unit).ngroups_fp);
   4551                 *enable = (val & hgo_bit) ? 1 : 0;
   4552             }
   4553         }
   4554     }
   4555 #endif /* BCM_FIREBOLT_SUPPORT */
   4556 
   4557     return rv;
   4558 #else
   4559     return BCM_E_UNAVAIL;
   4560 #endif  /* BCM_HERCULES15_SUPPORT || BCM_FIREBOLT_SUPPORT */
   4561 }
   4562 
   4563 /*
   4564  * Function:
   4565  *      bcm_trunk_pool_set
   4566  * Description:
   4567  *      Set trunk pool table that contains the egress port number
   4568  *      indexed by the hash value.
   4569  * Parameters:
   4570  *      unit    - StrataSwitch PCI device unit number (driver internal).
   4571  *      port    - Port number, -1 to all ports.
   4572  *      tid     - Trunk id.
   4573  *      size    - Trunk pool size.
   4574  *      weights - Weights for each port, all 0 means weighted fair.
   4575  * Returns:
   4576  *      BCM_E_xxxx
   4577  */
   4578 
   4579 int
   4580 bcm_esw_trunk_pool_set(int unit, bcm_port_t port, bcm_trunk_t tid,
   4581                    int size, const int weights[BCM_TRUNK_MAX_PORTCNT])
   4582 {
   4583 #ifdef  BCM_HERCULES15_SUPPORT
   4584     uint32 val;
   4585     int idx_min, idx_max, weighted, p, idx;
   4586     mem_trunk_port_pool_entry_t trk_pool;
   4587     trunk_private_t *t_info;
   4588     bcm_trunk_member_t member_array[BCM_TRUNK_FABRIC_MAX_PORTCNT];
   4589     int member_count;
   4590     bcm_port_t tp[BCM_TRUNK_FABRIC_MAX_PORTCNT];
   4591     soc_field_t pf[] = {PORT_NO_0f, PORT_NO_1f, PORT_NO_2f, PORT_NO_3f};
   4592     int token[BCM_TRUNK_MAX_PORTCNT], index;
   4593     int i, reset=0, blk, rv=BCM_E_NONE, lp=0;
   4594 
   4595     if (!SOC_IS_HERCULES15(unit)) {
   4596         return BCM_E_UNAVAIL;
   4597     }
   4598 
   4599     if (port >= 0) {
   4600         if (BCM_GPORT_IS_SET(port)) {
   4601             bcm_trunk_t     tgid;
   4602             bcm_module_t    modid;
   4603             int             id;
   4604 
   4605             BCM_IF_ERROR_RETURN(
   4606                 _bcm_esw_gport_resolve(unit, port, &modid, &port, &tgid, &id));
   4607             if ((-1 != id) || (-1 != tgid)){
   4608                 return BCM_E_PARAM;
   4609             }
   4610         } else {
   4611             if (!SOC_PORT_VALID(unit, port) || !IS_HG_PORT(unit, port) ) {
   4612                 return BCM_E_PORT;
   4613             }
   4614         }
   4615     }
   4616 
   4617     TRUNK_INIT(unit);
   4618     TRUNK_CHECK(unit, tid);
   4619     t_info = &TRUNK_INFO(unit, tid);
   4620     if (t_info->tid == BCM_TRUNK_INVALID) {
   4621         return BCM_E_NOT_FOUND;
   4622     }
   4623 
   4624     idx_min = soc_mem_index_min(unit, MEM_TRUNK_PORT_POOLm);
   4625     idx_max = soc_mem_index_max(unit, MEM_TRUNK_PORT_POOLm);
   4626     if ((size < idx_min) || (size > idx_max)) {
   4627         return BCM_E_PARAM;
   4628     }
   4629     if (size == 0) {
   4630         index = size = idx_max;
   4631     } else {
   4632         index = size - 1;
   4633     }
   4634 
   4635     BCM_IF_ERROR_RETURN(bcm_esw_trunk_get(unit, tid, NULL,
   4636                 BCM_TRUNK_FABRIC_MAX_PORTCNT, member_array, &member_count));
   4637     if (member_count <= 0) {
   4638         return BCM_E_NOT_FOUND;
   4639     }
   4640 
   4641     for (i=0; i < member_count; i++) {
   4642         BCM_IF_ERROR_RETURN
   4643             (bcm_esw_port_local_get(unit, member_array[i].gport, &tp[i])); 
   4644          lp |= weights[tp[i]-1];
   4645          if ((lp & ~0x3f) != 0) {
   4646              return BCM_E_PARAM;
   4647          }
   4648     }
   4649     weighted = (lp) ? 1 : 0;
   4650 
   4651     soc_mem_lock(unit, MEM_TRUNK_PORT_POOLm);
   4652     PBMP_PORT_ITER(unit, p) {
   4653         if ((port >= 0) && (p != port)) {
   4654             continue;
   4655         }
   4656 
   4657         if ((rv = READ_ING_HGTRUNKr(unit, p, tid, &val)) >= 0) {
   4658             soc_reg_field_set(unit, ING_HGTRUNKr, &val,
   4659                               TRUNK_POOL_SIZEf, size);
   4660             rv = WRITE_ING_HGTRUNKr(unit, p, tid, val);
   4661         }
   4662         if (rv < 0) {
   4663             break;
   4664         }
   4665 
   4666         if (weighted) {
   4667             for (i = 0; i < member_count; i++) {
   4668                  token[tp[i]-1] = weights[tp[i]-1];
   4669             }
   4670         }
   4671 
   4672         idx = index;
   4673         blk = SOC_PORT_BLOCK(unit, p);
   4674 
   4675         while (idx >= 0) {
   4676             if (weighted) {
   4677                 for (i = 0; i < member_count; i++) {
   4678                     if (token[tp[i]-1]) {
   4679                         reset = 0;
   4680                         break;
   4681                     }
   4682                     reset = 1;
   4683                 }
   4684                 if (reset) {
   4685                     for (i = 0; i < member_count; i++) {
   4686                         token[tp[i]-1] = weights[tp[i]-1];
   4687                     }
   4688                 }
   4689             }
   4690             for (i = 0; i < member_count; i++) {
   4691                 if (idx < 0) break;
   4692                 sal_memset(&trk_pool, 0, sizeof(trk_pool));
   4693                 if (weighted) {
   4694                     if (token[tp[i]-1]) {
   4695                         if ((rv = READ_MEM_TRUNK_PORT_POOLm(unit, blk, index-idx, &trk_pool)) >= 0) {
   4696                             soc_MEM_TRUNK_PORT_POOLm_field32_set(unit, &trk_pool, pf[tid], tp[i]);
   4697                             rv = WRITE_MEM_TRUNK_PORT_POOLm(unit, blk, index-idx,  &trk_pool);
   4698                         }
   4699                         token[tp[i]-1]--;
   4700                         idx--;
   4701                     } else {
   4702                       continue;
   4703                     }
   4704                 } else {
   4705                     if ((rv = READ_MEM_TRUNK_PORT_POOLm(unit, blk, index-idx, &trk_pool)) >= 0) {
   4706                         soc_MEM_TRUNK_PORT_POOLm_field32_set(unit, &trk_pool, pf[tid], tp[i]);
   4707                         rv = WRITE_MEM_TRUNK_PORT_POOLm(unit, blk, index-idx,  &trk_pool);
   4708                     }
   4709                     idx--;
   4710                 }
   4711             }
   4712         }
   4713     }
   4714     soc_mem_unlock(unit, MEM_TRUNK_PORT_POOLm);
   4715 
   4716     return rv;
   4717 #else
   4718     return BCM_E_UNAVAIL;
   4719 #endif  /* BCM_HERCULES15_SUPPORT */
   4720 }
   4721 
   4722 /*
   4723  * Function:
   4724  *      bcm_trunk_pool_get
   4725  * Description:
   4726  *      Get trunk pool table that contains the egress port number
   4727  *      indexed by the hash value.
   4728  * Parameters:
   4729  *      unit    - StrataSwitch PCI device unit number (driver internal).
   4730  *      port    - Port number.
   4731  *      tid     - Trunk id.
   4732  *      size    - (OUT) Trunk pool size.
   4733  *      weights - (OUT) Weights (total count) for each port.
   4734  * Returns:
   4735  *      BCM_E_xxxx
   4736  */
   4737 
   4738 int
   4739 bcm_esw_trunk_pool_get(int unit, bcm_port_t port, bcm_trunk_t tid,
   4740                    int *size, int weights[BCM_TRUNK_MAX_PORTCNT])
   4741 {
   4742 #ifdef  BCM_HERCULES15_SUPPORT
   4743     uint32 val;
   4744     mem_trunk_port_pool_entry_t trk_pool;
   4745     trunk_private_t *t_info;
   4746     bcm_trunk_member_t member_array[BCM_TRUNK_FABRIC_MAX_PORTCNT];
   4747     int member_count;
   4748     bcm_port_t tp[BCM_TRUNK_FABRIC_MAX_PORTCNT];
   4749     soc_field_t pf[] = {PORT_NO_0f, PORT_NO_1f, PORT_NO_2f, PORT_NO_3f};
   4750     int i,pool, idx, blk, pool_port, rv=BCM_E_NONE;
   4751 
   4752     if (!SOC_IS_HERCULES15(unit)) {
   4753         return BCM_E_UNAVAIL;
   4754     }
   4755 
   4756     if (BCM_GPORT_IS_SET(port)) {
   4757         bcm_trunk_t     tgid;
   4758         bcm_module_t    modid;
   4759         int             id;
   4760 
   4761         BCM_IF_ERROR_RETURN(
   4762             _bcm_esw_gport_resolve(unit, port, &modid, &port, &tgid, &id));
   4763         if ((-1 != id) || (-1 != tgid)){
   4764             return BCM_E_PARAM;
   4765         }
   4766     } else {
   4767         if (!SOC_PORT_VALID(unit, port) || !IS_HG_PORT(unit, port) ) {
   4768             return BCM_E_PORT;
   4769         }
   4770     }
   4771 
   4772     TRUNK_INIT(unit);
   4773     TRUNK_CHECK(unit, tid);
   4774     t_info = &TRUNK_INFO(unit, tid);
   4775     if (t_info->tid == BCM_TRUNK_INVALID) {
   4776         return BCM_E_NOT_FOUND;
   4777     }
   4778 
   4779     *size = 0;
   4780     for (idx=0; idx < BCM_TRUNK_MAX_PORTCNT; idx++) {
   4781          weights[idx] = 0;
   4782     }
   4783 
   4784     SOC_IF_ERROR_RETURN(READ_ING_HGTRUNKr(unit, port, tid, &val));
   4785     *size = soc_reg_field_get(unit, ING_HGTRUNKr, val, TRUNK_POOL_SIZEf);
   4786     if (*size == 0) { /* HW meaning, we never program 0 above in _set */
   4787         *size = 1;
   4788     }
   4789 
   4790     BCM_IF_ERROR_RETURN(bcm_esw_trunk_get(unit, tid, NULL,
   4791                 BCM_TRUNK_FABRIC_MAX_PORTCNT, member_array, &member_count)); 
   4792     for (i=0; i < member_count; i++) {
   4793         BCM_IF_ERROR_RETURN(bcm_esw_port_local_get(unit,
   4794                     member_array[i].gport, &tp[i]));
   4795     }
   4796 
   4797     blk = SOC_PORT_BLOCK(unit, port);
   4798     pool = *size;
   4799     for (idx = 0; idx < pool; idx++) {
   4800          if ((rv = READ_MEM_TRUNK_PORT_POOLm(unit, blk, idx, &trk_pool)) >= 0) {
   4801               pool_port = soc_MEM_TRUNK_PORT_POOLm_field32_get(unit, &trk_pool, pf[tid]);
   4802               for (i=0; i < member_count; i++) {
   4803                    if (pool_port == tp[i]) {
   4804                        weights[tp[i]-1]++;
   4805                        break;
   4806                    }
   4807               }
   4808          }
   4809     }
   4810 
   4811     return rv;
   4812 #else
   4813     return BCM_E_UNAVAIL;
   4814 #endif  /* BCM_HERCULES15_SUPPORT */
   4815 }
   4816 
   4817 int _bcm_nuc_tpbm_get(int unit,
   4818                       int num_ports,
   4819                       bcm_module_t *tm,
   4820                       uint32 *nuc_tpbm)
   4821 {
   4822     int i, mod = -1;
   4823     uint32 mod_type;
   4824     int all_equal = 1;
   4825     uint32 xgs12_tpbm = 0;
   4826     uint32 xgs3_tpbm = 0;
   4827     uint32 unknown_tpbm = 0;
   4828 
   4829     *nuc_tpbm = 0x1;
   4830     for (i = 0; i < num_ports; i++) {
   4831         if (i == 0) {
   4832             mod = tm[i];
   4833         } else if (mod != tm[i]) {
   4834             all_equal = 0;
   4835         }
   4836         BCM_IF_ERROR_RETURN
   4837             (_bcm_switch_module_type_get(unit, tm[i], &mod_type));
   4838         switch(mod_type) {
   4839             case BCM_SWITCH_MODULE_XGS1   :
   4840             case BCM_SWITCH_MODULE_XGS2   : xgs12_tpbm |= (1 << i); break;
   4841             case BCM_SWITCH_MODULE_XGS3   : xgs3_tpbm |= (1 << i); break;
   4842             case BCM_SWITCH_MODULE_UNKNOWN:
   4843             default                       : unknown_tpbm |= (1 << i); break;
   4844         }
   4845     }
   4846     if (all_equal) {
   4847         *nuc_tpbm = ((0x1 << num_ports) - 1);
   4848     } else if (unknown_tpbm || xgs12_tpbm) {
   4849         *nuc_tpbm = 0x1;
   4850     } else if (xgs3_tpbm) {
   4851         *nuc_tpbm = xgs3_tpbm;
   4852     }
   4853 
   4854     return(BCM_E_NONE);
   4855 }
   4856 
   4857 /*
   4858  * Function:
   4859  *      bcm_trunk_find
   4860  * Description:
   4861  *      Get trunk id that contains the given system port
   4862  * Parameters:
   4863  *      unit    - StrataSwitch PCI device unit number (driver internal)
   4864  *      modid   - Module ID
   4865  *      port    - Port number
   4866  *      tid     - (OUT) Trunk id
   4867  * Returns:
   4868  *      BCM_E_xxxx
   4869  */
   4870 int
   4871 bcm_esw_trunk_find(int unit, bcm_module_t modid, bcm_port_t port,
   4872                    bcm_trunk_t *tid)
   4873 {
   4874     bcm_module_t hw_mod;
   4875     bcm_port_t   hw_port;
   4876     int          tgid, id;
   4877     int          isLocal;
   4878 
   4879     TRUNK_INIT(unit);
   4880 
   4881     if (tid == NULL) {
   4882         return BCM_E_PARAM;
   4883     }
   4884 
   4885     if (BCM_GPORT_IS_SET(port)) {
   4886         BCM_IF_ERROR_RETURN(
   4887             _bcm_esw_gport_resolve(unit, port, &hw_mod, &hw_port, &tgid, &id));
   4888 
   4889 #if defined(BCM_HGPROXY_COE_SUPPORT)
   4890         if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) &&
   4891             _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port)) {
   4892             id = -1;
   4893         } else
   4894 #endif
   4895 #if defined(BCM_KATANA2_SUPPORT)
   4896         if (_BCM_KT2_GPORT_IS_LINKPHY_OR_SUBTAG_SUBPORT_GPORT(unit, port)) {
   4897             id = -1;
   4898         }
   4899 #endif
   4900         if (-1 != tgid) {
   4901             return BCM_E_PORT;
   4902         } else if (-1 != id) {
   4903 #if defined(BCM_TRIDENT2_SUPPORT) && defined(INCLUDE_L3)
   4904             if (soc_feature(unit, soc_feature_vp_lag)) {
   4905                 return bcm_td2_vp_lag_find(unit, port, tid);
   4906             } else
   4907 #endif /* BCM_TRIDENT2_SUPPORT && INCLUDE_L3 */
   4908             {
   4909                 return BCM_E_PORT;
   4910             }
   4911         }
   4912     } else {
   4913         PORT_DUALMODID_VALID(unit, port);
   4914         BCM_IF_ERROR_RETURN
   4915             (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_SET,
   4916                                     modid, port,
   4917                                     &hw_mod, &hw_port));
   4918 
   4919         if (!SOC_MODID_ADDRESSABLE(unit, hw_mod)) {
   4920             return BCM_E_BADID;
   4921         }
   4922 
   4923         if (!SOC_PORT_ADDRESSABLE(unit, hw_port)) {
   4924             return BCM_E_PORT;
   4925         }
   4926     }
   4927 
   4928     BCM_IF_ERROR_RETURN(_bcm_esw_modid_is_local(unit, hw_mod, &isLocal));
   4929 
   4930 #ifdef BCM_XGS3_SWITCH_SUPPORT
   4931     if (SOC_IS_XGS3_SWITCH(unit)) {
   4932 #ifdef BCM_TOMAHAWK3_SUPPORT
   4933         if (SOC_IS_TOMAHAWK3(unit)) {
   4934             return(_bcm_th3_trunk_get_port_property(unit, hw_port, tid));
   4935         } else
   4936 #endif
   4937         {
   4938 #ifdef BCM_TRIDENT_SUPPORT
   4939         int rv = BCM_E_NONE;
   4940         if (soc_feature(unit, soc_feature_shared_trunk_member_table)) {
   4941             if (isLocal && (IS_ST_PORT(unit, hw_port)
   4942                 || (soc_feature(unit, soc_feature_subtag_coe) &&
   4943                     IS_SUBTAG_PORT (unit, hw_port))
   4944                 || (soc_feature(unit, soc_feature_linkphy_coe) &&
   4945                     IS_LP_PORT (unit, hw_port))
   4946                 || (soc_feature(unit, soc_feature_hgproxy_subtag_coe) &&
   4947                     IS_SUBTAG_PORT (unit, hw_port)))) {
   4948 
   4949                 int my_modid = 0;
   4950                 /* If the passed in mod-id matches the local mod-id, look for
   4951                    the trunk with only the port. Else, for CoE type of
   4952                    applications look for both the mod-id and port-id */
   4953                 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_modid));
   4954                 if (IS_ST_PORT(unit, hw_port) && (my_modid == hw_mod)) {
   4955                     rv = _bcm_trident_trunk_fabric_find(unit, hw_port, tid);
   4956                 } else {
   4957                     return (_bcm_trident_trunk_get_port_property(unit, hw_mod,
   4958                                                               hw_port, tid));
   4959                 }
   4960 
   4961                 if (BCM_SUCCESS(rv)) {
   4962                     return rv;
   4963                 }
   4964                 
   4965                 return(_bcm_trident_trunk_get_port_property(unit, hw_mod, 
   4966                                                                hw_port, tid));
   4967             } else {
   4968                 return(_bcm_trident_trunk_get_port_property(unit, hw_mod, hw_port, tid));
   4969             } 
   4970         } else 
   4971 #endif /* BCM_TRIDENT_SUPPORT */
   4972         {
   4973             if (isLocal && IS_ST_PORT(unit, hw_port)) {
   4974                 return(_bcm_xgs3_trunk_fabric_find(unit, hw_port, tid));
   4975             } else {
   4976                 return(_bcm_xgs3_trunk_get_port_property(unit, hw_mod, hw_port, tid)); 
   4977             }
   4978         }
   4979         }
   4980     } else
   4981 #endif /* BCM_XGS3_SWITCH_SUPPORT */
   4982     {
   4983         /* Hercules 1.5 */
   4984 
   4985         int idx = 0;
   4986         int i;
   4987         bcm_trunk_member_t member_array[BCM_TRUNK_FABRIC_MAX_PORTCNT];
   4988         int member_count;
   4989         bcm_port_t tp[BCM_TRUNK_FABRIC_MAX_PORTCNT];
   4990 
   4991         for (idx = 0; idx < TRUNK_NUM_GROUPS(unit); idx++) {
   4992              if (TRUNK_INFO(unit, idx).tid == BCM_TRUNK_INVALID) {
   4993                 continue;
   4994              }
   4995              
   4996              BCM_IF_ERROR_RETURN(bcm_esw_trunk_get(unit, idx, NULL,
   4997                 BCM_TRUNK_FABRIC_MAX_PORTCNT, member_array, &member_count));
   4998              if (member_count <= 0) {
   4999                  continue;
   5000              }
   5001 
   5002              for (i = 0; i < member_count; i++) {
   5003                  BCM_IF_ERROR_RETURN
   5004                      (bcm_esw_port_local_get(unit, member_array[i].gport, &tp[i])); 
   5005 
   5006                  if (isLocal && IS_ST_PORT(unit, hw_port)) {
   5007                      if (TRUNK_FABRIC_TID(unit, idx)) {
   5008                          if (tp[i] == hw_port) {
   5009                              *tid = idx;
   5010                              return BCM_E_NONE;
   5011                          }
   5012                      }
   5013                  }
   5014              }
   5015         }
   5016 
   5017         return BCM_E_NOT_FOUND;
   5018     }
   5019 }
   5020 
   5021 /*
   5022  * Function:
   5023  *      bcm_esw_trunk_failover_set
   5024  * Purpose:
   5025  *      Assign the failover port list for a specific trunk port.
   5026  * Parameters:
   5027  *      unit - (IN) Unit number.
   5028  *      tid - (IN) Trunk id.
   5029  *      failport - (IN) Port in trunk for which to specify failover port list.
   5030  *      psc - (IN) Port selection criteria for failover port list.
   5031  *      flags - (IN) BCM_TRUNK_FLAG_FAILOVER_xxx.
   5032  *      count - (IN) Number of ports in failover port list.
   5033  *      fail_to_array - (IN) Failover port list.
   5034  * Returns:
   5035  *      BCM_E_XXX
   5036  * Notes:
   5037  */
   5038 int 
   5039 bcm_esw_trunk_failover_set(int unit, bcm_trunk_t tid, bcm_gport_t failport, 
   5040                            int psc, uint32 flags, int count, 
   5041                            bcm_gport_t *fail_to_array)
   5042 {
   5043 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT)
   5044     trunk_private_t *t_info;
   5045     int rv, id, fabric_trunk;
   5046     bcm_port_t port, *ftp=NULL;
   5047     bcm_module_t modid, *ftm=NULL;
   5048     bcm_trunk_t tgid;
   5049 
   5050     TRUNK_INIT(unit);
   5051 
   5052     TRUNK_CHECK(unit, tid);
   5053 
   5054     t_info = &TRUNK_INFO(unit, tid);
   5055 
   5056     if (t_info->tid == BCM_TRUNK_INVALID) {
   5057         return (BCM_E_NOT_FOUND);
   5058     }
   5059 
   5060     fabric_trunk = TRUNK_FABRIC_TID(unit, tid);
   5061 
   5062     if (fabric_trunk) {
   5063         if (!soc_feature(unit, soc_feature_hg_trunk_failover)) {
   5064             return BCM_E_UNAVAIL;
   5065         }
   5066         if (BCM_GPORT_IS_SET(failport)) {
   5067             BCM_IF_ERROR_RETURN
   5068                 (bcm_esw_port_local_get(unit, failport, &port));
   5069         } else {
   5070             port = failport;
   5071         }
   5072         modid = -1;
   5073     } else {
   5074         if (!soc_feature(unit, soc_feature_port_lag_failover)) {
   5075             return BCM_E_UNAVAIL;
   5076         }
   5077 #if defined(BCM_TRIDENT_SUPPORT)
   5078         if (soc_feature(unit, soc_feature_shared_trunk_member_table)) {
   5079             if (BCM_GPORT_IS_SET(failport)) {
   5080                 BCM_IF_ERROR_RETURN
   5081                     (bcm_esw_port_local_get(unit, failport, &port));
   5082             } else {
   5083                 port = failport;
   5084             }
   5085 
   5086             if (IS_HG_PORT(unit, port)) {
   5087                 return BCM_E_UNAVAIL;
   5088             }
   5089             /* not supported for Cascaded Physical Ports*/
   5090             if ((soc_feature(unit, soc_feature_linkphy_coe) &&
   5091                 IS_LP_PORT(unit, port)) ||
   5092                 (soc_feature(unit, soc_feature_subtag_coe) &&
   5093                 IS_SUBTAG_PORT(unit, port)) || 
   5094                 (soc_feature(unit, soc_feature_hgproxy_subtag_coe) &&
   5095                 IS_SUBTAG_PORT (unit, port))) {
   5096                 return BCM_E_UNAVAIL;
   5097             }
   5098         }
   5099 #endif
   5100 
   5101         BCM_IF_ERROR_RETURN
   5102             (_bcm_esw_gport_resolve(unit, failport, &modid, &port, &tgid, &id));
   5103         if ((-1 != tgid) || (-1 != id)) {
   5104             return BCM_E_PARAM;
   5105         }
   5106     }
   5107 
   5108     if (psc <= 0) {
   5109 	psc = BCM_TRUNK_PSC_DEFAULT;
   5110     }
   5111 
   5112     /* Failover options:
   5113      * 1) Specify plan with a flag
   5114      * 2) Specify plan with count > 0 and fail_to_array listing ports
   5115      * 3) Disable failover with count == 0
   5116      */
   5117     if ((flags == 0) && ((count < 0) ||
   5118                          ((count > 0) && (fail_to_array == NULL)))) {
   5119         return BCM_E_PARAM;
   5120     }
   5121 
   5122     if (count > 0) {
   5123         if ((TRUNK_FP_TID(unit, tid) &&
   5124              (count > TRUNK_CNTL(unit).nports_fp)) ||
   5125             (TRUNK_FABRIC_TID(unit, tid) &&
   5126              (count > TRUNK_CNTL(unit).nports_hg)) ) {
   5127             return (BCM_E_PARAM);
   5128         } else {
   5129             ftp = sal_alloc(sizeof(bcm_port_t) * count, "failover ports");
   5130             if (NULL == ftp) {
   5131                 return BCM_E_MEMORY;
   5132             }
   5133             ftm = sal_alloc(sizeof(bcm_module_t) * count, "failover mods");
   5134             if (NULL == ftm) {
   5135                 sal_free(ftp);
   5136                 return BCM_E_MEMORY;
   5137             }
   5138             rv = _bcm_esw_trunk_gport_array_resolve(unit, fabric_trunk,
   5139                                                     count, fail_to_array,
   5140                                                     ftp, ftm);
   5141             if (BCM_FAILURE(rv)) {
   5142                 sal_free(ftp);
   5143                 sal_free(ftm);
   5144             }
   5145         }
   5146     }
   5147 
   5148     /* Offset of trunk type */
   5149     tgid = tid - (fabric_trunk ? TRUNK_CNTL(unit).ngroups_fp : 0);
   5150 
   5151     TRUNK_LOCK(unit);
   5152 #ifdef BCM_TOMAHAWK3_SUPPORT
   5153     if (SOC_IS_TOMAHAWK3(unit)) {
   5154         rv = _bcm_th3_trunk_hwfailover_set(unit, tid,
   5155                 port, psc, flags, count, fail_to_array);
   5156     } else 
   5157 #endif /* BCM_TRIDENT_SUPPORT */
   5158 #ifdef BCM_TRIDENT_SUPPORT
   5159     if (soc_feature(unit, soc_feature_shared_trunk_member_table)) {
   5160         rv = _bcm_trident_trunk_hwfailover_set(unit, tgid, fabric_trunk,
   5161                 port, modid, psc, flags, count, ftp, ftm);
   5162     } else 
   5163 #endif /* BCM_TRIDENT_SUPPORT */
   5164     {
   5165         rv = _bcm_xgs3_trunk_hwfailover_set(unit, tgid, fabric_trunk,
   5166                 port, modid, psc, flags, count, ftp, ftm);
   5167     }
   5168     if (NULL != ftp) {
   5169         sal_free(ftp);
   5170     }
   5171     if (NULL != ftm) {
   5172         sal_free(ftm);
   5173     }
   5174 
   5175 #ifdef BCM_WARM_BOOT_SUPPORT
   5176     SOC_CONTROL_LOCK(unit);
   5177     SOC_CONTROL(unit)->scache_dirty = 1;
   5178     SOC_CONTROL_UNLOCK(unit);
   5179 #endif
   5180 
   5181     TRUNK_UNLOCK(unit);
   5182 
   5183     return rv;
   5184 #else /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */
   5185     return BCM_E_UNAVAIL; 
   5186 #endif
   5187 }
   5188 
   5189 /*
   5190  * Function:
   5191  *      bcm_esw_trunk_failover_get
   5192  * Purpose:
   5193  *      Retrieve the failover port list for a specific trunk port.
   5194  * Parameters:
   5195  *      unit - (IN) Unit number.
   5196  *      tid - (IN) Trunk id.
   5197  *      failport - (IN) Port in trunk for which to retrieve failover port list.
   5198  *      psc - (OUT) Port selection criteria for failover port list.
   5199  *      flags - (OUT) BCM_TRUNK_FLAG_FAILOVER_xxx.
   5200  *      array_size - (IN) Maximum number of ports in provided failover port list.
   5201  *      fail_to_array - (OUT) Failover port list.
   5202  *      array_count - (OUT) Number of ports in returned failover port list.
   5203  * Returns:
   5204  *      BCM_E_XXX
   5205  * Notes:
   5206  */
   5207 int 
   5208 bcm_esw_trunk_failover_get(int unit, bcm_trunk_t tid, bcm_gport_t failport, 
   5209                            int *psc, uint32 *flags, int array_size, 
   5210                            bcm_gport_t *fail_to_array, int *array_count)
   5211 {
   5212 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT)
   5213     trunk_private_t *t_info;
   5214     int rv, id, fabric_trunk;
   5215     bcm_port_t port, *ftp=NULL;
   5216     bcm_module_t modid, *ftm=NULL;
   5217     bcm_trunk_t tgid;
   5218 
   5219     TRUNK_INIT(unit);
   5220 
   5221     /* Following check is for Non-Tomahawk3 */
   5222     if (!SOC_IS_TOMAHAWK3(unit)) {
   5223         if (!soc_feature(unit, soc_feature_hg_trunk_failover)) {
   5224             return BCM_E_UNAVAIL;
   5225         }
   5226     }
   5227 
   5228     TRUNK_CHECK(unit, tid);
   5229 
   5230     t_info = &TRUNK_INFO(unit, tid);
   5231 
   5232     if (t_info->tid == BCM_TRUNK_INVALID) {
   5233         return (BCM_E_NOT_FOUND);
   5234     }
   5235 
   5236     fabric_trunk = TRUNK_FABRIC_TID(unit, tid);
   5237 
   5238     if (fabric_trunk) {
   5239         if (!soc_feature(unit, soc_feature_hg_trunk_failover)) {
   5240             return BCM_E_UNAVAIL;
   5241         }
   5242         if (BCM_GPORT_IS_SET(failport)) {
   5243             BCM_IF_ERROR_RETURN
   5244                 (bcm_esw_port_local_get(unit, failport, &port));
   5245         } else {
   5246             port = failport;
   5247         }
   5248         modid = -1;
   5249     } else {
   5250         if (!soc_feature(unit, soc_feature_port_lag_failover)) {
   5251             return BCM_E_UNAVAIL;
   5252         }
   5253         
   5254 #if defined(BCM_TRIDENT_SUPPORT)
   5255         if (soc_feature(unit, soc_feature_shared_trunk_member_table)) {
   5256             if (BCM_GPORT_IS_SET(failport)) {
   5257                 BCM_IF_ERROR_RETURN
   5258                     (bcm_esw_port_local_get(unit, failport, &port));
   5259             } else {
   5260                 port = failport;
   5261             }
   5262 
   5263             if (IS_HG_PORT(unit, port)) {
   5264                 return BCM_E_UNAVAIL;
   5265             }
   5266             /* not supported for Cascaded Physical Ports*/
   5267             if ((soc_feature(unit, soc_feature_linkphy_coe) &&
   5268                 IS_LP_PORT(unit, port)) ||
   5269                 (soc_feature(unit, soc_feature_subtag_coe) &&
   5270                 IS_SUBTAG_PORT(unit, port)) ||
   5271                 (soc_feature(unit, soc_feature_hgproxy_subtag_coe) &&
   5272                 IS_SUBTAG_PORT (unit, port))) {
   5273                 return BCM_E_UNAVAIL;
   5274             }
   5275         }
   5276 #endif
   5277         BCM_IF_ERROR_RETURN
   5278             (_bcm_esw_gport_resolve(unit, failport, &modid, &port, &tgid, &id));
   5279         if ((-1 != tgid) || (-1 != id)) {
   5280             return BCM_E_PARAM;
   5281         }
   5282     }
   5283 
   5284     if ((psc == NULL) || (flags == NULL) || (array_size < 0) ||
   5285         (fail_to_array == NULL) || (array_count == NULL)) {
   5286         return BCM_E_PARAM;
   5287     }
   5288 
   5289     /* Offset of trunk type */
   5290     tgid = tid - (fabric_trunk ? TRUNK_CNTL(unit).ngroups_fp : 0);
   5291 
   5292     if (array_size > 0) {
   5293         ftp = sal_alloc(sizeof(bcm_port_t) * array_size, "failover ports");
   5294         if (NULL == ftp) {
   5295             return BCM_E_MEMORY;
   5296         }
   5297         ftm = sal_alloc(sizeof(bcm_module_t) * array_size, "failover mods");
   5298         if (NULL == ftm) {
   5299             sal_free(ftp);
   5300             return BCM_E_MEMORY;
   5301         }
   5302     }
   5303     sal_memset(ftm, 0, sizeof(bcm_module_t) * array_size);
   5304     sal_memset(ftp, 0, sizeof(bcm_port_t) * array_size);
   5305 
   5306     TRUNK_LOCK(unit);
   5307 #ifdef BCM_TOMAHAWK3_SUPPORT
   5308     if (SOC_IS_TOMAHAWK3(unit)) {
   5309         rv = _bcm_th3_trunk_hwfailover_get(unit, tid,
   5310                 port, psc, flags, array_size, ftp, array_count);
   5311     } else 
   5312 #endif
   5313 #ifdef BCM_TRIDENT_SUPPORT
   5314     if (soc_feature(unit, soc_feature_shared_trunk_member_table)) {
   5315         rv = _bcm_trident_trunk_hwfailover_get(unit, tgid, fabric_trunk,
   5316                 port, modid, psc, flags, array_size, ftp, ftm, array_count);
   5317     } else
   5318 #endif /* BCM_TRIDENT_SUPPORT */
   5319     {
   5320         rv = _bcm_xgs3_trunk_hwfailover_get(unit, tgid, fabric_trunk,
   5321                 port, modid, psc, flags, array_size, ftp, ftm, array_count);
   5322     }
   5323     TRUNK_UNLOCK(unit);
   5324 
   5325     if (BCM_SUCCESS(rv)) {
   5326         rv = _bcm_esw_trunk_gport_construct(unit, fabric_trunk, *array_count,
   5327                                           ftp, ftm, fail_to_array);
   5328     }
   5329 
   5330     if (NULL != ftp) {
   5331         sal_free(ftp);
   5332     }
   5333     if (NULL != ftm) {
   5334         sal_free(ftm);
   5335     }
   5336 
   5337     return rv;
   5338 
   5339 #else /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */
   5340     return BCM_E_UNAVAIL; 
   5341 #endif
   5342 }
   5343 
   5344 /*
   5345  * Function:
   5346  *      bcm_esw_trunk_member_add
   5347  * Purpose:
   5348  *      Add a member to a trunk group.
   5349  * Parameters:
   5350  *      unit   - (IN) Unit number.
   5351  *      tid    - (IN) Trunk id.
   5352  *      member - (IN) Pointer to a trunk member structure.
   5353  * Returns:
   5354  *      BCM_E_XXX
   5355  */
   5356 int 
   5357 bcm_esw_trunk_member_add(
   5358     int unit, 
   5359     bcm_trunk_t tid, 
   5360     bcm_trunk_member_t *member)
   5361 {
   5362     trunk_private_t    *t_info;
   5363     int                rv = BCM_E_NONE;
   5364     int                member_count;
   5365     bcm_trunk_member_t *member_array = NULL;
   5366     bcm_trunk_info_t   trunk_info;
   5367     int                tid_is_vp_lag;
   5368     bcm_module_t       modid, member_modid;
   5369     bcm_port_t         port, member_port;
   5370     bcm_trunk_t        tgid, member_tgid;
   5371     int                id, member_id;
   5372     int                i;
   5373 
   5374     TRUNK_INIT(unit);
   5375 
   5376     BCM_IF_ERROR_RETURN
   5377         (_bcm_esw_trunk_id_is_vp_lag(unit, tid, &tid_is_vp_lag));
   5378     if (!tid_is_vp_lag) {
   5379         TRUNK_CHECK(unit, tid);
   5380         t_info = &TRUNK_INFO(unit, tid);
   5381         if (t_info->tid == BCM_TRUNK_INVALID) {
   5382             return BCM_E_NOT_FOUND;
   5383         }
   5384     }
   5385 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_HELIX4_SUPPORT)
   5386     if (soc_feature(unit, soc_feature_epc_linkflap_recover)) {
   5387         int status = 1;
   5388         SOC_LINKSCAN_MODPORT_MAP_LOCK(unit);
   5389         rv =  _bcm_td_stk_modport_map_member_link_handler(unit,
   5390                                   member->gport, tid, 0, &status);
   5391         SOC_LINKSCAN_MODPORT_MAP_UNLOCK(unit);
   5392         if (BCM_FAILURE(rv)) {
   5393             return rv;
   5394         }
   5395         if (status == 0) {
   5396             return rv;
   5397         } else {
   5398             rv = BCM_E_NONE;
   5399         }
   5400     }
   5401 #endif /* #(BCM_TRIUMPH3_SUPPORT) || defined(BCM_HELIX4_SUPPORT) */
   5402     BCM_IF_ERROR_RETURN
   5403         (_bcm_esw_gport_resolve(unit, member->gport,
   5404                                 &modid, &port, &tgid, &id));
   5405     if (!tid_is_vp_lag && (-1 != tgid)) {
   5406         return BCM_E_PARAM;
   5407     }
   5408 
   5409     /* Get number of trunk group's existing member ports */
   5410     BCM_IF_ERROR_RETURN
   5411         (bcm_esw_trunk_get(unit, tid, &trunk_info, 0, NULL, &member_count));
   5412 
   5413     /* Allocate member array to accomodate existing members and
   5414      * the new member to be added.
   5415      */
   5416     member_array = sal_alloc(sizeof(bcm_trunk_member_t) *
   5417             (member_count + 1), "trunk_member_array");
   5418     if (member_array == NULL) {
   5419         return BCM_E_MEMORY;
   5420     }
   5421     sal_memset(member_array, 0,
   5422             sizeof(bcm_trunk_member_t) * (member_count + 1));
   5423 
   5424     /* Retrieve existing member ports */
   5425     rv = bcm_esw_trunk_get(unit, tid, &trunk_info, member_count + 1,
   5426             member_array, &member_count);
   5427     if (BCM_FAILURE(rv)) {
   5428         sal_free(member_array);
   5429         return rv;
   5430     }
   5431 
   5432     /* If resilient hashing is enabled, check that the given member is not
   5433      * already a member of the group.
   5434      */
   5435     if (trunk_info.psc == BCM_TRUNK_PSC_DYNAMIC_RESILIENT) {
   5436         for (i = 0; i < member_count; i++) {
   5437             rv = _bcm_esw_gport_resolve(unit, member_array[i].gport,
   5438                     &member_modid, &member_port, &member_tgid, &member_id);
   5439             if (BCM_FAILURE(rv)) { 
   5440                 sal_free(member_array);
   5441                 return rv;
   5442             }
   5443             if (-1 != member_id) {
   5444                 if (member_array[i].gport == member->gport) {
   5445                     sal_free(member_array);
   5446                     return BCM_E_EXISTS;
   5447                 }
   5448             } else if (-1 != member_tgid) {
   5449                 sal_free(member_array);
   5450                 return BCM_E_INTERNAL;
   5451             } else {
   5452                 if ((member_modid == modid) && (member_port == port)) {
   5453                     sal_free(member_array);
   5454                     return BCM_E_EXISTS;
   5455                 }
   5456             }
   5457         }
   5458     }
   5459 
   5460     /* Add given member to group */
   5461     member_array[member_count].flags = member->flags;
   5462     member_array[member_count].gport = member->gport;
   5463     member_array[member_count].dynamic_scaling_factor =
   5464         member->dynamic_scaling_factor;
   5465     member_array[member_count].dynamic_load_weight =
   5466         member->dynamic_load_weight;
   5467     member_array[member_count].dynamic_queue_size_weight =
   5468         member->dynamic_queue_size_weight;
   5469     rv = _bcm_esw_trunk_modify(unit, tid, &trunk_info, member_count + 1,
   5470             member_array, TRUNK_MEMBER_OP_ADD, member);
   5471     sal_free(member_array);
   5472     return rv;
   5473 }
   5474 
   5475 /*
   5476  * Function:
   5477  *      bcm_esw_trunk_member_delete
   5478  * Purpose:
   5479  *      Remove a member from a trunk group.
   5480  * Parameters:
   5481  *      unit   - (IN) Unit number.
   5482  *      tid    - (IN) Trunk id.
   5483  *      member - (IN) Pointer to a trunk member structure.
   5484  * Returns:
   5485  *      BCM_E_XXX
   5486  */
   5487 int 
   5488 bcm_esw_trunk_member_delete(
   5489     int unit, 
   5490     bcm_trunk_t tid, 
   5491     bcm_trunk_member_t *member)
   5492 {
   5493     trunk_private_t    *t_info;
   5494     bcm_module_t       modid;
   5495     bcm_port_t         port;
   5496     bcm_trunk_t        tgid;
   5497     int                id;
   5498     int                rv = BCM_E_NONE;
   5499     int                i, k;
   5500     int                member_count;
   5501     bcm_trunk_member_t *member_array;
   5502     bcm_module_t       member_modid;
   5503     bcm_port_t         member_port;
   5504     bcm_trunk_t        member_tgid;
   5505     int                member_id;
   5506     bcm_trunk_info_t   trunk_info;
   5507     int                tid_is_vp_lag;
   5508 
   5509     TRUNK_INIT(unit);
   5510 
   5511     BCM_IF_ERROR_RETURN
   5512         (_bcm_esw_trunk_id_is_vp_lag(unit, tid, &tid_is_vp_lag));
   5513     if (!tid_is_vp_lag) {
   5514         TRUNK_CHECK(unit, tid);
   5515         t_info = &TRUNK_INFO(unit, tid);
   5516         if (t_info->tid == BCM_TRUNK_INVALID) {
   5517             return BCM_E_NOT_FOUND;
   5518         }
   5519     }
   5520 
   5521     BCM_IF_ERROR_RETURN
   5522         (_bcm_esw_gport_resolve(unit, member->gport,
   5523                                 &modid, &port, &tgid, &id));
   5524     if (!tid_is_vp_lag && (-1 != tgid)) {
   5525         return BCM_E_PARAM;
   5526     }
   5527 
   5528     /* Get number of trunk group's existing member ports */
   5529     BCM_IF_ERROR_RETURN
   5530         (bcm_esw_trunk_get(unit, tid, &trunk_info, 0, NULL, &member_count));
   5531 
   5532     if (member_count == 0) {
   5533         return BCM_E_NOT_FOUND;
   5534     } 
   5535 
   5536     /* Allocate member array to get existing members */
   5537     member_array = sal_alloc(sizeof(bcm_trunk_member_t) * member_count,
   5538             "trunk_member_array");
   5539     if (member_array == NULL) {
   5540         return BCM_E_MEMORY;
   5541     }
   5542     sal_memset(member_array, 0,
   5543             sizeof(bcm_trunk_member_t) * member_count);
   5544 
   5545     /* Retrieve existing member ports */
   5546     rv = bcm_esw_trunk_get(unit, tid, &trunk_info, member_count,
   5547             member_array, &member_count);
   5548     if (BCM_FAILURE(rv)) {
   5549         sal_free(member_array);
   5550         return rv;
   5551     }
   5552 
   5553     /* Find the index of the given member in the array */
   5554     for (i = 0; i < member_count; i++) {
   5555         rv = _bcm_esw_gport_resolve(unit, member_array[i].gport,
   5556                 &member_modid, &member_port,
   5557                 &member_tgid, &member_id);
   5558         if (BCM_FAILURE(rv)) { 
   5559             sal_free(member_array);
   5560             return rv;
   5561         }
   5562         if (-1 != member_id) {
   5563             if (member_array[i].gport == member->gport) {
   5564                 break;
   5565             }
   5566         } else if (-1 != member_tgid) {
   5567             sal_free(member_array);
   5568             return BCM_E_INTERNAL;
   5569         } else {
   5570             if ((member_modid == modid) && (member_port == port)) {
   5571                 break;
   5572             }
   5573         }
   5574     }
   5575 
   5576     if (i == member_count) {
   5577         sal_free(member_array);
   5578         return BCM_E_NOT_FOUND;
   5579     }
   5580 
   5581     /* Delete given member from array, and shift the remaining
   5582      * elements of the array.
   5583  */
   5584     for (k = i; k < member_count - 1; k++) {
   5585         member_array[k].flags = member_array[k+1].flags;
   5586         member_array[k].gport = member_array[k+1].gport;
   5587     }
   5588 
   5589     member_count--;
   5590     if (0 == member_count) {
   5591         rv = _bcm_esw_trunk_modify(unit, tid, &trunk_info,
   5592                 0, NULL, TRUNK_MEMBER_OP_DELETE, member);
   5593     } else {
   5594         rv = _bcm_esw_trunk_modify(unit, tid, &trunk_info,
   5595                 member_count, member_array, TRUNK_MEMBER_OP_DELETE, member);
   5596     }
   5597 
   5598     sal_free(member_array);
   5599     return rv;
   5600 }
   5601 
   5602 /*
   5603  * Function:
   5604  *      bcm_esw_trunk_member_delete_all
   5605  * Purpose:
   5606  *      Remove all members of a trunk group.
   5607  * Parameters:
   5608  *      unit   - (IN) Unit number.
   5609  *      tid    - (IN) Trunk id.
   5610  * Returns:
   5611  *      BCM_E_XXX
   5612  */
   5613 int 
   5614 bcm_esw_trunk_member_delete_all(
   5615     int unit, 
   5616     bcm_trunk_t tid) 
   5617 {
   5618     bcm_trunk_info_t trunk_info;
   5619     int member_count;
   5620 
   5621     BCM_IF_ERROR_RETURN
   5622         (bcm_esw_trunk_get(unit, tid, &trunk_info, 0, NULL, &member_count));
   5623 
   5624     if (member_count > 0) {
   5625         BCM_IF_ERROR_RETURN
   5626             (bcm_esw_trunk_set(unit, tid, &trunk_info, 0, NULL));
   5627     }
   5628 
   5629     return BCM_E_NONE;
   5630 }
   5631 
   5632 /*
   5633  * Function:
   5634  *      bcm_esw_trunk_member_status_set
   5635  * Purpose:
   5636  *      Set trunk member status.
   5637  * Parameters:
   5638  *      unit - (IN) Unit number.
   5639  *      member - (IN) Trunk member GPORT ID.
   5640  *      status - (IN) Trunk member link status: 0 = down, 1 = up.
   5641  * Returns:
   5642  *      BCM_E_XXX
   5643  */
   5644 int 
   5645 bcm_esw_trunk_member_status_set(
   5646     int unit, 
   5647     bcm_gport_t member, 
   5648     int status)
   5649 {
   5650     int rv = BCM_E_UNAVAIL;
   5651     bcm_module_t mod;
   5652     bcm_port_t port;
   5653     bcm_trunk_t tid;
   5654     int hw_id;
   5655     int is_local;
   5656     int set_hg_dlb_member_status = FALSE;
   5657 
   5658     TRUNK_INIT(unit);
   5659 
   5660     BCM_IF_ERROR_RETURN
   5661         (_bcm_esw_gport_resolve(unit, member, &mod, &port, &tid, &hw_id));
   5662     if ((tid != -1) || (hw_id != -1)) {
   5663         return BCM_E_PORT;
   5664     }
   5665     BCM_IF_ERROR_RETURN(_bcm_esw_modid_is_local(unit, mod, &is_local));
   5666 
   5667 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT)
   5668     if (soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) {
   5669         if (!is_local) {
   5670             return BCM_E_PORT;
   5671         }
   5672         if (soc_feature(unit, soc_feature_hg_dlb)) {
   5673             if (!IS_HG_PORT(unit, port)) {
   5674                 return BCM_E_PORT;
   5675             }
   5676         }
   5677         TRUNK_LOCK(unit);
   5678         rv = bcm_th2_hgt_lag_dlb_member_status_set(unit, port, status);
   5679         TRUNK_UNLOCK(unit);
   5680         return rv;
   5681     }
   5682 #endif /* BCM_TOMAHAWK2_SUPPORT */
   5683 
   5684     if (is_local) {
   5685         if (IS_HG_PORT(unit, port)) {
   5686             set_hg_dlb_member_status = TRUE;
   5687         }
   5688     }
   5689 
   5690     TRUNK_LOCK(unit);
   5691 
   5692     if (set_hg_dlb_member_status) {
   5693         if (soc_feature(unit, soc_feature_hg_dlb)) {
   5694 #ifdef BCM_TRIDENT_SUPPORT
   5695             rv = bcm_trident_hg_dlb_member_status_set(unit, port, status);
   5696 #endif /* BCM_TRIDENT_SUPPORT */
   5697         } else {
   5698             rv = BCM_E_UNAVAIL;
   5699         }
   5700     } else {
   5701         if (soc_feature(unit, soc_feature_lag_dlb)) {
   5702 #ifdef BCM_TRIUMPH3_SUPPORT
   5703             rv = bcm_tr3_lag_dlb_member_status_set(unit, mod, port, status);
   5704 #endif /* BCM_TRIUMPH3_SUPPORT */
   5705         } else {
   5706             rv = BCM_E_UNAVAIL;
   5707         }
   5708     }
   5709 
   5710     TRUNK_UNLOCK(unit);
   5711     return rv;
   5712 }
   5713 
   5714 /*
   5715  * Function:
   5716  *      bcm_esw_trunk_member_status_get
   5717  * Purpose:
   5718  *      Get trunk member status.
   5719  * Parameters:
   5720  *      unit - (IN) Unit number.
   5721  *      member - (IN) Trunk member GPORT ID.
   5722  *      status - (OUT) Trunk member link status.
   5723  * Returns:
   5724  *      BCM_E_XXX
   5725  */
   5726 int 
   5727 bcm_esw_trunk_member_status_get(
   5728     int unit, 
   5729     bcm_gport_t member, 
   5730     int *status)
   5731 {
   5732     int rv = BCM_E_UNAVAIL;
   5733     bcm_module_t mod;
   5734     bcm_port_t port;
   5735     bcm_trunk_t tid;
   5736     int hw_id;
   5737     int is_local;
   5738     int get_hg_dlb_member_status = FALSE;
   5739 
   5740     if (NULL == status) {
   5741         return BCM_E_PARAM;
   5742     }
   5743 
   5744     TRUNK_INIT(unit);
   5745 
   5746     BCM_IF_ERROR_RETURN
   5747         (_bcm_esw_gport_resolve(unit, member, &mod, &port, &tid, &hw_id));
   5748     if ((tid != -1) || (hw_id != -1)) {
   5749         return BCM_E_PORT;
   5750     }
   5751     BCM_IF_ERROR_RETURN(_bcm_esw_modid_is_local(unit, mod, &is_local));
   5752 
   5753 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT)
   5754     if (soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) {
   5755         if (!is_local) {
   5756             return BCM_E_PORT;
   5757         }
   5758         if (soc_feature(unit, soc_feature_hg_dlb)) {
   5759             if (!IS_HG_PORT(unit, port)) {
   5760                 return BCM_E_PORT;
   5761             }
   5762         }
   5763         TRUNK_LOCK(unit);
   5764         rv = bcm_th2_hgt_lag_dlb_member_status_get(unit, port, status);
   5765         TRUNK_UNLOCK(unit);
   5766         return rv;
   5767     }
   5768 #endif /* BCM_TOMAHAWK2_SUPPORT */
   5769     if (is_local) {
   5770         if (IS_HG_PORT(unit, port)) {
   5771             get_hg_dlb_member_status = TRUE;
   5772         }
   5773     }
   5774 
   5775     TRUNK_LOCK(unit);
   5776 
   5777     if (get_hg_dlb_member_status) {
   5778         if (soc_feature(unit, soc_feature_hg_dlb)) {
   5779 #ifdef BCM_TRIDENT_SUPPORT
   5780             rv = bcm_trident_hg_dlb_member_status_get(unit, port, status);
   5781 #endif /* BCM_TRIDENT_SUPPORT */
   5782         } else {
   5783             rv = BCM_E_UNAVAIL;
   5784         }
   5785     } else {
   5786         if (soc_feature(unit, soc_feature_lag_dlb)) {
   5787 #ifdef BCM_TRIUMPH3_SUPPORT
   5788             rv = bcm_tr3_lag_dlb_member_status_get(unit, mod, port, status);
   5789 #endif /* BCM_TRIUMPH3_SUPPORT */
   5790         } else {
   5791             rv = BCM_E_UNAVAIL;
   5792         }
   5793     }
   5794 
   5795     TRUNK_UNLOCK(unit);
   5796     return rv;
   5797 }
   5798 
   5799 /*
   5800  * Function:
   5801  *      bcm_esw_trunk_ethertype_set
   5802  * Purpose:
   5803  *      Set the Ethertypes that are eligible or ineligible for
   5804  *      dynamic load balancing or resilient hashing.
   5805  * Parameters:
   5806  *      unit - (IN) Unit number.
   5807  *      flags - (IN) BCM_TRUNK_DYNAMIC_ETHERTYPE_xxx flags.
   5808  *      ethertype_count - (IN) Number of elements in ethertype_array.
   5809  *      ethertype_array - (IN) Array of Ethertypes.
   5810  * Returns:
   5811  *      BCM_E_XXX
   5812  */
   5813 int 
   5814 bcm_esw_trunk_ethertype_set(
   5815     int unit, 
   5816     uint32 flags, 
   5817     int ethertype_count, 
   5818     int *ethertype_array)
   5819 {
   5820     int rv;
   5821     int i;
   5822 
   5823     if ((ethertype_count > 0) && (NULL == ethertype_array)) {
   5824         return BCM_E_PARAM;
   5825     }
   5826     for (i = 0; i < ethertype_count; i++) {
   5827         if (ethertype_array[i] < 0 || ethertype_array[i] > 0xffff) {
   5828             return BCM_E_PARAM;
   5829         }
   5830     }
   5831 
   5832     TRUNK_INIT(unit);
   5833     TRUNK_LOCK(unit);
   5834 
   5835     rv = BCM_E_UNAVAIL;
   5836 
   5837     if (flags & BCM_TRUNK_DYNAMIC_ETHERTYPE_TRUNK) {
   5838         if (flags & BCM_TRUNK_DYNAMIC_ETHERTYPE_RESILIENT) {
   5839 #ifdef BCM_TRIDENT2_SUPPORT
   5840             if (soc_feature(unit, soc_feature_lag_resilient_hash)) {
   5841                 rv = bcm_td2_lag_rh_ethertype_set(unit, flags, ethertype_count,
   5842                         ethertype_array);
   5843                 if (BCM_FAILURE(rv)) {
   5844                     TRUNK_UNLOCK(unit);
   5845                     return rv;
   5846                 }
   5847             } else
   5848 #endif /* BCM_TRIDENT2_SUPPORT */
   5849             {
   5850                 /* Resilient hashing not supported for LAGs */
   5851                 return BCM_E_UNAVAIL;
   5852             }
   5853 
   5854         } else {
   5855 #ifdef BCM_TRIUMPH3_SUPPORT
   5856             if (soc_feature(unit, soc_feature_lag_dlb)) {
   5857 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT)
   5858                 if (soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) {
   5859                     rv = bcm_th2_hgt_lag_dlb_ethertype_set(unit, flags,
   5860                             ethertype_count, ethertype_array);
   5861                 } else
   5862 #endif /* BCM_TOMAHAWK2_SUPPORT */
   5863                 {
   5864                     rv = bcm_tr3_lag_dlb_ethertype_set(unit, flags, ethertype_count,
   5865                             ethertype_array);
   5866                 }
   5867                 if (BCM_FAILURE(rv)) {
   5868                     TRUNK_UNLOCK(unit);
   5869                     return rv;
   5870                 }
   5871             }
   5872 #endif /* BCM_TRIUMPH3_SUPPORT */
   5873         }
   5874     } else if (flags & BCM_TRUNK_DYNAMIC_ETHERTYPE_FABRIC_TRUNK) {
   5875         if (flags & BCM_TRUNK_DYNAMIC_ETHERTYPE_RESILIENT) {
   5876 #ifdef BCM_TRIDENT2_SUPPORT
   5877             if (soc_feature(unit, soc_feature_hg_resilient_hash)) {
   5878                 rv = bcm_td2_hg_rh_ethertype_set(unit, flags, ethertype_count,
   5879                         ethertype_array);
   5880                 if (BCM_FAILURE(rv)) {
   5881                     TRUNK_UNLOCK(unit);
   5882                     return rv;
   5883                 }
   5884             } else
   5885 #endif /* BCM_TRIDENT2_SUPPORT */
   5886             {
   5887                 /* Resilient hashing not supported for LAGs */
   5888                 return BCM_E_UNAVAIL;
   5889             }
   5890         } else {
   5891             if (soc_feature(unit, soc_feature_hg_dlb)) {
   5892 #ifdef BCM_TRIUMPH3_SUPPORT
   5893 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT)
   5894                 if (soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) {
   5895                     rv = bcm_th2_hgt_lag_dlb_ethertype_set(unit, flags, ethertype_count,
   5896                             ethertype_array);
   5897                     if (BCM_FAILURE(rv)) {
   5898                         TRUNK_UNLOCK(unit);
   5899                         return rv;
   5900                     }
   5901                 } else
   5902 #endif /* BCM_TOMAHAWK2_SUPPORT */
   5903                 {
   5904                     if (soc_mem_is_valid(unit, DLB_HGT_ETHERTYPE_ELIGIBILITY_MAPm)) {
   5905                         rv = bcm_tr3_hg_dlb_ethertype_set(unit, flags, ethertype_count,
   5906                                 ethertype_array);
   5907                         if (BCM_FAILURE(rv)) {
   5908                             TRUNK_UNLOCK(unit);
   5909                             return rv;
   5910                         }
   5911                     }
   5912                 }
   5913 #endif /* BCM_TRIUMPH3_SUPPORT */
   5914             }
   5915         }
   5916     } else {
   5917         TRUNK_UNLOCK(unit);
   5918         return BCM_E_PARAM;
   5919     }
   5920 
   5921     TRUNK_UNLOCK(unit);
   5922     return rv;
   5923 }
   5924 
   5925 /*
   5926  * Function:
   5927  *      bcm_esw_trunk_ethertype_get
   5928  * Purpose:
   5929  *      Get the Ethertypes that are eligible or ineligible for
   5930  *      dynamic load balancing or resilient hashing.
   5931  * Parameters:
   5932  *      unit - (IN) Unit number.
   5933  *      flags - (INOUT) BCM_TRUNK_DYNAMIC_ETHERTYPE_xxx flags.
   5934  *      ethertype_max - (IN) Number of elements in ethertype_array.
   5935  *      ethertype_array - (OUT) Array of Ethertypes.
   5936  *      ethertype_count - (OUT) Number of elements returned in ethertype_array.
   5937  * Returns:
   5938  *      BCM_E_XXX
   5939  */
   5940 int 
   5941 bcm_esw_trunk_ethertype_get(
   5942     int unit, 
   5943     uint32 *flags, 
   5944     int ethertype_max, 
   5945     int *ethertype_array, 
   5946     int *ethertype_count)
   5947 {
   5948     int rv;
   5949 
   5950     if (NULL == flags) {
   5951         return BCM_E_PARAM;
   5952     }
   5953     if ((ethertype_max > 0) && (NULL == ethertype_array)) {
   5954         return BCM_E_PARAM;
   5955     }
   5956     if (NULL == ethertype_count) {
   5957         return BCM_E_PARAM;
   5958     }
   5959 
   5960     TRUNK_INIT(unit);
   5961     TRUNK_LOCK(unit);
   5962 
   5963     rv = BCM_E_UNAVAIL;
   5964 
   5965     if (*flags & BCM_TRUNK_DYNAMIC_ETHERTYPE_TRUNK) {
   5966         if (*flags & BCM_TRUNK_DYNAMIC_ETHERTYPE_RESILIENT) {
   5967 #ifdef BCM_TRIDENT2_SUPPORT
   5968             if (soc_feature(unit, soc_feature_lag_resilient_hash)) {
   5969                 rv = bcm_td2_lag_rh_ethertype_get(unit, flags, ethertype_max,
   5970                         ethertype_array, ethertype_count);
   5971                 if (BCM_FAILURE(rv)) {
   5972                     TRUNK_UNLOCK(unit);
   5973                     return rv;
   5974                 }
   5975             } else
   5976 #endif /* BCM_TRIDENT2_SUPPORT */
   5977             {
   5978                 /* Resilient hashing not supported for LAGs */
   5979                 return BCM_E_UNAVAIL;
   5980             }
   5981         } else {
   5982 #ifdef BCM_TRIUMPH3_SUPPORT
   5983             if (soc_feature(unit, soc_feature_lag_dlb)) {
   5984 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT)
   5985                 if (soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) {
   5986                     rv = bcm_th2_hgt_lag_dlb_ethertype_get(unit, flags,
   5987                             ethertype_max, ethertype_array, ethertype_count);
   5988                 } else
   5989 #endif /* BCM_TOMAHAWK2_SUPPORT */
   5990                 {
   5991                     rv = bcm_tr3_lag_dlb_ethertype_get(unit, flags, ethertype_max,
   5992                             ethertype_array, ethertype_count);
   5993                 }
   5994                 if (BCM_FAILURE(rv)) {
   5995                     TRUNK_UNLOCK(unit);
   5996                     return rv;
   5997                 }
   5998             }
   5999 #endif /* BCM_TRIUMPH3_SUPPORT */
   6000         }
   6001     } else if (*flags & BCM_TRUNK_DYNAMIC_ETHERTYPE_FABRIC_TRUNK) {
   6002         if (*flags & BCM_TRUNK_DYNAMIC_ETHERTYPE_RESILIENT) {
   6003 #ifdef BCM_TRIDENT2_SUPPORT
   6004             if (soc_feature(unit, soc_feature_hg_resilient_hash)) {
   6005                 rv = bcm_td2_hg_rh_ethertype_get(unit, flags, ethertype_max,
   6006                         ethertype_array, ethertype_count);
   6007                 if (BCM_FAILURE(rv)) {
   6008                     TRUNK_UNLOCK(unit);
   6009                     return rv;
   6010                 }
   6011             } else
   6012 #endif /* BCM_TRIDENT2_SUPPORT */
   6013             {
   6014                 /* Resilient hashing not supported for Higig trunks */
   6015                 return BCM_E_UNAVAIL;
   6016             }
   6017         } else {
   6018             if (soc_feature(unit, soc_feature_hg_dlb)) {
   6019 #ifdef BCM_TRIUMPH3_SUPPORT
   6020 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT)
   6021                 if (soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) {
   6022                     rv = bcm_th2_hgt_lag_dlb_ethertype_get(unit, flags,
   6023                             ethertype_max, ethertype_array, ethertype_count);
   6024                     if (BCM_FAILURE(rv)) {
   6025                         TRUNK_UNLOCK(unit);
   6026                         return rv;
   6027                     }
   6028                 } else
   6029 #endif /* BCM_TOMAHAWK2_SUPPORT */
   6030                 {
   6031                     if (soc_mem_is_valid(unit, DLB_HGT_ETHERTYPE_ELIGIBILITY_MAPm)) {
   6032                         rv = bcm_tr3_hg_dlb_ethertype_get(unit, flags, ethertype_max,
   6033                                 ethertype_array, ethertype_count);
   6034                         if (BCM_FAILURE(rv)) {
   6035                             TRUNK_UNLOCK(unit);
   6036                             return rv;
   6037                         }
   6038                     }
   6039                 }
   6040 #endif /* BCM_TRIUMPH3_SUPPORT */
   6041             }
   6042         }
   6043     } else {
   6044         TRUNK_UNLOCK(unit);
   6045         return BCM_E_PARAM;
   6046     }
   6047 
   6048     TRUNK_UNLOCK(unit);
   6049     return rv;
   6050 }
   6051 
   6052 #ifdef BCM_TOMAHAWK_SUPPORT
   6053 
   6054 STATIC int
   6055 _bcm_th_trunk_agm_update(int unit, bcm_trunk_t tid,
   6056                          bcm_switch_agm_type_t agm_type,
   6057                          int agm_pool_id,
   6058                          int agm_index)
   6059 {
   6060     int rv = BCM_E_NONE, hgtid;
   6061     uint32 tg_entry[SOC_MAX_MEM_WORDS];
   6062     hg_trunk_group_entry_t hg_trunk_group_entry;
   6063     bcm_trunk_chip_info_t chip_info;
   6064     int tid_is_vp_lag;
   6065     trunk_private_t *t_info;
   6066 
   6067     TRUNK_INIT(unit);
   6068 
   6069     BCM_IF_ERROR_RETURN
   6070         (_bcm_esw_trunk_id_is_vp_lag(unit, tid, &tid_is_vp_lag));
   6071     if (!tid_is_vp_lag) {
   6072         TRUNK_CHECK(unit, tid);
   6073         t_info = &TRUNK_INFO(unit, tid);
   6074         if (t_info->tid == BCM_TRUNK_INVALID) {
   6075             return BCM_E_NOT_FOUND;
   6076         }
   6077     } else {
   6078         /* XXX vp_lag ? */
   6079         return BCM_E_UNAVAIL;
   6080     }
   6081 
   6082     BCM_IF_ERROR_RETURN(bcm_esw_trunk_chip_info_get(unit, &chip_info));
   6083     LOG_INFO(BSL_LS_BCM_TRUNK, (BSL_META_U(unit, "tid %d min %d tid max %d fabId min %d fabId max %d \n"),
   6084                 tid, chip_info.trunk_id_min, chip_info.trunk_id_max,
   6085                 chip_info.trunk_fabric_id_min, chip_info.trunk_fabric_id_max));
   6086 
   6087     if ((tid >= chip_info.trunk_id_min) && (tid <= chip_info.trunk_id_max)) {
   6088         if (agm_type != bcmSwitchAgmTypeTrunk) {
   6089             return BCM_E_PARAM;
   6090         }
   6091         /* trunk group entry */
   6092         if (soc_feature(unit, soc_feature_fastlag)) {
   6093 #ifdef BCM_TOMAHAWK3_SUPPORT
   6094             if (SOC_IS_TOMAHAWK3(unit)) {
   6095                  fast_trunk_ports_1_entry_t  fast_1;
   6096                  SOC_IF_ERROR_RETURN
   6097                      (READ_FAST_TRUNK_PORTS_1m(unit, MEM_BLOCK_ALL, tid, &fast_1));
   6098                  soc_FAST_TRUNK_PORTS_1m_field32_set(unit, &fast_1, AGM_MONITOR_POOL_IDf, agm_pool_id);
   6099                  soc_FAST_TRUNK_PORTS_1m_field32_set(unit, &fast_1, AGM_MONITOR_IDf, agm_index);
   6100                  SOC_IF_ERROR_RETURN
   6101                      (WRITE_FAST_TRUNK_PORTS_1m(unit, MEM_BLOCK_ALL, tid, &fast_1));
   6102             } else
   6103 #endif
   6104             {
   6105                 SOC_IF_ERROR_RETURN
   6106                     (READ_FAST_TRUNK_GROUPm(unit, MEM_BLOCK_ANY, tid, &tg_entry));
   6107                 soc_FAST_TRUNK_GROUPm_field32_set(unit, &tg_entry, AGM_MONITOR_POOL_IDf,
   6108                                              agm_pool_id);
   6109                 soc_FAST_TRUNK_GROUPm_field32_set(unit, &tg_entry, AGM_MONITOR_IDf,
   6110                                              agm_index);
   6111                 SOC_IF_ERROR_RETURN
   6112                     (WRITE_FAST_TRUNK_GROUPm(unit, MEM_BLOCK_ANY, tid, &tg_entry));
   6113             }
   6114         } else { /* Not a Fast lag */
   6115             SOC_IF_ERROR_RETURN
   6116                 (READ_TRUNK_GROUPm(unit, MEM_BLOCK_ANY, tid, &tg_entry));
   6117             soc_TRUNK_GROUPm_field32_set(unit, &tg_entry, AGM_MONITOR_POOL_IDf,
   6118                                          agm_pool_id);
   6119             soc_TRUNK_GROUPm_field32_set(unit, &tg_entry, AGM_MONITOR_IDf,
   6120                                          agm_index);
   6121             SOC_IF_ERROR_RETURN
   6122                 (WRITE_TRUNK_GROUPm(unit, MEM_BLOCK_ANY, tid, &tg_entry));
   6123         }
   6124     } else if ((tid >= chip_info.trunk_fabric_id_min) &&
   6125                (tid <= (chip_info.trunk_fabric_id_max + 1))) {
   6126         if (agm_type != bcmSwitchAgmTypeFabricTrunk) {
   6127             return BCM_E_PARAM;
   6128         }
   6129         /* Higig trunk group entry */
   6130         hgtid = tid - chip_info.trunk_fabric_id_min;
   6131         SOC_IF_ERROR_RETURN
   6132             (READ_HG_TRUNK_GROUPm(unit, MEM_BLOCK_ANY, hgtid,
   6133                                   &hg_trunk_group_entry));
   6134         soc_HG_TRUNK_GROUPm_field32_set(unit, &hg_trunk_group_entry,
   6135                                         AGM_MONITOR_POOL_IDf, agm_pool_id);
   6136         soc_HG_TRUNK_GROUPm_field32_set(unit, &hg_trunk_group_entry,
   6137                                         AGM_MONITOR_IDf, agm_index);
   6138         SOC_IF_ERROR_RETURN
   6139             (WRITE_HG_TRUNK_GROUPm(unit, MEM_BLOCK_ALL, hgtid,
   6140                 &hg_trunk_group_entry));
   6141     } else {
   6142         rv = BCM_E_PARAM;
   6143     }
   6144 
   6145     return rv;
   6146 }
   6147 
   6148 /*
   6149  * Function:
   6150  *      bcm_th_trunk_agm_attach
   6151  * Purpose:
   6152  *      Attach already created monitor entry to a trunk or a fabric trunk
   6153  *      Internally, Map the monitor_entry_id to an aggregation group.
   6154  */
   6155 int
   6156 bcm_th_trunk_agm_attach(int unit, bcm_trunk_t tid,
   6157                         bcm_switch_agm_id_t agm_id)
   6158 {
   6159     int rv = BCM_E_NONE;
   6160 
   6161     agm_monitor_t agm_mnt;
   6162     bcm_switch_agm_id_t agm_id_old;
   6163     int agm_pool_id;
   6164     uint32 agm_index;
   6165 
   6166     bcm_trunk_info_t tinfo;
   6167     int mbm_cnt, mbm_max;
   6168     bcm_trunk_member_t *mbm_arr;
   6169 
   6170     /* Validate parameters */
   6171     if (!SOC_UNIT_VALID(unit)) {
   6172         return BCM_E_UNIT;
   6173     }
   6174     TRUNK_CHECK(unit, tid);
   6175 
   6176     BCM_IF_ERROR_RETURN(bcm_th_switch_agm_info(unit, agm_id, &agm_mnt));
   6177     if (agm_mnt.group_id == (int)tid) {
   6178         return BCM_E_EXISTS;
   6179     }
   6180 
   6181     mbm_max = agm_mnt.attr.num_members;
   6182     mbm_arr = sal_alloc(mbm_max * sizeof(*mbm_arr), "mbm_arr");
   6183     if (mbm_arr == NULL) {
   6184         return BCM_E_MEMORY;
   6185     }
   6186 
   6187     rv = bcm_esw_trunk_get(unit, tid, &tinfo, mbm_max, mbm_arr, &mbm_cnt);
   6188     sal_free(mbm_arr);    
   6189     if (BCM_FAILURE(rv)) {
   6190         return rv;
   6191     }
   6192 
   6193     if (mbm_cnt != agm_mnt.attr.num_members) {
   6194         LOG_VERBOSE(BSL_LS_BCM_TRUNK, (BSL_META_U(unit,
   6195                     "AGM %d member cnt %d doesn't match trunk %d member cnt %d\n"), 
   6196                     agm_id, agm_mnt.attr.num_members, tid, mbm_cnt));
   6197         return BCM_E_PARAM;
   6198     }
   6199 
   6200     agm_pool_id = agm_mnt.agm_pool_id;
   6201     agm_index   = agm_mnt.attr.agm_id;
   6202 
   6203     BCM_IF_ERROR_RETURN(_bcm_th_trunk_agm_update(unit, tid, agm_mnt.attr.agm_type,
   6204                                                  agm_pool_id, agm_index));
   6205 
   6206     /* in case of changing AGM, detach the old AGM first */
   6207     if (BCM_SUCCESS(bcm_th_switch_agm_id_get_by_group(unit, tid, &agm_id_old))) {
   6208         BCM_IF_ERROR_RETURN(bcm_th_switch_agm_fwd_grp_update(unit, agm_id_old, 
   6209                             _AGM_GROUP_ID_INVALID));
   6210     }
   6211 
   6212     BCM_IF_ERROR_RETURN(bcm_th_switch_agm_fwd_grp_update(unit, agm_id, tid));
   6213 
   6214     return rv;
   6215 }
   6216 
   6217 /*
   6218  * Function:
   6219  *      bcm_th_trunk_agm_detach
   6220  * Purpose:
   6221  *      Detach a monitor entry from a trunk or a fabric trunk
   6222  *      Internally, un-map the monitor_entry_id from an aggregation
   6223  *      group (fp_lag/fabric_channel_lag).
   6224  */
   6225 int
   6226 bcm_th_trunk_agm_detach(int unit, bcm_trunk_t tid,
   6227                         bcm_switch_agm_id_t agm_id)
   6228 {
   6229     int rv = BCM_E_NONE;
   6230     agm_monitor_t agm_mnt;
   6231 
   6232     /* Validate parameters */
   6233     if (!SOC_UNIT_VALID(unit)) {
   6234         return BCM_E_UNIT;
   6235     }
   6236     TRUNK_CHECK(unit, tid);
   6237 
   6238     BCM_IF_ERROR_RETURN(bcm_th_switch_agm_info(unit, agm_id, &agm_mnt));
   6239     if (agm_mnt.group_id != (int)tid) {
   6240         return BCM_E_NOT_FOUND;
   6241     }
   6242 
   6243     BCM_IF_ERROR_RETURN(_bcm_th_trunk_agm_update(unit, tid, 
   6244                         agm_mnt.attr.agm_type, 0, _AGM_ID_INVALID));
   6245     BCM_IF_ERROR_RETURN(bcm_th_switch_agm_fwd_grp_update(unit, agm_id, 
   6246                         _AGM_GROUP_ID_INVALID));
   6247 
   6248     return rv;
   6249 }
   6250 
   6251 /*
   6252  * Function:
   6253  *      bcm_th_trunk_agm_attach_get
   6254  * Purpose:
   6255  *      Retrieve a monitor id attached to a (fabric)trunk
   6256  */
   6257 int
   6258 bcm_th_trunk_agm_attach_get(int unit, bcm_trunk_t trunk_id,
   6259                             bcm_switch_agm_id_t *agm_id)
   6260 {
   6261     /* Validate parameters */
   6262     if (!SOC_UNIT_VALID(unit)) {
   6263         return BCM_E_UNIT;
   6264     }
   6265     TRUNK_CHECK(unit, trunk_id);
   6266 
   6267     return bcm_th_switch_agm_id_get_by_group(unit, trunk_id, agm_id);
   6268 }
   6269 
   6270 #endif /* BCM_TOMAHAWK_SUPPORT */
   6271 
   6272 /*
   6273  * Function:
   6274  *      bcm_esw_trunk_agm_attach
   6275  * Purpose:
   6276  *      Attach already created monitor entry to a trunk or a fabric trunk
   6277  *      Internally, Map the monitor_entry_id to an aggregation group.
   6278  * Parameters:
   6279  *      unit       - (IN) bcm device.
   6280  *      trunk_id - (IN) id of a (fabric) trunk.
   6281  *      agm_id - (IN) id of aggregation group monitoring entry created
   6282  *                        via the bcm_switch_agm_create api.
   6283  * Returns:
   6284  *      BCM_E_NONE: if the attachment is succeed
   6285  *      BCM_E_PARAM: if the monitor_id is not valid or the monitor
   6286  *                   entry is not created. If the trunk id is not valid
   6287  *      BCM_E_FULL: if a monitor entry is already attached to
   6288  *      BCM_E_PARAM: if number of trunk member is different from the
   6289  *                   number on the monitor entry
   6290  */
   6291 int
   6292 bcm_esw_trunk_agm_attach(int unit, bcm_trunk_t trunk_id,
   6293                          bcm_switch_agm_id_t agm_id)
   6294 {
   6295     int rv = BCM_E_UNAVAIL;
   6296 
   6297 #if defined(BCM_TOMAHAWK_SUPPORT)
   6298     if (soc_feature(unit, soc_feature_agm)) {
   6299         TRUNK_LOCK(unit);
   6300         rv = bcm_th_trunk_agm_attach(unit, trunk_id, agm_id);
   6301         TRUNK_UNLOCK(unit);
   6302     }
   6303 #endif /* BCM_TOMAHAWK_SUPPORT */
   6304     return rv;
   6305 }
   6306 
   6307 /*
   6308  * Function:
   6309  *      bcm_esw_trunk_agm_detach
   6310  * Purpose:
   6311  *      Detach a monitor entry from a trunk or a fabric trunk
   6312  *      Internally, un-map the monitor_entry_id from an aggregation
   6313  *      group (fp_lag/fabric_channel_lag).
   6314  * Parameters:
   6315  *      unit       - (IN) bcm device.
   6316  *      trunk_id   - (IN) id of a (fabric) trunk.
   6317  *      agm_id - (IN) id of aggregation group monitoring entry created
   6318  *                        via the bcm_switch_agm_create api.
   6319  * Returns:
   6320  *      BCM_E_NONE: if the enable or disable is succeed
   6321  *      BCM_E_PARAM: If the ecmp id is not valid
   6322  *      BCM_E_NOT_FOUND: if there is no monitor entry attached to the
   6323  *                       aggregation group.
   6324  */
   6325 int
   6326 bcm_esw_trunk_agm_detach(int unit, bcm_trunk_t trunk_id,
   6327                          bcm_switch_agm_id_t agm_id)
   6328 {
   6329     int rv = BCM_E_UNAVAIL;
   6330 
   6331 #if defined(BCM_TOMAHAWK_SUPPORT)
   6332     if (soc_feature(unit, soc_feature_agm)) {
   6333         TRUNK_LOCK(unit);
   6334         rv = bcm_th_trunk_agm_detach(unit, trunk_id, agm_id);
   6335         TRUNK_UNLOCK(unit);
   6336     }
   6337 #endif /* BCM_TOMAHAWK_SUPPORT */
   6338     return rv;
   6339 }
   6340 
   6341 /*
   6342  * Function:
   6343  *      bcm_esw_trunk_agm_attach_get
   6344  * Purpose:
   6345  *      Retrieve a monitor id attached to a (fabric)trunk
   6346  * Parameters:
   6347  *      unit       - (IN) bcm device.
   6348  *      trunk_id   - (IN) (fabric) trunk id.
   6349  *      agm_id - (IN/OUT) aggregation group monitoring entry.
   6350  * Returns:
   6351  *      BCM_E_NONE: if monitor entry id found
   6352  *      BCM_E_NOT_FOUND: if no monitor entry is attached to the
   6353  *                       aggregation group.
   6354  */
   6355 int
   6356 bcm_esw_trunk_agm_attach_get(int unit, bcm_trunk_t trunk_id,
   6357                              bcm_switch_agm_id_t *agm_id)
   6358 {
   6359     int rv = BCM_E_UNAVAIL;
   6360 
   6361 #if defined(BCM_TOMAHAWK_SUPPORT)
   6362     if (soc_feature(unit, soc_feature_agm)) {
   6363         TRUNK_LOCK(unit);
   6364         rv = bcm_th_trunk_agm_attach_get(unit, trunk_id, agm_id);
   6365         TRUNK_UNLOCK(unit);
   6366     }
   6367 #endif /* BCM_TOMAHAWK_SUPPORT */
   6368     return rv;
   6369 }
   6370 
   6371 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   6372 /*
   6373  * Function    : _bcm_esw_trunk_gport_add
   6374  * Description : Add the GPORT ID for the specified trunk.
   6375  *
   6376  * Parameters  : (IN)  unit          - BCM device number
   6377  *                     (IN)  tid     - Trunk Group
   6378  *                     (IN)  gport   - GPORT ID
   6379  * Returns     : BCM_E_XXX
   6380  */
   6381 int
   6382 _bcm_esw_trunk_gport_add(int unit, bcm_trunk_t tid, bcm_gport_t gport)
   6383 {
   6384     int id_out = 0;
   6385     int result = FALSE;
   6386     int is_trunk = 0;
   6387     int base_index = 0;
   6388     int subport_index = 0;
   6389     bcm_port_t port_out = 0;
   6390     bcm_module_t mod_out = 0;
   6391     bcm_trunk_t tgid_out = 0;
   6392     bcm_trunk_t old_tid = 0;
   6393     modid_base_ptr_entry_t modid_base_entry;
   6394     modport_map_subport_entry_t modport_map_subport_entry;
   6395     trunk_private_t *t_info;
   6396 
   6397     /* Make sure trunk module is initialized. */
   6398     TRUNK_INIT(unit);
   6399 
   6400     /* Parameter check */
   6401     if (!TRUNK_FABRIC_TID(unit, tid)) {
   6402         return BCM_E_PARAM;
   6403     }
   6404 
   6405     t_info = &TRUNK_INFO(unit, tid);
   6406     if (t_info->tid == BCM_TRUNK_INVALID) {
   6407         return BCM_E_NOT_FOUND;
   6408     }
   6409 
   6410     tid -= TRUNK_CNTL(unit).ngroups_fp;
   6411 
   6412     if (!BCM_GPORT_IS_MODPORT(gport)) {
   6413         return BCM_E_PARAM;
   6414     }
   6415 
   6416     BCM_IF_ERROR_RETURN(_bcm_esw_gport_resolve(unit, gport,
   6417                             &mod_out, &port_out, &tgid_out, &id_out));
   6418     if ((-1 != tgid_out) || (-1 != id_out)) {
   6419         return BCM_E_PARAM;
   6420     }
   6421 
   6422     /* Check modport in one of additional module */
   6423     BCM_IF_ERROR_RETURN (
   6424         _bcm_esw_my_modid_additional_check(unit, mod_out, &result));
   6425     if (result == FALSE) {
   6426         return BCM_E_PARAM;
   6427     }
   6428 
   6429     mod_out %= 64;  /* lower 6 bit */
   6430     SOC_IF_ERROR_RETURN
   6431         (READ_MODID_BASE_PTRm(unit, MEM_BLOCK_ANY, mod_out,
   6432                                   &modid_base_entry));
   6433     base_index = soc_MODID_BASE_PTRm_field32_get(unit,
   6434                                        &modid_base_entry, MODID_BASEf);
   6435     subport_index = base_index; /* the index is indicated by module base ptr */
   6436     SOC_IF_ERROR_RETURN
   6437         (READ_MODPORT_MAP_SUBPORTm(unit, MEM_BLOCK_ANY, subport_index,
   6438                                        &modport_map_subport_entry));
   6439     is_trunk = soc_MODPORT_MAP_SUBPORTm_field32_get(unit,
   6440                                        &modport_map_subport_entry, ISTRUNKf);
   6441     old_tid = soc_MODPORT_MAP_SUBPORTm_field32_get(unit,
   6442                                        &modport_map_subport_entry, DESTf);
   6443     if (is_trunk && (old_tid == tid)) {
   6444         return BCM_E_NONE;
   6445     }
   6446     if (is_trunk && old_tid >= 0) {
   6447         return BCM_E_RESOURCE;
   6448     }
   6449 
   6450     soc_MODPORT_MAP_SUBPORTm_field32_set (unit,
   6451                          &modport_map_subport_entry, DESTf, tid);
   6452     soc_MODPORT_MAP_SUBPORTm_field32_set (unit,
   6453                          &modport_map_subport_entry, ISTRUNKf, 1);
   6454     soc_MODPORT_MAP_SUBPORTm_field32_set (unit,
   6455                          &modport_map_subport_entry, ENABLEf, 1);
   6456     SOC_IF_ERROR_RETURN
   6457         (WRITE_MODPORT_MAP_SUBPORTm(unit, MEM_BLOCK_ANY, subport_index,
   6458                                         &modport_map_subport_entry));
   6459 
   6460     return BCM_E_NONE;
   6461 }
   6462 
   6463 /*
   6464  * Function    : _bcm_esw_trunk_gport_get_all
   6465  * Description : Add the GPORT ID for the specified trunk.
   6466  *
   6467  * Parameters  : (IN)  unit               - BCM device number
   6468  *                     (IN)  tid          - Trunk Group
   6469  *                     (IN)  gport_size   - GPORT ID
   6470                        (OUT) gport_array  - GPORT Array
   6471                        (OUT) count        - GPORT Count
   6472  * Returns     : BCM_E_XXX
   6473  */
   6474 int
   6475 _bcm_esw_trunk_gport_get_all(int unit, bcm_trunk_t tid, int gport_size,
   6476                             bcm_gport_t *gport_array, int *count)
   6477 {
   6478     int rv = BCM_E_NONE;
   6479     int mod_idx = 0;
   6480     int port_idx = 0;
   6481     int is_trunk = 0;
   6482     int base_index = 0;
   6483     bcm_gport_t modport = 0;
   6484     _bcm_gport_dest_t dest;
   6485     bcm_trunk_t egress_tid = 0;
   6486     bcm_stk_modid_config_t mod_cfg;
   6487     modid_base_ptr_entry_t modid_base_entry;
   6488     modport_map_subport_entry_t modport_map_subport_entry;
   6489     trunk_private_t *t_info;
   6490 
   6491     /* Make sure trunk module is initialized. */
   6492     TRUNK_INIT(unit);
   6493 
   6494     /* Parameter check */
   6495     if (!TRUNK_FABRIC_TID(unit, tid)) {
   6496         return BCM_E_PARAM;
   6497     }
   6498 
   6499     t_info = &TRUNK_INFO(unit, tid);
   6500     if (t_info->tid == BCM_TRUNK_INVALID) {
   6501         return BCM_E_NOT_FOUND;
   6502     }
   6503 
   6504     tid -= TRUNK_CNTL(unit).ngroups_fp;
   6505 
   6506     if (gport_size < 0 || count == NULL) {
   6507         return BCM_E_PARAM;
   6508     }
   6509 
   6510     if ((gport_size > 0) && gport_array == NULL) {
   6511         return BCM_E_PARAM;
   6512     }
   6513 
   6514     mod_cfg.modid_type = bcmStkModidTypeMultiNextHops;
   6515     BCM_IF_ERROR_RETURN(bcm_esw_stk_modid_config_get(unit, &mod_cfg));
   6516 
   6517     *count = 0;
   6518     if (gport_size == 0) {
   6519         for (mod_idx = mod_cfg.modid; mod_idx < mod_cfg.modid + mod_cfg.num_mods;
   6520              mod_idx ++) {
   6521              mod_idx %= 64;  /* lower 6 bit */
   6522              SOC_IF_ERROR_RETURN
   6523                 (READ_MODID_BASE_PTRm(unit, MEM_BLOCK_ANY, mod_idx, &modid_base_entry));
   6524              base_index = soc_MODID_BASE_PTRm_field32_get(unit,
   6525                                        &modid_base_entry, MODID_BASEf);
   6526              /* Search for unused index. */
   6527              for (port_idx = base_index; port_idx < base_index + mod_cfg.num_ports;
   6528                   port_idx++) {
   6529                   SOC_IF_ERROR_RETURN
   6530                       (READ_MODPORT_MAP_SUBPORTm(unit, MEM_BLOCK_ANY, port_idx,
   6531                                                  &modport_map_subport_entry));
   6532                   is_trunk = soc_MODPORT_MAP_SUBPORTm_field32_get(unit,
   6533                                               &modport_map_subport_entry, ISTRUNKf);
   6534                   /* Check if index is used. */
   6535                   egress_tid = soc_MODPORT_MAP_SUBPORTm_field32_get(unit,
   6536                                               &modport_map_subport_entry, DESTf);
   6537                   if (is_trunk && (egress_tid == tid)) {/*  Entry found. */
   6538                       (*count)++;
   6539                   }
   6540               }
   6541         }
   6542         return BCM_E_NONE;
   6543     }
   6544 
   6545     _bcm_gport_dest_t_init(&dest);
   6546     for (mod_idx = mod_cfg.modid; mod_idx < mod_cfg.modid + mod_cfg.num_mods;
   6547          mod_idx ++) {
   6548         mod_idx %= 64;  /* lower 6 bit */
   6549         SOC_IF_ERROR_RETURN
   6550             (READ_MODID_BASE_PTRm(unit, MEM_BLOCK_ANY, mod_idx, &modid_base_entry));
   6551         base_index = soc_MODID_BASE_PTRm_field32_get(unit,
   6552                                        &modid_base_entry, MODID_BASEf);
   6553         /* Search for unused index. */
   6554         for (port_idx = base_index; port_idx < base_index + mod_cfg.num_ports;
   6555              port_idx++) {
   6556             if ((*count) < gport_size) {
   6557                 SOC_IF_ERROR_RETURN
   6558                     (READ_MODPORT_MAP_SUBPORTm(unit, MEM_BLOCK_ANY, port_idx,
   6559                                                &modport_map_subport_entry));
   6560                 is_trunk = soc_MODPORT_MAP_SUBPORTm_field32_get(unit,
   6561                                               &modport_map_subport_entry, ISTRUNKf);
   6562                 /* Check if index is used. */
   6563                 egress_tid = soc_MODPORT_MAP_SUBPORTm_field32_get(unit,
   6564                                                &modport_map_subport_entry, DESTf);
   6565                 if (is_trunk && (egress_tid == tid)) {
   6566                     /*  Entry found. */
   6567                     dest.port = port_idx;
   6568                     dest.modid = mod_idx;
   6569                     dest.gport_type = _SHR_GPORT_TYPE_MODPORT;
   6570                     rv = _bcm_esw_gport_construct(unit, &dest, &modport);
   6571                     gport_array[(*count)++] = modport;
   6572                 }
   6573             }
   6574         }
   6575      }
   6576 
   6577     return rv;
   6578 
   6579 }
   6580 
   6581 /*
   6582  * Function    : _bcm_esw_trunk_gport_delete
   6583  * Description : Delete the GPORT ID for the specified trunk.
   6584  *
   6585  * Parameters  : (IN)  unit          - BCM device number
   6586  *                     (IN)  tid     - Trunk Group
   6587  *                     (IN)  gport   - GPORT ID
   6588  * Returns     : BCM_E_XXX
   6589  */
   6590 int
   6591 _bcm_esw_trunk_gport_delete(int unit, bcm_trunk_t tid, bcm_gport_t gport)
   6592 {
   6593     int id_out = 0;
   6594     int base_index = 0;
   6595     int is_trunk = 0;
   6596     int result = FALSE;
   6597     int subport_index = 0;
   6598     bcm_port_t port_out = 0;
   6599     bcm_module_t mod_out = 0;
   6600     bcm_trunk_t tgid_out = 0;
   6601     modid_base_ptr_entry_t modid_base_entry;
   6602     modport_map_subport_entry_t modport_map_subport_entry;
   6603     trunk_private_t *t_info;
   6604 
   6605     /* Make sure trunk module is initialized. */
   6606     TRUNK_INIT(unit);
   6607 
   6608     /* Parameter check */
   6609     if (!TRUNK_FABRIC_TID(unit, tid)) {
   6610         return BCM_E_PARAM;
   6611     }
   6612 
   6613     t_info = &TRUNK_INFO(unit, tid);
   6614     if (t_info->tid == BCM_TRUNK_INVALID) {
   6615         return BCM_E_NOT_FOUND;
   6616     }
   6617     tid -= TRUNK_CNTL(unit).ngroups_fp;
   6618 
   6619     if (!BCM_GPORT_IS_MODPORT(gport)) {
   6620         return BCM_E_PARAM;
   6621     }
   6622 
   6623     BCM_IF_ERROR_RETURN(_bcm_esw_gport_resolve(unit, gport,
   6624                             &mod_out, &port_out, &tgid_out, &id_out));
   6625     if ((-1 != tgid_out) || (-1 != id_out)) {
   6626         return BCM_E_PARAM;
   6627     }
   6628 
   6629     /* Check modport in one of additional module */
   6630     BCM_IF_ERROR_RETURN (
   6631         _bcm_esw_my_modid_additional_check(unit, mod_out, &result));
   6632     if (result == FALSE) {
   6633         return BCM_E_PARAM;
   6634     }
   6635 
   6636     mod_out %= 64;   /* lower 6 bit */
   6637     SOC_IF_ERROR_RETURN
   6638             (READ_MODID_BASE_PTRm(unit, MEM_BLOCK_ANY, mod_out,
   6639                                    &modid_base_entry));
   6640     base_index = soc_MODID_BASE_PTRm_field32_get(unit,
   6641                                    &modid_base_entry, MODID_BASEf);
   6642     subport_index = base_index; /* the index is indicated by module base ptr */
   6643     SOC_IF_ERROR_RETURN
   6644         (READ_MODPORT_MAP_SUBPORTm(unit, MEM_BLOCK_ANY, subport_index,
   6645                                    &modport_map_subport_entry));
   6646     is_trunk = soc_MODPORT_MAP_SUBPORTm_field32_get(unit,
   6647                                        &modport_map_subport_entry, ISTRUNKf);
   6648     if (!is_trunk) {
   6649         return BCM_E_NOT_FOUND;
   6650     }
   6651     soc_MODPORT_MAP_SUBPORTm_field32_set(unit,
   6652                                    &modport_map_subport_entry, DESTf, 0);
   6653     soc_MODPORT_MAP_SUBPORTm_field32_set (unit,
   6654                                    &modport_map_subport_entry, ISTRUNKf, 0);
   6655     soc_MODPORT_MAP_SUBPORTm_field32_set (unit,
   6656                                  &modport_map_subport_entry, ENABLEf, 0);
   6657     SOC_IF_ERROR_RETURN
   6658         (WRITE_MODPORT_MAP_SUBPORTm(unit, MEM_BLOCK_ANY, subport_index,
   6659                                         &modport_map_subport_entry));
   6660 
   6661     return BCM_E_NONE;
   6662 }
   6663 
   6664 /*
   6665  * Function    : _bcm_esw_trunk_gport_delete_all
   6666  * Description : Delete the GPORT ID for the specified trunk.
   6667  *
   6668  * Parameters  : (IN)  unit          - BCM device number
   6669  *                     (IN)  tid     - Trunk Group
   6670  * Returns     : BCM_E_XXX
   6671  */
   6672 int
   6673 _bcm_esw_trunk_gport_delete_all(int unit, bcm_trunk_t tid)
   6674 {
   6675     int mod_idx = 0;
   6676     int port_idx = 0;
   6677     int is_trunk = 0;
   6678     int base_index = 0;
   6679     bcm_trunk_t egress_tid = 0;
   6680     bcm_stk_modid_config_t mod_cfg;
   6681     modid_base_ptr_entry_t modid_base_entry;
   6682     modport_map_subport_entry_t modport_map_subport_entry;
   6683     trunk_private_t *t_info;
   6684 
   6685     /* Make sure trunk module is initialized. */
   6686     TRUNK_INIT(unit);
   6687 
   6688     /* Parameter check */
   6689     if (!TRUNK_FABRIC_TID(unit, tid)) {
   6690         return BCM_E_PARAM;
   6691     }
   6692     t_info = &TRUNK_INFO(unit, tid);
   6693     if (t_info->tid == BCM_TRUNK_INVALID) {
   6694         return BCM_E_NOT_FOUND;
   6695     }
   6696     tid -= TRUNK_CNTL(unit).ngroups_fp;
   6697 
   6698     mod_cfg.modid_type = bcmStkModidTypeMultiNextHops;
   6699     BCM_IF_ERROR_RETURN(
   6700         bcm_esw_stk_modid_config_get(unit, &mod_cfg));
   6701 
   6702     for (mod_idx = mod_cfg.modid; mod_idx < mod_cfg.modid + mod_cfg.num_mods;
   6703          mod_idx ++) {
   6704         mod_idx %= 64;   /* lower 6 bit */
   6705         SOC_IF_ERROR_RETURN
   6706             (READ_MODID_BASE_PTRm(unit, MEM_BLOCK_ANY, mod_idx, &modid_base_entry));
   6707         base_index = soc_MODID_BASE_PTRm_field32_get(unit,
   6708                                            &modid_base_entry, MODID_BASEf);
   6709         /* Search for unused index. */
   6710         for (port_idx = base_index; port_idx < base_index + mod_cfg.num_ports;
   6711             port_idx++) {
   6712             SOC_IF_ERROR_RETURN
   6713                 (READ_MODPORT_MAP_SUBPORTm(unit, MEM_BLOCK_ANY, port_idx,
   6714                                            &modport_map_subport_entry));
   6715             is_trunk = soc_MODPORT_MAP_SUBPORTm_field32_get(unit,
   6716                                        &modport_map_subport_entry, ISTRUNKf);
   6717             /* Check if index is used. */
   6718             egress_tid = soc_MODPORT_MAP_SUBPORTm_field32_get(unit,
   6719                                            &modport_map_subport_entry, DESTf);
   6720             if (is_trunk && (egress_tid == tid)) {
   6721                 /*  Entry found. */
   6722                 soc_MODPORT_MAP_SUBPORTm_field32_set (unit,
   6723                                            &modport_map_subport_entry, DESTf, 0);
   6724                 soc_MODPORT_MAP_SUBPORTm_field32_set (unit,
   6725                                            &modport_map_subport_entry, ISTRUNKf, 0);
   6726                 soc_MODPORT_MAP_SUBPORTm_field32_set (unit,
   6727                                            &modport_map_subport_entry, ENABLEf, 0);
   6728                 SOC_IF_ERROR_RETURN
   6729                     (WRITE_MODPORT_MAP_SUBPORTm(unit, MEM_BLOCK_ANY, port_idx,
   6730                                                 &modport_map_subport_entry));
   6731             }
   6732         }
   6733     }
   6734 
   6735     return BCM_E_NONE;
   6736 }
   6737 
   6738 #endif /* BCM_TRIDENT2PLUS_SUPPORT */
   6739 
   6740 /*
   6741  * Function    : bcm_esw_trunk_gport_add
   6742  * Description : Add the GPORT ID for the specified trunk.
   6743  *
   6744  * Parameters  : (IN)  unit          - BCM device number
   6745  *                     (IN)  tid     - Trunk Group
   6746  *                     (IN)  gport   - GPORT ID
   6747  * Returns     : BCM_E_XXX
   6748  */
   6749 int
   6750 bcm_esw_trunk_gport_add(int unit, bcm_trunk_t tid, bcm_gport_t gport)
   6751 {
   6752     int rv = BCM_E_UNAVAIL;
   6753 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   6754     if (soc_feature(unit, soc_feature_multi_next_hops_on_port)) {
   6755         rv = _bcm_esw_trunk_gport_add(unit, tid, gport);
   6756     }
   6757 #endif
   6758     return rv;
   6759 }
   6760 
   6761 /*
   6762  * Function    : bcm_esw_trunk_gport_get_all
   6763  * Description : Add the GPORT ID for the specified trunk.
   6764  *
   6765  * Parameters  : (IN)  unit               - BCM device number
   6766  *                     (IN)  tid          - Trunk Group
   6767  *                     (IN)  gport_size   - GPORT ID
   6768                        (OUT) gport_array  - GPORT Array
   6769                        (OUT) count        - GPORT Count
   6770  * Returns     : BCM_E_XXX
   6771  */
   6772 int
   6773 bcm_esw_trunk_gport_get_all(int unit, bcm_trunk_t tid, int gport_size,
   6774                             bcm_gport_t *gport_array, int *count)
   6775 {
   6776     int rv = BCM_E_UNAVAIL;
   6777 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   6778     if (soc_feature(unit, soc_feature_multi_next_hops_on_port)) {
   6779         if (gport_size < 0 || count == NULL) {
   6780             return BCM_E_PARAM;
   6781         }
   6782 
   6783         if ((gport_size > 0) && gport_array == NULL) {
   6784             return BCM_E_PARAM;
   6785         }
   6786 
   6787         rv = _bcm_esw_trunk_gport_get_all(unit, tid, gport_size, gport_array, count);
   6788     }
   6789 #endif
   6790     return rv;
   6791 }
   6792 
   6793 /*
   6794  * Function    : bcm_esw_trunk_gport_delete
   6795  * Description : Delete the GPORT ID for the specified trunk.
   6796  *
   6797  * Parameters  : (IN)  unit          - BCM device number
   6798  *                     (IN)  tid     - Trunk Group
   6799  *                     (IN)  gport   - GPORT ID
   6800  * Returns     : BCM_E_XXX
   6801  */
   6802 int
   6803 bcm_esw_trunk_gport_delete(int unit, bcm_trunk_t tid, bcm_gport_t gport)
   6804 {
   6805     int rv = BCM_E_UNAVAIL;
   6806 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   6807     if (soc_feature(unit, soc_feature_multi_next_hops_on_port)) {
   6808         rv = _bcm_esw_trunk_gport_delete(unit, tid, gport);
   6809     }
   6810 #endif
   6811     return rv;
   6812 }
   6813 
   6814 /*
   6815  * Function    : bcm_esw_trunk_gport_delete_all
   6816  * Description : Delete the GPORT ID for the specified trunk.
   6817  *
   6818  * Parameters  : (IN)  unit          - BCM device number
   6819  *                     (IN)  tid     - Trunk Group
   6820  * Returns     : BCM_E_XXX
   6821  */
   6822 int
   6823 bcm_esw_trunk_gport_delete_all(int unit, bcm_trunk_t tid)
   6824 {
   6825     int rv = BCM_E_UNAVAIL;
   6826 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   6827     if (soc_feature(unit, soc_feature_multi_next_hops_on_port)) {
   6828         rv = _bcm_esw_trunk_gport_delete_all(unit, tid);
   6829     }
   6830 #endif
   6831     return rv;
   6832 }
   6833 
   6834 /*
   6835  * Function:
   6836  *      _bcm_esw_trunk_local_members_get
   6837  * Purpose:
   6838  *      Get local member ports of a trunk group.
   6839  * Parameters:
   6840  *      unit       - (IN) Device Number
   6841  *      trunk_id   - (IN) Trunk Identifier
   6842  *      local_member_max   - (OUT) Size of local_member_array
   6843  *      local_member_array - (OUT) Array of local trunk members 
   6844  *      local_member_count - (OUT) Number of local trunk members
   6845  * Returns:
   6846  *      BCM_E_XXX
   6847  * Notes:
   6848  *      If local_member_max = 0 and local_member_array == NULL,
   6849  *      the number of local trunk members will still be returned in
   6850  *      local_member_count. 
   6851  */
   6852 
   6853 int 
   6854 _bcm_esw_trunk_local_members_get(int unit, bcm_trunk_t trunk_id, 
   6855                                  int local_member_max, 
   6856                                  bcm_port_t *local_member_array, 
   6857                                  int *local_member_count)
   6858 {
   6859     int rv;
   6860     int member_count;
   6861     bcm_trunk_member_t *member_array;
   6862     int i;
   6863     bcm_module_t mod_out;
   6864     bcm_port_t port_out;
   6865     bcm_trunk_t tgid_out;
   6866     int id_out;
   6867     int modid_local;
   6868     bcm_trunk_info_t trunk_info;
   6869 #if defined(BCM_KATANA2_SUPPORT)
   6870     int local_subport = 0;
   6871 #endif
   6872 
   6873     if (local_member_max < 0) {
   6874         return BCM_E_PARAM;
   6875     }
   6876 
   6877     if ((local_member_max == 0) && (NULL != local_member_array)) {
   6878         return BCM_E_PARAM;
   6879     }
   6880 
   6881     if ((local_member_max > 0) && (NULL == local_member_array)) {
   6882         return BCM_E_PARAM;
   6883     }
   6884 
   6885     if (NULL == local_member_count) {
   6886         return BCM_E_PARAM;
   6887     }
   6888 
   6889     *local_member_count = 0;
   6890 
   6891     BCM_IF_ERROR_RETURN(_bcm_trunk_id_validate(unit, trunk_id));
   6892 
   6893     /* First, get the number of trunk members. */
   6894     rv = bcm_esw_trunk_get(unit, trunk_id, &trunk_info, 0, NULL, &member_count);
   6895     if (BCM_FAILURE(rv)) {
   6896         return BCM_E_PORT;
   6897     }
   6898 
   6899     if (0 == member_count) {
   6900         return BCM_E_NONE;
   6901     }
   6902 
   6903     member_array = sal_alloc(sizeof(bcm_trunk_member_t) * member_count,
   6904             "trunk member array");
   6905     if (member_array == NULL) {
   6906         return BCM_E_MEMORY;
   6907     }
   6908     sal_memset(member_array, 0, sizeof(bcm_trunk_member_t) * member_count);
   6909 
   6910     rv = bcm_esw_trunk_get(unit, trunk_id, &trunk_info, member_count,
   6911             member_array, &member_count);
   6912     if (BCM_FAILURE(rv)) {
   6913         sal_free(member_array);
   6914         return BCM_E_PORT;
   6915     }
   6916 
   6917     for (i = 0; i < member_count; i++) {
   6918         rv = _bcm_esw_gport_resolve(unit, member_array[i].gport,
   6919                 &mod_out, &port_out, &tgid_out, &id_out);
   6920         if (BCM_FAILURE(rv)) {
   6921             sal_free(member_array);
   6922             return rv;
   6923         }
   6924 
   6925 #if defined(BCM_KATANA2_SUPPORT)
   6926         /* Coverity fix for leaked_storage issue. Freeing member_array
   6927         if the function returns with error */
   6928         rv = _bcm_kt2_modport_is_local_coe_subport(unit,
   6929                  mod_out, port_out, &local_subport);
   6930         if (BCM_FAILURE(rv)) {
   6931             sal_free(member_array);
   6932             return rv;
   6933         }
   6934         if (local_subport) {
   6935             if (NULL != local_member_array) {
   6936                 local_member_array[*local_member_count] =
   6937                     BCM_GPORT_SUBPORT_PORT_GET(member_array[i].gport);
   6938             }
   6939             (*local_member_count)++;
   6940             if (*local_member_count == local_member_max) {
   6941                 break;
   6942             }
   6943         }
   6944 #endif
   6945 
   6946 #ifdef BCM_HGPROXY_COE_SUPPORT
   6947         if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) &&
   6948             _bcm_xgs5_subport_coe_mod_port_local(unit, mod_out, port_out)) {
   6949             rv = _bcmi_coe_subport_mod_port_physical_port_get(
   6950                      unit, mod_out, port_out, &port_out);
   6951             if (BCM_FAILURE(rv)) {
   6952                 sal_free(member_array);
   6953                 return rv;
   6954             }
   6955             modid_local = 1;
   6956         } else
   6957 #endif
   6958         {
   6959             rv = _bcm_esw_modid_is_local(unit, mod_out, &modid_local);
   6960             if (BCM_FAILURE(rv)) {
   6961                 sal_free(member_array);
   6962                 return rv;
   6963             }
   6964         }
   6965 
   6966         if (modid_local) {
   6967             /* Convert system port to physical port */
   6968             if (soc_feature(unit, soc_feature_sysport_remap)) {
   6969                 BCM_XLATE_SYSPORT_S2P(unit, &port_out);
   6970             }
   6971 
   6972             if (NULL != local_member_array) {
   6973                 local_member_array[*local_member_count] = port_out;
   6974             }
   6975             (*local_member_count)++;
   6976             if (*local_member_count == local_member_max) {
   6977                 break;
   6978             }
   6979         }
   6980     }
   6981 
   6982     sal_free(member_array);
   6983 
   6984     return BCM_E_NONE;
   6985 }
   6986 
   6987 #ifdef BCM_WARM_BOOT_SUPPORT
   6988 
   6989 #define TRUNK_MIN_FABRIC_TID(unit) \
   6990     (TRUNK_CNTL(unit).ngroups_hg ? TRUNK_CNTL(unit).ngroups_fp : -1)
   6991 #define TRUNK_MAX_FABRIC_TID(unit) \
   6992     ( TRUNK_CNTL(unit).ngroups_hg ? \
   6993      (TRUNK_CNTL(unit).ngroups_fp + TRUNK_CNTL(unit).ngroups_hg - 1): -1)
   6994 
   6995 /*
   6996  * _bcm_trunk_lag_reinit
   6997  *
   6998  * Restores sw state for front pannel trunks
   6999  * Note: Application must register modid-port mapping function
   7000  *       using bcm_stk_modmap_register before calling this
   7001  */
   7002 STATIC int
   7003 _bcm_trunk_lag_reinit(int unit)
   7004 {
   7005 #if defined(BCM_TRIDENT_SUPPORT)
   7006     if (soc_feature(unit, soc_feature_shared_trunk_member_table)) {
   7007         return (_bcm_trident_trunk_lag_reinit(unit, TRUNK_CNTL(unit).ngroups_fp,
   7008                                    TRUNK_CNTL(unit).t_info));
   7009     } else 
   7010 #ifdef BCM_TOMAHAWK3_SUPPORT
   7011     if (SOC_IS_TOMAHAWK3(unit)) {
   7012 
   7013         return (_bcm_th3_trunk_lag_reinit(unit, TRUNK_CNTL(unit).ngroups_fp,
   7014                                    TRUNK_CNTL(unit).t_info));
   7015     } else
   7016 #endif /*BCM_TOMAHAWK3_SUPPORT*/
   7017 #endif /* BCM_TRIDENT_SUPPORT */
   7018 
   7019 #if defined(BCM_FIREBOLT_SUPPORT)
   7020     if (SOC_IS_FBX(unit)) {
   7021         return (_xgs3_trunk_reinit(unit, TRUNK_CNTL(unit).ngroups_fp,
   7022                                    TRUNK_CNTL(unit).t_info));
   7023     }
   7024 #endif /* BCM_FIREBOLT_SUPPORT */
   7025 
   7026     return BCM_E_NONE;
   7027 }
   7028 
   7029 /*
   7030  * _bcm_trunk_fabric_reinit
   7031  *
   7032  * Restores sw state for fabric trunks
   7033  */
   7034 STATIC int
   7035 _bcm_trunk_fabric_reinit(int unit)
   7036 {
   7037 #if defined(BCM_TRIDENT_SUPPORT)
   7038     if (soc_feature(unit, soc_feature_shared_trunk_member_table)) {
   7039         int min_tid = TRUNK_MIN_FABRIC_TID(unit);
   7040 
   7041         return (_bcm_trident_trunk_fabric_reinit(unit, 
   7042                                           TRUNK_MIN_FABRIC_TID(unit),
   7043                                           TRUNK_MAX_FABRIC_TID(unit),
   7044                                           &TRUNK_INFO(unit,min_tid)));
   7045     } else 
   7046 #endif /* BCM_TRIDENT_SUPPORT */
   7047 #if defined(BCM_FIREBOLT_SUPPORT)
   7048     if (SOC_IS_FBX(unit) && !SOC_IS_RAPTOR(unit)) {
   7049         int min_tid = TRUNK_MIN_FABRIC_TID(unit);
   7050         if (SOC_IS_TOMAHAWKX(unit)) {
   7051             if (soc_feature(unit, soc_feature_higig2)) {
   7052                 /* In TH, HG ports are not supported in low latency modes */
   7053                 return (_xgs3_trunk_fabric_reinit(unit, 
   7054                                           TRUNK_MIN_FABRIC_TID(unit),
   7055                                           TRUNK_MAX_FABRIC_TID(unit),
   7056                                           &TRUNK_INFO(unit,min_tid)));
   7057             }
   7058         } else {
   7059             return (_xgs3_trunk_fabric_reinit(unit, 
   7060                                           TRUNK_MIN_FABRIC_TID(unit),
   7061                                           TRUNK_MAX_FABRIC_TID(unit),
   7062                                           &TRUNK_INFO(unit,min_tid)));
   7063         }
   7064     }
   7065 #endif /* BCM_FIREBOLT_SUPPORT */
   7066 
   7067     return BCM_E_NONE;
   7068 }
   7069 
   7070 /*
   7071  * _bcm_trunk_reinit
   7072  *
   7073  * Recovers trunk state from hardware (Reload)
   7074  */
   7075 int
   7076 _bcm_trunk_reinit(int unit)
   7077 {
   7078     int                 rv;
   7079     bcm_trunk_t         tid;
   7080     trunk_private_t     *t_info;
   7081     soc_scache_handle_t scache_handle;
   7082     uint8               *trunk_scache;
   7083     uint16              recovered_ver;
   7084     uint32              ngroups;
   7085     uint8               flags;
   7086     int                 recovered_dlf_index;
   7087 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT)
   7088     bcm_trunk_t         hgtid;
   7089     int                 tix, idx;
   7090     int                 fp_hwf_recover = 1;
   7091 #endif /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */
   7092     uint32              additional_scache_size;
   7093 #if defined(BCM_SABER2_SUPPORT)
   7094     uint32              fp_ngroups = 0;
   7095     uint32              hg_ngroups = 0;
   7096     uint16              default_ver = BCM_WB_DEFAULT_VERSION;
   7097 #endif /* BCM_SABER2_SUPPORT */
   7098  	 
   7099     /*
   7100      * Trunk state initialization
   7101      */
   7102     t_info = TRUNK_CNTL(unit).t_info;
   7103 
   7104     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_TRUNK, 0);
   7105     rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE,
   7106                                  0, &trunk_scache,  
   7107                                  BCM_WB_DEFAULT_VERSION, &recovered_ver);
   7108 
   7109     if (BCM_E_NOT_FOUND == rv) {
   7110         trunk_scache = NULL;
   7111     } else if (BCM_FAILURE(rv)) {
   7112         return rv;
   7113     } else {
   7114         /* Validate trunk info matches */
   7115 #if defined(BCM_SABER2_SUPPORT)
   7116         if (SOC_IS_SABER2(unit) && soc_sb2_5626x_devtype(unit) &&
   7117                 (recovered_ver <= BCM_WB_VERSION_1_4) &&
   7118                 (default_ver > BCM_WB_VERSION_1_4)) {
   7119             sal_memcpy(&fp_ngroups, trunk_scache, sizeof(ngroups));
   7120             ngroups = SABER2_5626X_NGROUPS_FP;
   7121         } else
   7122 #endif /* BCM_SABER2_SUPPORT */
   7123         {
   7124             sal_memcpy(&ngroups, trunk_scache, sizeof(ngroups));
   7125         }
   7126         if (ngroups != TRUNK_CNTL(unit).ngroups_fp) {
   7127             return BCM_E_CONFIG;
   7128         }
   7129         trunk_scache += sizeof(ngroups);
   7130         
   7131 #if defined(BCM_SABER2_SUPPORT)
   7132         if (SOC_IS_SABER2(unit) && soc_sb2_5626x_devtype(unit) &&
   7133                 (recovered_ver <= BCM_WB_VERSION_1_4) &&
   7134                 (default_ver > BCM_WB_VERSION_1_4)) {
   7135             sal_memcpy(&hg_ngroups, trunk_scache, sizeof(ngroups));
   7136             ngroups = SABER2_5626X_NGROUPS_HG;
   7137         } else
   7138 #endif /* BCM_SABER2_SUPPORT */
   7139         {
   7140             sal_memcpy(&ngroups, trunk_scache, sizeof(ngroups));
   7141         }
   7142         if (ngroups != TRUNK_CNTL(unit).ngroups_hg) {
   7143             return BCM_E_CONFIG;
   7144         }
   7145         trunk_scache += sizeof(ngroups);
   7146 
   7147         sal_memset(TRUNK_CNTL(unit).trunk_bmp_ptr, 0,
   7148                    TRUNK_CNTL(unit).trunk_bmp_alloc);
   7149         sal_memcpy(TRUNK_CNTL(unit).trunk_bmp_ptr, trunk_scache,
   7150                    TRUNK_CNTL(unit).trunk_bmp_alloc);
   7151 
   7152         for (tid = 0; tid < TRUNK_NUM_GROUPS(unit); tid++) {
   7153             if (SHR_BITGET(TRUNK_CNTL(unit).trunk_bmp_ptr, tid)) {
   7154                 t_info->tid = tid;
   7155             }
   7156             t_info++;
   7157         }
   7158 #if defined(BCM_SABER2_SUPPORT)
   7159         if (SOC_IS_SABER2(unit) && soc_sb2_5626x_devtype(unit) &&
   7160                 (recovered_ver <= BCM_WB_VERSION_1_4) &&
   7161                 (default_ver > BCM_WB_VERSION_1_4)) {
   7162             int tmp_trunk_bmp_alloc = SHR_BITALLOCSIZE(fp_ngroups + hg_ngroups);
   7163             trunk_scache += tmp_trunk_bmp_alloc;
   7164         } else
   7165 #endif /* BCM_SABER2_SUPPORT */
   7166         {
   7167             trunk_scache += TRUNK_CNTL(unit).trunk_bmp_alloc;
   7168         }
   7169 
   7170 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT)
   7171 #if defined(BCM_TRIDENT2_SUPPORT)
   7172         /* WarmBoot recovery support for front panel ports hardware failover
   7173          * configuration(for scorpion) is always present in SDK.
   7174          * But hardware failover support for front panel ports in Trident2
   7175          * is added when trunk scache is at WB version 1.3 by enabling the
   7176          * corresponding soc_feature. A new version 1.4 is introducted to
   7177          * recover front panel hardware failover configuration on Trident2.
   7178          */
   7179         if (SOC_IS_TRIDENT2(unit) && recovered_ver <= BCM_WB_VERSION_1_3) {
   7180             fp_hwf_recover = 0;
   7181         }
   7182 #endif /* BCM_TRIDENT2_SUPPORT */
   7183 
   7184         if ((TRUNK_CNTL(unit).fp_hwf_alloc) && (fp_hwf_recover)) {
   7185             idx = 0;
   7186             sal_memcpy(TRUNK_CNTL(unit).fp_hwf_flags, trunk_scache,
   7187                        TRUNK_CNTL(unit).fp_hwf_alloc);
   7188 #if defined(BCM_SABER2_SUPPORT)
   7189             if (SOC_IS_SABER2(unit) && soc_sb2_5626x_devtype(unit) &&
   7190                     (recovered_ver <= BCM_WB_VERSION_1_4) &&
   7191                     (default_ver > BCM_WB_VERSION_1_4)) {
   7192                 int tmp_fp_hwf_alloc = (fp_ngroups * 3 +
   7193                         soc_mem_index_count(unit, SOURCE_TRUNK_MAP_TABLEm)) *
   7194                     sizeof(uint8);
   7195                 trunk_scache += tmp_fp_hwf_alloc;
   7196             } else
   7197 #endif /* BCM_SABER2_SUPPORT */
   7198             {
   7199                 trunk_scache += TRUNK_CNTL(unit).fp_hwf_alloc;
   7200             }
   7201 
   7202             if (soc_feature(unit, soc_feature_port_lag_failover)) {
   7203                 /* FP trunk failover flags */
   7204                 for (tid = 0; tid < TRUNK_CNTL(unit).ngroups_fp; tid++) {
   7205                     TRUNK_INFO(unit, tid).flags =
   7206                         TRUNK_CNTL(unit).fp_hwf_flags[idx++];
   7207 #ifdef BCM_TRIDENT_SUPPORT
   7208                     if (soc_feature(unit, soc_feature_shared_trunk_member_table)) {
   7209                         uint16 num_ports;
   7210                         num_ports = TRUNK_CNTL(unit).fp_hwf_flags[idx++] << 8;
   7211                         num_ports += TRUNK_CNTL(unit).fp_hwf_flags[idx++];
   7212                         _bcm_trident_hw_failover_num_ports_set(unit, tid,
   7213                                 FALSE, num_ports);
   7214                         for (tix = 0; tix < num_ports; tix++) {
   7215                             BCM_IF_ERROR_RETURN
   7216                                 (_bcm_trident_hw_failover_flags_set(unit, tid,
   7217                                     tix, FALSE, 
   7218                                     TRUNK_CNTL(unit).fp_hwf_flags[idx++]));
   7219                         }
   7220 
   7221                     } else
   7222  #ifdef BCM_TOMAHAWK3_SUPPORT
   7223                     if (SOC_IS_TOMAHAWK3(unit)) {
   7224                         uint16 num_ports;
   7225                         num_ports = TRUNK_CNTL(unit).fp_hwf_flags[idx++] << 8;
   7226                         num_ports += TRUNK_CNTL(unit).fp_hwf_flags[idx++];
   7227                         _bcm_th3_trunk_hwfailover_num_ports_set(unit, tid,
   7228                                 num_ports);
   7229                         for (tix = 0; tix < num_ports; tix++) {
   7230                                 _bcm_th3_trunk_hwfailover_flags_set(unit, tid,
   7231                                     tix, TRUNK_CNTL(unit).fp_hwf_flags[idx++]);
   7232                         }
   7233 
   7234                     } else
   7235 #endif
   7236 #endif /* BCM_TRIDENT_SUPPORT */
   7237                     {
   7238                         for (tix = 0; tix < TRUNK_CNTL(unit).nports_fp; tix++) {
   7239                             _bcm_xgs3_hw_failover_flags_set(unit, tid,
   7240                                     tix, FALSE,
   7241                                     TRUNK_CNTL(unit).fp_hwf_flags[idx++]);
   7242                         }
   7243                     }
   7244                 }
   7245             }
   7246         }
   7247 
   7248         if (TRUNK_CNTL(unit).hg_hwf_alloc) {
   7249             idx = 0;
   7250 
   7251             sal_memcpy(TRUNK_CNTL(unit).hg_hwf_flags, trunk_scache,
   7252                        TRUNK_CNTL(unit).hg_hwf_alloc);
   7253 #if defined(BCM_SABER2_SUPPORT)
   7254             if (SOC_IS_SABER2(unit) && soc_sb2_5626x_devtype(unit) &&
   7255                     (recovered_ver <= BCM_WB_VERSION_1_4) &&
   7256                     (default_ver > BCM_WB_VERSION_1_4)) {
   7257                 int  tmp_hg_hwf_alloc = (hg_ngroups * (hg_ngroups + 1)) *
   7258                     sizeof(uint8);
   7259                 trunk_scache += tmp_hg_hwf_alloc;
   7260             } else
   7261 #endif /* BCM_SABER2_SUPPORT */
   7262             {
   7263                 trunk_scache += TRUNK_CNTL(unit).hg_hwf_alloc;
   7264             }
   7265 
   7266             if (soc_feature(unit, soc_feature_hg_trunk_failover)) {
   7267                 /* HG trunk failover flags */
   7268                 for (tid = TRUNK_CNTL(unit).ngroups_fp;
   7269                      tid < TRUNK_NUM_GROUPS(unit); tid++) {
   7270                     TRUNK_INFO(unit, tid).flags =
   7271                         TRUNK_CNTL(unit).hg_hwf_flags[idx++];
   7272                     hgtid = tid - TRUNK_CNTL(unit).ngroups_fp;
   7273 #ifdef BCM_TRIDENT_SUPPORT
   7274                     if (soc_feature(unit, soc_feature_shared_trunk_member_table)) {
   7275                         uint16 num_ports;
   7276                         num_ports = TRUNK_CNTL(unit).hg_hwf_flags[idx++];
   7277                         _bcm_trident_hw_failover_num_ports_set(unit, hgtid,
   7278                                 TRUE, num_ports);
   7279                         for (tix = 0; tix < num_ports; tix++) {
   7280                             _bcm_trident_hw_failover_flags_set(unit, hgtid,
   7281                                     tix, TRUE, 
   7282                                     TRUNK_CNTL(unit).hg_hwf_flags[idx++]);
   7283                         }
   7284 
   7285                     } else
   7286 #endif /* BCM_TRIDENT_SUPPORT */
   7287                     {
   7288                         for (tix = 0; tix < TRUNK_CNTL(unit).nports_hg; tix++) {
   7289                             _bcm_xgs3_hw_failover_flags_set(unit, hgtid,
   7290                                     tix, TRUE,
   7291                                     TRUNK_CNTL(unit).hg_hwf_flags[idx++]);
   7292                         }
   7293                     }
   7294                 }
   7295             }
   7296         }
   7297 #endif /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */
   7298 
   7299         additional_scache_size = 0;
   7300 
   7301         if (recovered_ver >= BCM_WB_VERSION_1_1) {
   7302             /* Recover BCM_TRUNK_FLAG_IPMC_CLEAVE flag */
   7303             for (tid = 0; tid < TRUNK_CNTL(unit).ngroups_fp; tid++) {
   7304                 sal_memcpy(&flags, trunk_scache, sizeof(uint8));
   7305                 trunk_scache += sizeof(uint8);
   7306                 if (flags & 0x1) {
   7307                     t_info = &TRUNK_INFO(unit, tid);
   7308                     t_info->flags |= BCM_TRUNK_FLAG_IPMC_CLEAVE;
   7309                 }
   7310             }
   7311 #if defined(BCM_SABER2_SUPPORT)
   7312             if (SOC_IS_SABER2(unit) && soc_sb2_5626x_devtype(unit) &&
   7313                     (recovered_ver <= BCM_WB_VERSION_1_4) &&
   7314                     (default_ver > BCM_WB_VERSION_1_4)) {
   7315                 int  tmp_ngroups_fp =
   7316                     (fp_ngroups - TRUNK_CNTL(unit).ngroups_fp) *
   7317                     sizeof(uint8);
   7318                 trunk_scache += tmp_ngroups_fp;
   7319             }
   7320 #endif /* BCM_SABER2_SUPPORT */
   7321             /* Recover ipmc_psc */ 
   7322             for (tid = 0; tid < TRUNK_CNTL(unit).ngroups_fp; tid++) {
   7323                 t_info = &TRUNK_INFO(unit, tid);
   7324                 sal_memcpy(&t_info->ipmc_psc, trunk_scache, sizeof(int));
   7325                 trunk_scache += sizeof(int);
   7326             }
   7327 #if defined(BCM_SABER2_SUPPORT)
   7328             if (SOC_IS_SABER2(unit) && soc_sb2_5626x_devtype(unit) &&
   7329                     (recovered_ver <= BCM_WB_VERSION_1_4) &&
   7330                     (default_ver > BCM_WB_VERSION_1_4)) {
   7331                 int  tmp_ngroups_fp =
   7332                     (fp_ngroups - TRUNK_CNTL(unit).ngroups_fp) *
   7333                     sizeof(int);
   7334                 trunk_scache += tmp_ngroups_fp;
   7335             }
   7336 #endif /* BCM_SABER2_SUPPORT */
   7337         } else {
   7338             additional_scache_size += (TRUNK_CNTL(unit).ngroups_fp *
   7339                     sizeof(uint8));
   7340             additional_scache_size += (TRUNK_CNTL(unit).ngroups_fp *
   7341                     sizeof(int));
   7342         }
   7343 
   7344         if (recovered_ver >= BCM_WB_VERSION_1_2) {
   7345             /* Recover front panel trunk membership */
   7346             for (tid = 0; tid < TRUNK_CNTL(unit).ngroups_fp; tid++) {
   7347 #if defined(BCM_TRIDENT_SUPPORT)
   7348                 if (soc_feature(unit, soc_feature_shared_trunk_member_table)) {
   7349                     uint16 num_ports;
   7350                     uint16 *modport;
   7351                     uint32 *member_flags;
   7352                     uint8 truncated_flags;
   7353                     int i;
   7354 
   7355                     sal_memcpy(&num_ports, trunk_scache, sizeof(uint16));
   7356                     trunk_scache += sizeof(uint16);
   7357 
   7358                     modport = sal_alloc(sizeof(uint16) * num_ports, "modport");
   7359                     if (NULL == modport) {
   7360                         return BCM_E_MEMORY;
   7361                     }
   7362                     member_flags = sal_alloc(sizeof(uint32) * num_ports,
   7363                             "member_flags");
   7364                     if (NULL == member_flags) {
   7365                         sal_free(modport);
   7366                         return BCM_E_MEMORY;
   7367                     }
   7368 
   7369 #if defined(BCM_SABER2_SUPPORT)
   7370                     if (SOC_IS_SABER2(unit) && soc_sb2_5626x_devtype(unit) &&
   7371                             (recovered_ver <= BCM_WB_VERSION_1_4) &&
   7372                             (default_ver > BCM_WB_VERSION_1_4) &&
   7373                             (num_ports > TRUNK_CNTL(unit).nports_fp)) {
   7374                         LOG_ERROR(BSL_LS_BCM_TRUNK, (BSL_META_U(unit,
   7375                                         "ERROR: Maximum port supported on "
   7376                                         "5626x devices are %d\n"
   7377                                         "Trunk id: %d has extra %d ports "
   7378                                         "Please remove extra ports "
   7379                                         "re-sync and update/warm boot\n"),
   7380                                     TRUNK_CNTL(unit).nports_fp, tid,
   7381                                     num_ports -
   7382                                     TRUNK_CNTL(unit).nports_fp));
   7383                         sal_free(modport);
   7384                         sal_free(member_flags);
   7385                         return BCM_E_CONFIG;
   7386                     }
   7387 #endif /* BCM_SABER2_SUPPORT */
   7388                     for (i = 0; i < num_ports; i++) {
   7389                         sal_memcpy(&modport[i], trunk_scache, sizeof(uint16));
   7390                         trunk_scache += sizeof(uint16);
   7391                         sal_memcpy(&truncated_flags, trunk_scache,
   7392                                 sizeof(uint8));
   7393                         trunk_scache += sizeof(uint8);
   7394                         member_flags[i] = truncated_flags;
   7395                     }
   7396                     rv = _bcm_trident_trunk_member_info_set(unit, tid,
   7397                             num_ports, modport, member_flags);
   7398                     sal_free(modport);
   7399                     sal_free(member_flags);
   7400                     if (BCM_FAILURE(rv)) {
   7401                         return rv;
   7402                     }
   7403                 } else 
   7404 #if defined(BCM_TOMAHAWK3_SUPPORT)
   7405                 if (SOC_IS_TOMAHAWK3(unit)) {
   7406                     uint16 num_ports;
   7407                     uint8  *member_port;
   7408                     uint32 *member_flags;
   7409                     uint8 truncated_flags;
   7410                     int i;
   7411 
   7412                     sal_memcpy(&num_ports, trunk_scache, sizeof(uint16));
   7413                     trunk_scache += sizeof(uint16);
   7414                     if (num_ports == 0) {
   7415                         continue;
   7416                     }
   7417                     t_info = &TRUNK_INFO(unit, tid);
   7418                     t_info->in_use = 1;
   7419 
   7420                     member_port = sal_alloc(sizeof(uint8) * num_ports, "port");
   7421                     if (NULL == member_port) {
   7422                         return BCM_E_MEMORY;
   7423                     }
   7424                     member_flags = sal_alloc(sizeof(uint32) * num_ports,
   7425                             "member_flags");
   7426                     if (NULL == member_flags) {
   7427                         sal_free(member_port);
   7428                         return BCM_E_MEMORY;
   7429                     }
   7430 
   7431                     for (i = 0; i < num_ports; i++) {
   7432                         sal_memcpy(&member_port[i], trunk_scache, sizeof(uint8));
   7433                         trunk_scache += sizeof(uint8);
   7434                         sal_memcpy(&truncated_flags, trunk_scache,
   7435                                 sizeof(uint8));
   7436                         trunk_scache += sizeof(uint8);
   7437                         member_flags[i] = truncated_flags;
   7438                     }
   7439                     rv = _bcm_th3_trunk_member_info_set(unit, tid,
   7440                             num_ports, member_port, member_flags);
   7441                     sal_free(member_port);
   7442                     sal_free(member_flags);
   7443                     if (BCM_FAILURE(rv)) {
   7444                         return rv;
   7445                     }
   7446                 } else 
   7447 #endif /* BCM_TOMAHAWK3_SUPPORT */
   7448 #endif /* BCM_TRIDENT_SUPPORT */
   7449 #if defined(BCM_XGS3_SWITCH_SUPPORT)
   7450                 {
   7451                     uint8 num_ports = 0;
   7452                     uint16 *modport;
   7453                     uint32 *member_flags;
   7454                     uint8 truncated_flags;
   7455                     int i;
   7456 
   7457                     sal_memcpy(&num_ports, trunk_scache, sizeof(uint8));
   7458                     trunk_scache += sizeof(uint8);
   7459                     modport = sal_alloc(sizeof(uint16) * num_ports, "modport");
   7460                     if (NULL == modport) {
   7461                         return BCM_E_MEMORY;
   7462                     }
   7463                     member_flags = sal_alloc(sizeof(uint32) * num_ports,
   7464                             "member_flags");
   7465                     if (NULL == member_flags) {
   7466                         sal_free(modport);
   7467                         return BCM_E_MEMORY;
   7468                     }
   7469 
   7470                     sal_memset(modport, 0,
   7471                                (sizeof(uint16) * num_ports));
   7472                     sal_memset(member_flags, 0,
   7473                                (sizeof(uint32) * num_ports));
   7474                     for (i = 0; i < num_ports; i++) {
   7475                         sal_memcpy(&modport[i], trunk_scache, sizeof(uint16));
   7476                         trunk_scache += sizeof(uint16);
   7477                         sal_memcpy(&truncated_flags, trunk_scache,
   7478                                 sizeof(uint8));
   7479                         trunk_scache += sizeof(uint8);
   7480                         member_flags[i] = truncated_flags;
   7481                     }
   7482                     _bcm_xgs3_trunk_member_info_set(unit, tid, num_ports,
   7483                             modport, member_flags);
   7484                     sal_free(modport);
   7485                     sal_free(member_flags);
   7486                 }
   7487 #endif /* BCM_XGS3_SWITCH_SUPPORT */
   7488             }
   7489 #if defined(BCM_SABER2_SUPPORT)
   7490             if (SOC_IS_SABER2(unit) && soc_sb2_5626x_devtype(unit) &&
   7491                     (recovered_ver <= BCM_WB_VERSION_1_4) &&
   7492                     (default_ver > BCM_WB_VERSION_1_4)) {
   7493                 for (tid = TRUNK_CNTL(unit).ngroups_fp; tid < fp_ngroups;
   7494                         tid++) {
   7495                     if (soc_feature(unit,
   7496                                 soc_feature_shared_trunk_member_table)) {
   7497                         uint16 num_ports;
   7498                         sal_memcpy(&num_ports, trunk_scache, sizeof(uint8));
   7499                         trunk_scache += sizeof(uint8);
   7500                         if (num_ports > 0) {
   7501                             LOG_ERROR(BSL_LS_BCM_TRUNK, (BSL_META_U(unit,
   7502                                             "ERROR: Maximum trunk supported "
   7503                                             "on 5626x devices are %d \n"
   7504                                             "Please remove Trunk id %d "
   7505                                             "re-sync and update/warm boot\n"),
   7506                                         TRUNK_CNTL(unit).ngroups_fp - 1,
   7507                                         tid));
   7508                             return BCM_E_CONFIG;
   7509                         }
   7510                     }
   7511                 }
   7512             }
   7513 #endif /* BCM_SABER2_SUPPORT */
   7514         } else {
   7515 #if defined(BCM_TRIDENT_SUPPORT)
   7516             if (soc_feature(unit, soc_feature_shared_trunk_member_table)) {
   7517                 additional_scache_size += (TRUNK_CNTL(unit).ngroups_fp * 2 +
   7518                         soc_mem_index_count(unit, TRUNK_MEMBERm) * 3) *
   7519                         sizeof(uint8);
   7520             } else
   7521 #endif /* BCM_TRIDENT_SUPPORT */
   7522 #if defined(BCM_XGS3_SWITCH_SUPPORT)
   7523             {
   7524                 additional_scache_size += (TRUNK_CNTL(unit).ngroups_fp *
   7525                         (1 + 3 * TRUNK_CNTL(unit).nports_fp) * sizeof(uint8));
   7526             }
   7527 #endif /* BCM_XGS3_SWITCH_SUPPORT */
   7528         }
   7529 
   7530         if (recovered_ver >= BCM_WB_VERSION_1_3) {
   7531 #ifdef BCM_TRIDENT_SUPPORT 
   7532             if (soc_feature(unit, soc_feature_hg_dlb) &&
   7533                 !soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) {
   7534                 BCM_IF_ERROR_RETURN(bcm_trident_hg_dlb_scache_recover(unit,
   7535                             &trunk_scache));
   7536             }
   7537 #endif /* BCM_TRIDENT_SUPPORT */
   7538 
   7539 #ifdef BCM_TRIUMPH3_SUPPORT 
   7540             if (soc_feature(unit, soc_feature_lag_dlb) &&
   7541                 !soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) {
   7542                 /* Recover LAG dynamic load balancing info */ 
   7543                 BCM_IF_ERROR_RETURN(bcm_tr3_lag_dlb_scache_recover(unit,
   7544                             &trunk_scache));
   7545             }
   7546 #endif /* BCM_TRIUMPH3_SUPPORT */
   7547 
   7548 #ifdef BCM_TOMAHAWK2_SUPPORT
   7549             if (soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) {
   7550                 /* Recover HGT_LAG dynamic load balancing info */
   7551                 BCM_IF_ERROR_RETURN(bcm_th2_hgt_lag_dlb_scache_recover(unit,
   7552                             &trunk_scache));
   7553             }
   7554 #endif /* BCM_TOMAHAWK2_SUPPORT */
   7555 
   7556         } else {
   7557 #ifdef BCM_TRIDENT_SUPPORT 
   7558             if (soc_feature(unit, soc_feature_hg_dlb)) {
   7559                 int hg_dlb_scache_size;
   7560                 BCM_IF_ERROR_RETURN(bcm_trident_hg_dlb_wb_alloc_size_get(unit,
   7561                             &hg_dlb_scache_size));
   7562                 additional_scache_size += hg_dlb_scache_size;
   7563             }
   7564 #endif /* BCM_TRIDENT_SUPPORT */
   7565 
   7566 #ifdef BCM_TRIUMPH3_SUPPORT 
   7567             if (soc_feature(unit, soc_feature_lag_dlb)) {
   7568                 int lag_dlb_scache_size;
   7569                 BCM_IF_ERROR_RETURN(bcm_tr3_lag_dlb_wb_alloc_size_get(unit,
   7570                             &lag_dlb_scache_size));
   7571                 additional_scache_size += lag_dlb_scache_size;
   7572             }
   7573 #endif /* BCM_TRIUMPH3_SUPPORT */
   7574         }
   7575 
   7576         if (recovered_ver <= BCM_WB_VERSION_1_3) {
   7577 #ifdef BCM_TRIDENT2_SUPPORT
   7578             if (SOC_IS_TRIDENT2(unit)) {
   7579                 additional_scache_size += TRUNK_CNTL(unit).fp_hwf_alloc;
   7580             }
   7581 #endif /* BCM_TRIDENT2_SUPPORT */
   7582         }
   7583 
   7584 #if defined(BCM_TRIDENT_SUPPORT)
   7585         if (soc_feature(unit, soc_feature_shared_trunk_member_table)) {
   7586             if (recovered_ver >= BCM_WB_VERSION_1_6) {
   7587                 /* Recover psc from scache in Level 2 warmboot */
   7588                 for (tid = 0; tid < TRUNK_CNTL(unit).ngroups_fp; tid++) {
   7589                     t_info = &TRUNK_INFO(unit, tid);
   7590                     sal_memcpy(&t_info->psc, trunk_scache, sizeof(int));
   7591                     trunk_scache += sizeof(int);
   7592                 }
   7593             } else {
   7594                 additional_scache_size += (TRUNK_CNTL(unit).ngroups_fp *
   7595                     sizeof(int));
   7596             }
   7597         }
   7598 /*#if defined(BCM_TOMAHAWK3_SUPPORT) Will Revisit why this piece is a problem. */
   7599 #if 0
   7600         else {
   7601                 for (tid = 0; tid < TRUNK_CNTL(unit).ngroups_fp; tid++) {
   7602                     t_info = &TRUNK_INFO(unit, tid);
   7603                     sal_memcpy(&t_info->psc, trunk_scache, sizeof(int));
   7604                     trunk_scache += sizeof(int);
   7605                 }
   7606         }
   7607 #endif
   7608 
   7609 #endif /* BCM_TRIDENT_SUPPORT */
   7610         if (recovered_ver >= BCM_WB_VERSION_1_7) {
   7611             for (tid = 0; tid < TRUNK_CNTL(unit).ngroups_fp; tid++) {
   7612 
   7613                 t_info = &TRUNK_INFO(unit, tid);
   7614                 sal_memcpy(&recovered_dlf_index, trunk_scache,
   7615                                sizeof(int));
   7616                 trunk_scache += sizeof(int);
   7617 
   7618                 t_info->dlf_index_spec = recovered_dlf_index;
   7619                 t_info->dlf_index_used = recovered_dlf_index;
   7620                 t_info->mc_index_spec = recovered_dlf_index;
   7621                 t_info->mc_index_used = recovered_dlf_index;
   7622                 t_info->ipmc_index_spec = recovered_dlf_index;
   7623                 t_info->ipmc_index_used = recovered_dlf_index;
   7624             }
   7625         } else {
   7626             additional_scache_size += (TRUNK_CNTL(unit).ngroups_fp *
   7627                                              sizeof(int));
   7628         }
   7629 
   7630 #if defined(BCM_TRIDENT_SUPPORT)
   7631         if (soc_feature(unit, soc_feature_shared_trunk_member_table)) {
   7632             if (recovered_ver >= BCM_WB_VERSION_1_8) {
   7633                 sal_memcpy(&bcm_trident_trunk_mbr_zero_rsvd[unit],
   7634                            trunk_scache,
   7635                            sizeof(int));
   7636             } else {
   7637                 additional_scache_size += (sizeof(int));
   7638             }
   7639         }
   7640 #endif /* BCM_TRIDENT_SUPPORT */
   7641 
   7642         if (additional_scache_size > 0) {
   7643             SOC_IF_ERROR_RETURN
   7644                 (soc_scache_realloc(unit, scache_handle,
   7645                                     additional_scache_size));
   7646         }
   7647 
   7648         /* To add new state:
   7649          * if (recovered_ver >= BCM_WB_VERSION_1_x) {
   7650          *     Recover state for ver 1_x 
   7651          * } else {
   7652          *     Re-alloc scache for 'sync' operation for ver 1_x state. 
   7653          * }
   7654          */
   7655     }
   7656 
   7657     if (SOC_IS_XGS12_FABRIC(unit)) {
   7658 #ifdef BCM_XGS12_FABRIC_SUPPORT
   7659         bcm_pbmp_t tports;
   7660         bcm_port_t port;
   7661         bcm_trunk_info_t *t_data, td;        
   7662         int member_count;
   7663         uint32 val;
   7664   	         
   7665         for (tid = 0; tid < TRUNK_CNTL(unit).ngroups_hg; tid++) {
   7666             PBMP_HG_ITER(unit, port) {
   7667                 SOC_IF_ERROR_RETURN(READ_ING_HGTRUNKr(unit, port, tid, &val));
   7668                 break;
   7669             }
   7670   	             
   7671             SOC_PBMP_CLEAR(tports);
   7672             SOC_PBMP_WORD_SET(tports, 0,
   7673                               soc_reg_field_get(unit, ING_HGTRUNKr, val, BMAPf));
   7674             SOC_PBMP_COUNT(tports, member_count);
   7675             if (0 == member_count) {
   7676                 /*
   7677                  * Nothing to update for this TID
   7678                  */
   7679                 continue;
   7680             }
   7681   	             
   7682             sal_memset(&td, 0, sizeof(bcm_trunk_info_t));
   7683             t_data = &td;
   7684   	             
   7685             switch(soc_reg_field_get(unit, ING_HGTRUNKr, val, ALGORITHMf)) {
   7686             case 0:
   7687                 t_data->psc = BCM_TRUNK_PSC_SRCDSTMAC;
   7688   	                 
   7689                 if (soc_reg_field_get(unit, ING_HGTRUNKr, val, EN_IPMACSAf)) {
   7690                     t_data->psc |= BCM_TRUNK_PSC_IPMACSA;
   7691                 }
   7692                 if (soc_reg_field_get(unit, ING_HGTRUNKr, val, EN_IPMACDAf)) {
   7693                     t_data->psc |= BCM_TRUNK_PSC_IPMACDA;
   7694                 }
   7695                 if (soc_reg_field_get(unit, ING_HGTRUNKr, val, EN_IPTYPEf)) {
   7696                     t_data->psc |= BCM_TRUNK_PSC_IPTYPE;
   7697                 }
   7698                 if (soc_reg_field_get(unit, ING_HGTRUNKr, val, EN_IPVIDf)) {
   7699                     t_data->psc |= BCM_TRUNK_PSC_IPVID;
   7700                 }
   7701                 if (soc_reg_field_get(unit, ING_HGTRUNKr, val, EN_IPSAf)) {
   7702                     t_data->psc |= BCM_TRUNK_PSC_IPSA;
   7703                 }
   7704                 if (soc_reg_field_get(unit, ING_HGTRUNKr, val, EN_IPDAf)) {
   7705                     t_data->psc |= BCM_TRUNK_PSC_IPDA;
   7706                 }
   7707                 if (soc_reg_field_get(unit, ING_HGTRUNKr, val, EN_L4SSf)) {
   7708                     t_data->psc |= BCM_TRUNK_PSC_L4SS;
   7709                 }
   7710                 if (soc_reg_field_get(unit, ING_HGTRUNKr, val, EN_L4DSf)) {
   7711                     t_data->psc |= BCM_TRUNK_PSC_L4DS;
   7712                 }
   7713                 if (soc_reg_field_get(unit, ING_HGTRUNKr, val, EN_MACDAf)) {
   7714                     t_data->psc |= BCM_TRUNK_PSC_MACDA;
   7715                 }
   7716                 if (soc_reg_field_get(unit, ING_HGTRUNKr, val, EN_MACSAf)) {
   7717                     t_data->psc |= BCM_TRUNK_PSC_MACSA;
   7718                 }
   7719                 if (soc_reg_field_get(unit, ING_HGTRUNKr, val, EN_TYPEf)) {
   7720                     t_data->psc |= BCM_TRUNK_PSC_TYPE;
   7721                 }
   7722                 if (soc_reg_field_get(unit, ING_HGTRUNKr, val, EN_VIDf)) {
   7723                     t_data->psc |= BCM_TRUNK_PSC_VID;
   7724                 }
   7725                 break;
   7726             case 1:
   7727                 t_data->psc = BCM_TRUNK_PSC_REDUNDANT;
   7728                 break;
   7729             default:
   7730                 t_data->psc = -1;
   7731                 break;
   7732             }
   7733   	             
   7734             t_data->dlf_index = -1;
   7735             t_data->mc_index = -1;
   7736             t_data->ipmc_index = -1;
   7737   	             
   7738             /*
   7739              * Fill in t_info struct for this tid
   7740              */
   7741             t_info = &TRUNK_INFO(unit, tid);
   7742   	             
   7743             /*
   7744              * Check number of ports in trunk group
   7745              */
   7746             if (member_count < 1 ||
   7747                 (TRUNK_FP_TID(unit, tid) &&
   7748                  (member_count > TRUNK_CNTL(unit).nports_fp)) ||
   7749                 (TRUNK_FABRIC_TID(unit, tid) &&
   7750                  (member_count > TRUNK_CNTL(unit).nports_hg))) {
   7751                 return (BCM_E_PARAM);
   7752             }
   7753   	             
   7754             TRUNK_LOCK(unit);
   7755             t_info->tid = tid;
   7756             t_info->psc = t_data->psc;
   7757             t_info->in_use = TRUE;
   7758             TRUNK_UNLOCK(unit);
   7759         }
   7760 #endif /* BCM_XGS12_FABRIC_SUPPORT */
   7761     } else if (SOC_IS_XGS3_FABRIC(unit)) {
   7762 #ifdef BCM_XGS3_FABRIC_SUPPORT
   7763         /*
   7764          * recover software state for fabric trunks
   7765          */
   7766         BCM_IF_ERROR_RETURN(_bcm_trunk_fabric_reinit(unit));
   7767 #endif /* BCM_XGS3_FABRIC_SUPPORT */
   7768     }
   7769 
   7770 #ifdef BCM_XGS_SWITCH_SUPPORT
   7771     if (SOC_IS_XGS3_SWITCH(unit)) {
   7772         if (SOC_IS_FBX(unit)) { 
   7773             /*
   7774              * recover software state for fabric trunks
   7775              */
   7776             BCM_IF_ERROR_RETURN(_bcm_trunk_fabric_reinit(unit));
   7777 
   7778             /*
   7779              * recover software state for ether trunks
   7780              */
   7781             BCM_IF_ERROR_RETURN(_bcm_trunk_lag_reinit(unit));
   7782         }
   7783     }
   7784 #endif
   7785 
   7786  #ifdef BCM_APACHE_SUPPORT
   7787     if (soc_feature(unit, soc_feature_apache_round_robin_fp_lag)) {
   7788         int tid;
   7789         for (tid = 0; tid < TRUNK_CNTL(unit).ngroups_fp; tid++) {
   7790             if (TRUNK_CNTL(unit).t_info[tid].rr_lag_select != -1) {
   7791                 SHR_BITSET(TRUNK_CNTL(unit).fp_rr_lag_bmp,
   7792                            TRUNK_CNTL(unit).t_info[tid].rr_lag_select);
   7793             }
   7794         }
   7795     }
   7796 #endif /* BCM_APACHE_SUPPORT */
   7797 
   7798     return BCM_E_NONE;
   7799 }
   7800 
   7801 /*
   7802  * Function:
   7803  *      _bcm_esw_trunk_sync
   7804  * Purpose:
   7805  *      Record Trunk module persisitent info for Level 2 Warm Boot
   7806  * Parameters:
   7807  *      unit - StrataSwitch unit number.
   7808  * Returns:
   7809  *      BCM_E_XXX
   7810  */
   7811 
   7812 int
   7813 _bcm_esw_trunk_sync(int unit)
   7814 {
   7815     bcm_trunk_t tid;
   7816     trunk_private_t *t_info;
   7817     soc_scache_handle_t scache_handle;
   7818     uint8               *trunk_scache;
   7819     uint32              ngroups;
   7820     uint8               flags;
   7821 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT)
   7822     bcm_trunk_t         hgtid;
   7823     int                 tix, idx;
   7824 #endif /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */
   7825 
   7826     if (SOC_IS_XGS12_FABRIC(unit)) {
   7827         return BCM_E_NONE;
   7828     }
   7829 
   7830     TRUNK_INIT(unit);
   7831 
   7832     /* Limited scache mode unsupported */
   7833     if (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit)) {
   7834         return BCM_E_NONE;
   7835     }
   7836 
   7837     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_TRUNK, 0);
   7838     BCM_IF_ERROR_RETURN
   7839         (_bcm_esw_scache_ptr_get(unit, scache_handle, FALSE,
   7840                                  0,
   7841                                  &trunk_scache, BCM_WB_DEFAULT_VERSION, NULL));
   7842 
   7843     ngroups = TRUNK_CNTL(unit).ngroups_fp;
   7844     sal_memcpy(trunk_scache, &ngroups, sizeof(ngroups));
   7845     trunk_scache += sizeof(ngroups);
   7846         
   7847     ngroups = TRUNK_CNTL(unit).ngroups_hg;
   7848     sal_memcpy(trunk_scache, &ngroups, sizeof(ngroups));
   7849     if (ngroups != TRUNK_CNTL(unit).ngroups_hg) {
   7850         return BCM_E_CONFIG;
   7851     }
   7852     trunk_scache += sizeof(ngroups);
   7853 
   7854     sal_memset(TRUNK_CNTL(unit).trunk_bmp_ptr, 0,
   7855                TRUNK_CNTL(unit).trunk_bmp_alloc);
   7856 
   7857     for (tid = 0; tid < TRUNK_NUM_GROUPS(unit); tid++) {
   7858         t_info = &TRUNK_INFO(unit, tid);
   7859         if (BCM_TRUNK_INVALID != t_info->tid) {
   7860             SHR_BITSET(TRUNK_CNTL(unit).trunk_bmp_ptr, tid);
   7861         }
   7862         t_info++;
   7863     }
   7864     sal_memcpy(trunk_scache, TRUNK_CNTL(unit).trunk_bmp_ptr,
   7865                TRUNK_CNTL(unit).trunk_bmp_alloc);
   7866     trunk_scache += TRUNK_CNTL(unit).trunk_bmp_alloc;
   7867 
   7868 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT)
   7869     if (TRUNK_CNTL(unit).fp_hwf_alloc) {
   7870         idx = 0;
   7871 
   7872         if (soc_feature(unit, soc_feature_port_lag_failover)) {
   7873             /* FP trunk failover flags */
   7874             for (tid = 0; tid < TRUNK_CNTL(unit).ngroups_fp; tid++) {
   7875                 TRUNK_CNTL(unit).fp_hwf_flags[idx++] =
   7876                     TRUNK_INFO(unit, tid).flags;
   7877 #if defined(BCM_TRIDENT_SUPPORT)
   7878                 if (soc_feature(unit, soc_feature_shared_trunk_member_table)) {
   7879                     uint16 num_ports; 
   7880                     num_ports = _bcm_trident_hw_failover_num_ports_get(unit, tid, FALSE);
   7881                     /* Max number of ports per front-panel trunk group is 256,
   7882                      * requiring two bytes of storage. */
   7883                     TRUNK_CNTL(unit).fp_hwf_flags[idx++] = num_ports >> 8;
   7884                     TRUNK_CNTL(unit).fp_hwf_flags[idx++] = num_ports & 0xff;
   7885                     for (tix = 0; tix < num_ports; tix++) {
   7886                         TRUNK_CNTL(unit).fp_hwf_flags[idx++] = 
   7887                             _bcm_trident_hw_failover_flags_get(unit, tid,
   7888                                     tix, FALSE);
   7889                     }
   7890                 } else
   7891 #if defined(BCM_TOMAHAWK3_SUPPORT)
   7892                 if (SOC_IS_TOMAHAWK3(unit)) {
   7893                     int fail_to_ports, fpid;
   7894                     fail_to_ports = _bcm_th3_trunk_hwfailover_num_ports_get(unit, tid);
   7895                     TRUNK_CNTL(unit).fp_hwf_flags[idx++] = fail_to_ports >> 8;
   7896                     TRUNK_CNTL(unit).fp_hwf_flags[idx++] = fail_to_ports & 0xff;
   7897                     for (fpid = 0; fpid < fail_to_ports; fpid++) {
   7898                         TRUNK_CNTL(unit).fp_hwf_flags[idx++] = 
   7899                                _bcm_th3_trunk_hwfailover_flags_get(unit, tid, fpid);
   7900                     }
   7901                 } else
   7902 #endif
   7903 #endif /* BCM_TRIDENT_SUPPORT */
   7904                 {
   7905                     for (tix = 0; tix < TRUNK_CNTL(unit).nports_fp; tix++) {
   7906                         TRUNK_CNTL(unit).fp_hwf_flags[idx++] = 
   7907                             _bcm_xgs3_hw_failover_flags_get(unit, tid,
   7908                                     tix, FALSE);
   7909                     }
   7910                 }
   7911             } /* tid */
   7912         } /* lag failover */
   7913         sal_memcpy(trunk_scache, TRUNK_CNTL(unit).fp_hwf_flags,
   7914                    TRUNK_CNTL(unit).fp_hwf_alloc);
   7915         trunk_scache += TRUNK_CNTL(unit).fp_hwf_alloc;
   7916     }
   7917     if (TRUNK_CNTL(unit).hg_hwf_alloc) {
   7918 
   7919         if (soc_feature(unit, soc_feature_hg_trunk_failover)) {
   7920             idx = 0;
   7921             /* HG trunk failover flags */
   7922             for (tid = TRUNK_CNTL(unit).ngroups_fp;
   7923                     tid < TRUNK_NUM_GROUPS(unit); tid++) {
   7924                 TRUNK_CNTL(unit).hg_hwf_flags[idx++] =
   7925                     TRUNK_INFO(unit, tid).flags;
   7926                 hgtid = tid - TRUNK_CNTL(unit).ngroups_fp;
   7927 #if defined(BCM_TRIDENT_SUPPORT)
   7928                 if (soc_feature(unit, soc_feature_shared_trunk_member_table)) {
   7929                     uint16 num_ports; 
   7930                     num_ports = _bcm_trident_hw_failover_num_ports_get(unit, hgtid, TRUE);
   7931                     /* Max number of ports per front-panel trunk group is 32,
   7932                      * requiring one byte of storage. */
   7933                     TRUNK_CNTL(unit).hg_hwf_flags[idx++] = num_ports;
   7934                     for (tix = 0; tix < num_ports; tix++) {
   7935                         TRUNK_CNTL(unit).hg_hwf_flags[idx++] = 
   7936                             _bcm_trident_hw_failover_flags_get(unit, hgtid,
   7937                                     tix, TRUE);
   7938                     }
   7939                 } else
   7940 #endif /* BCM_TRIDENT_SUPPORT */
   7941                 {
   7942                     for (tix = 0; tix < TRUNK_CNTL(unit).nports_hg; tix++) { 
   7943                         TRUNK_CNTL(unit).hg_hwf_flags[idx++] =  
   7944                             _bcm_xgs3_hw_failover_flags_get(unit, hgtid,
   7945                                     tix, TRUE);
   7946                     }
   7947                 }
   7948             }
   7949         }
   7950         sal_memcpy(trunk_scache, TRUNK_CNTL(unit).hg_hwf_flags,
   7951                    TRUNK_CNTL(unit).hg_hwf_alloc);
   7952         trunk_scache += TRUNK_CNTL(unit).hg_hwf_alloc;
   7953     }
   7954 #endif /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */
   7955 
   7956     /* Store BCM_TRUNK_FLAG_IPMC_CLEAVE flag */
   7957     for (tid = 0; tid < TRUNK_CNTL(unit).ngroups_fp; tid++) {
   7958         t_info = &TRUNK_INFO(unit, tid);
   7959         if (t_info->flags & BCM_TRUNK_FLAG_IPMC_CLEAVE) {
   7960             flags = 0x1;
   7961         } else {
   7962             flags = 0x0;
   7963         }
   7964         sal_memcpy(trunk_scache, &flags, sizeof(uint8));
   7965         trunk_scache += sizeof(uint8);
   7966     }
   7967 
   7968     /* Store ipmc_psc */
   7969     for (tid = 0; tid < TRUNK_CNTL(unit).ngroups_fp; tid++) {
   7970         t_info = &TRUNK_INFO(unit, tid);
   7971         sal_memcpy(trunk_scache, &t_info->ipmc_psc, sizeof(int));
   7972         trunk_scache += sizeof(int);
   7973     }
   7974 
   7975     /* Store front-panel trunk membership info */
   7976     for (tid = 0; tid < TRUNK_CNTL(unit).ngroups_fp; tid++) {
   7977 #if defined(BCM_TRIDENT_SUPPORT)
   7978         if (soc_feature(unit, soc_feature_shared_trunk_member_table)) {
   7979             uint16 num_ports;
   7980             uint16 *modport;
   7981             uint32 *member_flags;
   7982             uint8  truncated_flags;
   7983             int rv, i;
   7984 
   7985             BCM_IF_ERROR_RETURN(_bcm_trident_trunk_member_info_get(unit, tid,
   7986                         0, NULL, NULL, &num_ports));
   7987             modport = sal_alloc(sizeof(uint16) * num_ports, "modport");
   7988             if (NULL == modport) {
   7989                 return BCM_E_MEMORY;
   7990             }
   7991             member_flags = sal_alloc(sizeof(uint32) * num_ports,
   7992                     "member_flags");
   7993             if (NULL == member_flags) {
   7994                 sal_free(modport);
   7995                 return BCM_E_MEMORY;
   7996             }
   7997             rv = _bcm_trident_trunk_member_info_get(unit, tid,
   7998                         num_ports, modport, member_flags, &num_ports);
   7999             if (BCM_FAILURE(rv)) {
   8000                 sal_free(modport);
   8001                 sal_free(member_flags);
   8002                 return rv;
   8003             }
   8004 
   8005             sal_memcpy(trunk_scache, &num_ports, sizeof(uint16));
   8006             trunk_scache += sizeof(uint16);
   8007             for (i = 0; i < num_ports; i++) {
   8008                 sal_memcpy(trunk_scache, &modport[i], sizeof(uint16));
   8009                 trunk_scache += sizeof(uint16);
   8010 
   8011                 /* Truncate the flags to 1 byte, as there are only 8 flags */
   8012                 truncated_flags = member_flags[i] & 0xff;
   8013                 sal_memcpy(trunk_scache, &truncated_flags, sizeof(uint8));
   8014                 trunk_scache += sizeof(uint8);
   8015             }
   8016 
   8017             sal_free(modport);
   8018             sal_free(member_flags);
   8019         } else
   8020 #endif /* BCM_TRIDENT_SUPPORT */
   8021 #if defined(BCM_TOMAHAWK3_SUPPORT)
   8022         if (SOC_IS_TOMAHAWK3(unit)) {
   8023             _esw_trunk_add_info_t *t_data;
   8024             uint16 num_ports;
   8025             uint8 port;
   8026             uint8 mflags;
   8027             int rv, i;
   8028 
   8029             t_info = &TRUNK_INFO(unit, tid);
   8030             t_data = sal_alloc(sizeof(_esw_trunk_add_info_t), "trunk_add_info");
   8031             if (t_data == NULL) {
   8032                 return BCM_E_MEMORY;
   8033             }
   8034             sal_memset(t_data, 0, sizeof(_esw_trunk_add_info_t));
   8035 
   8036             /* first obtain the number of member ports */
   8037 
   8038             rv = _bcm_th3_trunk_member_info_get(unit, tid, t_data, t_info);
   8039             if (BCM_FAILURE(rv)) {
   8040 	        sal_free(t_data);
   8041                 return rv;
   8042             }
   8043             num_ports = t_data->num_ports;
   8044             sal_memcpy(trunk_scache, &num_ports, sizeof(uint16));
   8045             trunk_scache += sizeof(uint16);
   8046             if (t_data->num_ports != 0) {
   8047                 /* Then obtain the member ports info */
   8048                 rv = _bcm_th3_trunk_member_info_get(unit, tid, t_data, t_info);
   8049                 if (BCM_FAILURE(rv)) {
   8050 	            sal_free(t_data);
   8051                     return rv;
   8052                 }
   8053                 for (i = 0; i < num_ports; i++) {
   8054                     /* Module is 0 for TH3 */
   8055                     port = t_data->tp[i];
   8056                     sal_memcpy(trunk_scache, &port, sizeof(uint8));
   8057                     trunk_scache += sizeof(uint8);
   8058         
   8059                     /* Truncate the flags to 1 byte, as there are only 8 flags */
   8060                     mflags = t_data->member_flags[i];
   8061                     sal_memcpy(trunk_scache, &mflags, sizeof(mflags));
   8062                     trunk_scache += sizeof(uint8);
   8063                 }
   8064 	        sal_free(t_data->tp);
   8065 	        sal_free(t_data->tm);
   8066 	        sal_free(t_data->member_flags);
   8067 	        sal_free(t_data->dynamic_scaling_factor);
   8068 	        sal_free(t_data->dynamic_load_weight);
   8069 	        sal_free(t_data->dynamic_queue_size_weight);
   8070             } /* if num_ports */
   8071 	    sal_free(t_data);
   8072 
   8073         } else
   8074 #endif /* BCM_TOMAHAWK3_SUPPORT */
   8075 #ifdef BCM_XGS3_SWITCH_SUPPORT
   8076         {
   8077             uint8  num_ports;
   8078             uint16 modport[BCM_XGS3_TRUNK_MAX_PORTCNT];
   8079             uint32 member_flags[BCM_XGS3_TRUNK_MAX_PORTCNT];
   8080             uint8  truncated_flags;
   8081             int i;
   8082 
   8083             _bcm_xgs3_trunk_member_info_get(unit, tid, &num_ports,
   8084                     modport, member_flags);
   8085             sal_memcpy(trunk_scache, &num_ports, sizeof(uint8));
   8086             trunk_scache += sizeof(uint8);
   8087             for (i = 0; i < num_ports; i++) {
   8088                 sal_memcpy(trunk_scache, &modport[i], sizeof(uint16));
   8089                 trunk_scache += sizeof(uint16);
   8090 
   8091                 /* Truncate the flags to 1 byte, as there are only 4 flags */
   8092                 truncated_flags = member_flags[i] & 0xff;
   8093                 sal_memcpy(trunk_scache, &truncated_flags, sizeof(uint8));
   8094                 trunk_scache += sizeof(uint8);
   8095             }
   8096         }
   8097 #endif /* BCM_XGS3_SWITCH_SUPPORT */
   8098     }
   8099     /* Store Higig dynamic load balancing info */
   8100 #ifdef BCM_TRIDENT_SUPPORT
   8101     if (soc_feature(unit, soc_feature_hg_dlb) &&
   8102         !soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) {
   8103         BCM_IF_ERROR_RETURN(bcm_trident_hg_dlb_sync(unit, &trunk_scache));
   8104     }
   8105 #endif /* BCM_TRIDENT_SUPPORT */
   8106 
   8107     /* Store LAG dynamic load balancing info */
   8108 #ifdef BCM_TRIUMPH3_SUPPORT
   8109     if (soc_feature(unit, soc_feature_lag_dlb) &&
   8110         !soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) {
   8111         BCM_IF_ERROR_RETURN(bcm_tr3_lag_dlb_sync(unit, &trunk_scache));
   8112     }
   8113 #endif /* BCM_TRIUMPH3_SUPPORT */
   8114 
   8115 #ifdef BCM_TOMAHAWK2_SUPPORT
   8116     if (soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) {
   8117         BCM_IF_ERROR_RETURN(bcm_th2_hgt_lag_dlb_sync(unit, &trunk_scache));
   8118     }
   8119 #endif /* BCM_TOMAHAWK2_SUPPORT */
   8120 
   8121     /* Store front-panel trunk psc info */
   8122 #if defined(BCM_TRIDENT_SUPPORT)
   8123     if (soc_feature(unit, soc_feature_shared_trunk_member_table)) {
   8124         for (tid = 0; tid < TRUNK_CNTL(unit).ngroups_fp; tid++) {
   8125             t_info = &TRUNK_INFO(unit, tid);
   8126             sal_memcpy(trunk_scache, &t_info->psc, sizeof(int));
   8127             trunk_scache += sizeof(int);
   8128         }
   8129     }
   8130 /*#if defined(BCM_TOMAHAWK3_SUPPORT) Will Revisit why this piece is a problem. */
   8131 #if 0
   8132     else {
   8133         for (tid = 0; tid < TRUNK_CNTL(unit).ngroups_fp; tid++) {
   8134             t_info = &TRUNK_INFO(unit, tid);
   8135             sal_memcpy(trunk_scache, &t_info->psc, sizeof(int));
   8136             trunk_scache += sizeof(int);
   8137         }
   8138     }
   8139 #endif
   8140 #endif /* BCM_TRIDENT_SUPPORT */
   8141 
   8142     /* Store dlf_index */
   8143     for (tid = 0; tid < TRUNK_CNTL(unit).ngroups_fp; tid++) {
   8144         t_info = &TRUNK_INFO(unit, tid);
   8145         sal_memcpy(trunk_scache, &t_info->dlf_index_used, sizeof(int));
   8146         trunk_scache += sizeof(int);
   8147     }
   8148 
   8149     /* Store bcm_trident_trunk_mbr_zero_rsvd info. */
   8150 #if defined(BCM_TRIDENT_SUPPORT)
   8151     if (soc_feature(unit, soc_feature_shared_trunk_member_table)) {
   8152         sal_memcpy(trunk_scache, &bcm_trident_trunk_mbr_zero_rsvd[unit], sizeof(int));
   8153         trunk_scache += sizeof(int);
   8154     }
   8155 #endif /* BCM_TRIDENT_SUPPORT */
   8156 
   8157     return BCM_E_NONE;
   8158 }
   8159 #endif /* BCM_WARM_BOOT_SUPPORT */
   8160   	 
   8161 #ifndef BCM_SW_STATE_DUMP_DISABLE
   8162 /*
   8163  * Function:
   8164  *     _bcm_trunk_sw_dump
   8165  * Purpose:
   8166  *     Displays trunk information maintained by software.
   8167  * Parameters:
   8168  *     unit - Device unit number
   8169  * Returns:
   8170  *     None
   8171  */
   8172 void
   8173 _bcm_trunk_sw_dump(int unit)
   8174 {
   8175     trunk_cntl_t    *t_cntl;
   8176     trunk_private_t *t_info;
   8177     int             i;
   8178     int             print_trunk_info;
   8179 
   8180     t_cntl = &TRUNK_CNTL(unit);
   8181     LOG_CLI((BSL_META_U(unit,
   8182                         "\nSW Information TRUNK - Unit %d\n"), unit));
   8183     LOG_CLI((BSL_META_U(unit,
   8184                         "  Front  panel trunk groups    : %d\n"), t_cntl->ngroups_fp));
   8185     LOG_CLI((BSL_META_U(unit,
   8186                         "  Front  panel trunk max ports : %d\n"), t_cntl->nports_fp));
   8187     LOG_CLI((BSL_META_U(unit,
   8188                         "  Fabric panel trunk groups    : %d\n"), t_cntl->ngroups_hg));
   8189     LOG_CLI((BSL_META_U(unit,
   8190                         "  Fabric panel trunk max ports : %d\n"), t_cntl->nports_hg));
   8191 
   8192     print_trunk_info = TRUE;
   8193     for (i = 0; i < TRUNK_NUM_GROUPS(unit); i++) {
   8194         t_info = &TRUNK_INFO(unit, i);
   8195 #if defined(BCM_TRIDENT_SUPPORT)
   8196         if (TRUNK_CNTL(unit).ngroups_fp > 128) {
   8197             /* Trident has 1024 front panel trunk groups.
   8198              * Print only the ones that are in use. 
   8199              */
   8200             print_trunk_info = t_info->tid != BCM_TRUNK_INVALID;
   8201         } 
   8202 #endif /* BCM_TRIDENT_SUPPORT */
   8203         if (print_trunk_info) {
   8204             LOG_CLI((BSL_META_U(unit,
   8205                                 "  Trunk %d\n"), i));
   8206             LOG_CLI((BSL_META_U(unit,
   8207                                 "      ID              : %d\n"), t_info->tid));
   8208             LOG_CLI((BSL_META_U(unit,
   8209                                 "      in use          : %d\n"), t_info->in_use));
   8210             LOG_CLI((BSL_META_U(unit,
   8211                                 "      psc             : 0x%x\n"), t_info->psc));
   8212             LOG_CLI((BSL_META_U(unit,
   8213                                 "      ipmc_psc        : 0x%x\n"), t_info->ipmc_psc));
   8214             LOG_CLI((BSL_META_U(unit,
   8215                                 "      rtag            : 0x%x\n"), t_info->rtag));
   8216             LOG_CLI((BSL_META_U(unit,
   8217                                 "      flags           : 0x%x\n"), t_info->flags));
   8218             if (soc_feature(unit, soc_feature_hg_dlb) ||
   8219                 soc_feature(unit, soc_feature_lag_dlb)) {
   8220                 LOG_CLI((BSL_META_U(unit,
   8221                                     "      dynamic_size    : 0x%x\n"), t_info->dynamic_size));
   8222                 LOG_CLI((BSL_META_U(unit,
   8223                                     "      dynamic_age     : 0x%x\n"), t_info->dynamic_age));
   8224             }
   8225             if (!SOC_IS_XGS3_SWITCH(unit)) {
   8226                 /* Unused for XGS3 devices */
   8227                 LOG_CLI((BSL_META_U(unit,
   8228                                     "      dlf index spec  : %d\n"),
   8229                          t_info->dlf_index_spec));
   8230                 LOG_CLI((BSL_META_U(unit,
   8231                                     "      dlf index used  : %d\n"),
   8232                          t_info->dlf_index_used));
   8233                 LOG_CLI((BSL_META_U(unit,
   8234                                     "      dlf port used   : %d\n"), 
   8235                          t_info->dlf_port_used));
   8236                 LOG_CLI((BSL_META_U(unit,
   8237                                     "      mc index spec   : %d\n"),
   8238                          t_info->mc_index_spec));
   8239                 LOG_CLI((BSL_META_U(unit,
   8240                                     "      mc index used   : %d\n"),
   8241                          t_info->mc_index_used));
   8242                 LOG_CLI((BSL_META_U(unit,
   8243                                     "      mc port used    : %d\n"),
   8244                          t_info->mc_port_used));
   8245                 LOG_CLI((BSL_META_U(unit,
   8246                                     "      ipmc index spec : %d\n"),
   8247                          t_info->ipmc_index_spec));
   8248                 LOG_CLI((BSL_META_U(unit,
   8249                                     "      ipmc index used : %d\n"),
   8250                          t_info->ipmc_index_used));
   8251                 LOG_CLI((BSL_META_U(unit,
   8252                                     "      ipmc port used  : %d\n"),
   8253                          t_info->ipmc_port_used));
   8254             }
   8255         }
   8256     }
   8257 
   8258 #if defined(BCM_TRIDENT_SUPPORT)
   8259     if (soc_feature(unit, soc_feature_shared_trunk_member_table)) {
   8260         _bcm_trident_trunk_sw_dump(unit);
   8261     } else 
   8262 #endif /* BCM_TRIDENT_SUPPORT */
   8263 #if defined(BCM_XGS3_SWITCH_SUPPORT)
   8264         if (SOC_IS_FBX(unit) && !SOC_IS_RAPTOR(unit)) {
   8265             _bcm_xgs3_trunk_sw_dump(unit);
   8266         }
   8267 #endif /* BCM_XGS3_SWITCH_SUPPORT */
   8268 
   8269 #if defined(BCM_TRIDENT2_SUPPORT) && defined(INCLUDE_L3)
   8270     if (soc_feature(unit, soc_feature_vp_lag)) {
   8271         bcm_td2_vp_lag_sw_dump(unit);
   8272     }
   8273 #endif /* BCM_TRIDENT2_SUPPORT && INCLUDE_L3 */
   8274 
   8275     return;
   8276 }
   8277 #endif /* BCM_SW_STATE_DUMP_DISABLE */
   8278 
   8279 /*
   8280  * Function:
   8281  *     _bcm_esw_trunk_tgid_extended_mem_get
   8282  * Purpose:
   8283  *     Called by the macro TRUNK_CHK_TGID_EXTENDED to fetch the memory
   8284  *     that will be used to determine the number of trunk group IDs
   8285  * Parameters:
   8286  *     unit - Device unit number
   8287  * Returns:
   8288  *     The memory used to determine the number of trunk group IDs
   8289  */
   8290 soc_mem_t
   8291 _bcm_esw_trunk_tgid_extended_mem_get(int unit)
   8292 {
   8293     soc_mem_t ret = TRUNK_GROUPm;
   8294 
   8295     if (soc_feature(unit, soc_feature_fastlag)) {
   8296         ret = FAST_TRUNK_GROUPm;
   8297 
   8298 #ifdef BCM_TOMAHAWK3_SUPPORT
   8299         if (SOC_IS_TOMAHAWK3(unit)) {
   8300             ret = FAST_TRUNK_SIZEm;
   8301         }
   8302 #endif
   8303     }
   8304 
   8305     return ret;
   8306 }
   8307 
   8308 /*
   8309  * Function:
   8310  *      _bcm_esw_trunk_lock
   8311  * Purpose:
   8312  *     Lock Trunk module - if module was not initialized NOOP
   8313  *    
   8314  * Parameters:
   8315  *      unit - (IN) Unit number.
   8316  * Returns:
   8317  *      BCM_E_XXX
   8318  * Notes:
   8319  */
   8320 int 
   8321 _bcm_esw_trunk_lock(int unit)
   8322 {
   8323     if (NULL != TRUNK_CNTL(unit).lock) {
   8324         return sal_mutex_take(TRUNK_CNTL(unit).lock, 
   8325                               sal_mutex_FOREVER);
   8326     }
   8327     return (BCM_E_NONE);
   8328 }
   8329 /*
   8330  * Function:
   8331  *      _bcm_esw_trunk_unlock
   8332  * Purpose:
   8333  *     Unlock Trunk module - if module was not initialized NOOP
   8334  *    
   8335  * Parameters:
   8336  *      unit - (IN) Unit number.
   8337  * Returns:
   8338  *      BCM_E_XXX
   8339  * Notes:
   8340  */
   8341 int 
   8342 _bcm_esw_trunk_unlock(int unit)
   8343 {
   8344     if (NULL != TRUNK_CNTL(unit).lock) {
   8345         return sal_mutex_give(TRUNK_CNTL(unit).lock);
   8346     }
   8347     return (BCM_E_NONE);
   8348 }
   8349 
   8350 int
   8351 _bcm_esw_trunk_group_num(int unit)
   8352 {
   8353 
   8354 #if defined(BCM_TRIDENT2_SUPPORT) && defined(INCLUDE_L3)
   8355         if (soc_feature(unit, soc_feature_vp_lag)) {
   8356             return TRUNK_NUM_GROUPS(unit) + _bcm_esw_num_vp_trunk_groups(unit);
   8357         }
   8358 #endif /* BCM_TRIDENT2_SUPPORT && INCLUDE_L3 */
   8359 
   8360         return TRUNK_NUM_GROUPS(unit);
   8361 }