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


      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  * Trident Front Panel and Higig Trunking
      8  */
      9 
     10 #include <soc/defs.h>
     11 #include <sal/core/libc.h>
     12 #include <shared/bsl.h>
     13 #ifdef BCM_TRIDENT_SUPPORT 
     14 
     15 #include <soc/mem.h>
     16 #include <soc/profile_mem.h>
     17 #include <soc/bradley.h>
     18 #include <sal/appl/sal.h>
     19 
     20 #if defined BCM_METROLITE_SUPPORT
     21 #include <soc/katana2.h>
     22 #endif
     23 #include <bcm/error.h>
     24 
     25 #include <bcm_int/esw/mbcm.h>
     26 #include <bcm_int/esw/link.h>   /* LAG failover support */
     27 #include <bcm_int/esw_dispatch.h>
     28 #include <bcm_int/esw/switch.h>
     29 #include <bcm_int/esw/stack.h>
     30 #include <bcm_int/esw/trunk.h>
     31 #include <bcm_int/esw/trident.h>
     32 #include <bcm_int/esw/triumph3.h>
     33 #include <bcm_int/esw/trident2.h>
     34 #include <bcm_int/esw/katana2.h>
     35 #if defined(BCM_TRIUMPH_SUPPORT) && defined(INCLUDE_L3)
     36 #include <bcm_int/esw/triumph.h>
     37 #endif
     38 #ifdef BCM_HGPROXY_COE_SUPPORT 
     39 #include <bcm_int/esw/xgs5.h>
     40 #endif /* BCM_HGPROXY_COE_SUPPORT */
     41 
     42 #include <bcm_int/esw/portctrl.h>
     43 #define _BCM_TD_FP_TRUNK_RTAG1_6_MAX_PORTCNT  16
     44 #define _BCM_TD_FABRIC_TRUNK_RTAG1_6_MAX_PORTCNT 16
     45 
     46 #ifdef BCM_KATANA_SUPPORT
     47 #define _BCM_KATANA_FP_TRUNK_RTAG1_6_MAX_PORTCNT     8
     48 #define _BCM_KATANA_FABRIC_TRUNK_RTAG1_6_MAX_PORTCNT 4
     49 #endif
     50 
     51 /* -------------------------------- */
     52 /* Trunk membership info            */
     53 /* -------------------------------- */
     54 typedef struct {
     55     uint16 num_ports;
     56     uint16 *modport;
     57     uint32 *member_flags;
     58 #ifdef BCM_WARM_BOOT_SUPPORT
     59     uint8 recovered_from_scache;
     60 #endif /* BCM_WARM_BOOT_SUPPORT */
     61 } _trident_member_info_t;
     62 
     63 typedef struct {
     64     _trident_member_info_t *member_info;
     65 } _trident_trunk_member_info_t;
     66 
     67 STATIC _trident_trunk_member_info_t *_trident_trunk_member_info[BCM_MAX_NUM_UNITS];
     68 
     69 #define MEMBER_INFO(_unit_, _tid_) (_trident_trunk_member_info[_unit_]->member_info[_tid_])
     70 
     71 /* -------------------------------- */
     72 /* Module and port to trunk mapping */
     73 /* -------------------------------- */
     74 STATIC uint16 *_trident_mod_port_to_tid_map[BCM_MAX_NUM_UNITS];
     75 
     76 /* ----------------------------------------------------------------- */
     77 /* Bookkeeping info on which entries of trunk member tables are used */
     78 /* ----------------------------------------------------------------- */
     79 typedef struct _trident_trunk_member_bookkeeping_s {
     80     SHR_BITDCL *fp_trunk_member_bitmap;
     81     SHR_BITDCL *hg_trunk_member_bitmap;
     82 } _trident_trunk_member_bookkeeping_t;
     83 
     84 STATIC _trident_trunk_member_bookkeeping_t *_trident_trunk_member_bk[BCM_MAX_NUM_UNITS];
     85 
     86 #define TRUNK_MEMBER_INFO(_unit_) (_trident_trunk_member_bk[_unit_])
     87 
     88 #define _BCM_FP_TRUNK_MEMBER_USED_GET(_u_, _idx_) \
     89     SHR_BITGET(TRUNK_MEMBER_INFO(_u_)->fp_trunk_member_bitmap, _idx_)
     90 #define _BCM_FP_TRUNK_MEMBER_USED_SET(_u_, _idx_) \
     91     SHR_BITSET(TRUNK_MEMBER_INFO(_u_)->fp_trunk_member_bitmap, _idx_)
     92 #define _BCM_FP_TRUNK_MEMBER_USED_CLR(_u_, _idx_) \
     93     SHR_BITCLR(TRUNK_MEMBER_INFO(_u_)->fp_trunk_member_bitmap, _idx_)
     94 #define _BCM_FP_TRUNK_MEMBER_USED_SET_RANGE(_u_, _idx_, _count_) \
     95     SHR_BITSET_RANGE(TRUNK_MEMBER_INFO(_u_)->fp_trunk_member_bitmap, _idx_, _count_)
     96 #define _BCM_FP_TRUNK_MEMBER_USED_CLR_RANGE(_u_, _idx_, _count_) \
     97     SHR_BITCLR_RANGE(TRUNK_MEMBER_INFO(_u_)->fp_trunk_member_bitmap, _idx_, _count_)
     98 #define _BCM_FP_TRUNK_MEMBER_TEST_RANGE(_u_, _idx_, _count_, _result_) \
     99     SHR_BITTEST_RANGE(TRUNK_MEMBER_INFO(_u_)->fp_trunk_member_bitmap, _idx_, _count_, _result_)
    100                                                                                 
    101 #define _BCM_HG_TRUNK_MEMBER_USED_GET(_u_, _idx_) \
    102     SHR_BITGET(TRUNK_MEMBER_INFO(_u_)->hg_trunk_member_bitmap, _idx_)
    103 #define _BCM_HG_TRUNK_MEMBER_USED_SET(_u_, _idx_) \
    104     SHR_BITSET(TRUNK_MEMBER_INFO(_u_)->hg_trunk_member_bitmap, _idx_)
    105 #define _BCM_HG_TRUNK_MEMBER_USED_CLR(_u_, _idx_) \
    106     SHR_BITCLR(TRUNK_MEMBER_INFO(_u_)->hg_trunk_member_bitmap, _idx_)
    107 #define _BCM_HG_TRUNK_MEMBER_USED_SET_RANGE(_u_, _idx_, _count_) \
    108     SHR_BITSET_RANGE(TRUNK_MEMBER_INFO(_u_)->hg_trunk_member_bitmap, _idx_, _count_)
    109 #define _BCM_HG_TRUNK_MEMBER_USED_CLR_RANGE(_u_, _idx_, _count_) \
    110     SHR_BITCLR_RANGE(TRUNK_MEMBER_INFO(_u_)->hg_trunk_member_bitmap, _idx_, _count_)
    111 #define _BCM_HG_TRUNK_MEMBER_TEST_RANGE(_u_, _idx_, _count_, _result_) \
    112     SHR_BITTEST_RANGE(TRUNK_MEMBER_INFO(_u_)->hg_trunk_member_bitmap, _idx_, _count_, _result_)
    113 
    114 /* ------------------------------------------------- */
    115 /* Bookkeeping info for Higig dynamic load balancing */
    116 /* ------------------------------------------------- */
    117 typedef struct _trident_hg_dlb_bookkeeping_s {
    118     /* Higig DLB parameters */
    119     SHR_BITDCL *hg_dlb_id_used_bitmap;
    120     SHR_BITDCL *hg_dlb_flowset_block_bitmap; /* Each block corresponds to
    121                                                 512 entries */
    122 #ifdef BCM_TRIUMPH3_SUPPORT
    123     SHR_BITDCL *hg_dlb_member_id_used_bitmap;
    124 #endif /* BCM_TRIUMPH3_SUPPORT */
    125     int hg_dlb_sample_rate;
    126     int hg_dlb_tx_load_min_th;
    127     int hg_dlb_tx_load_max_th;
    128     int hg_dlb_qsize_min_th;
    129     int hg_dlb_qsize_max_th;
    130     uint8 *hg_dlb_load_weight;
    131     soc_profile_mem_t *hg_dlb_quality_map_profile;
    132 #ifdef BCM_WARM_BOOT_SUPPORT
    133     uint8 recovered_from_scache; /* Indicates if the following members of this
    134                                     structure have been recovered from scached:
    135                                     hg_dlb_sample_rate,
    136                                     hg_dlb_tx_load_min_th,
    137                                     hg_dlb_tx_load_max_th,
    138                                     hg_dlb_tx_qsize_min_th,
    139                                     hg_dlb_tx_qsize_max_th,
    140                                     hg_dlb_load_weight */
    141 #endif /* BCM_WARM_BOOT_SUPPORT */
    142 } _trident_hg_dlb_bookkeeping_t;
    143 
    144 STATIC _trident_hg_dlb_bookkeeping_t *_trident_hg_dlb_bk[BCM_MAX_NUM_UNITS];
    145 
    146 #define HG_DLB_INFO(_unit_) (_trident_hg_dlb_bk[_unit_])
    147 
    148 #define _BCM_HG_DLB_ID_USED_GET(_u_, _idx_) \
    149     SHR_BITGET(HG_DLB_INFO(_u_)->hg_dlb_id_used_bitmap, _idx_)
    150 #define _BCM_HG_DLB_ID_USED_SET(_u_, _idx_) \
    151     SHR_BITSET(HG_DLB_INFO(_u_)->hg_dlb_id_used_bitmap, _idx_)
    152 #define _BCM_HG_DLB_ID_USED_CLR(_u_, _idx_) \
    153     SHR_BITCLR(HG_DLB_INFO(_u_)->hg_dlb_id_used_bitmap, _idx_)
    154 
    155 #define _BCM_HG_DLB_FLOWSET_BLOCK_USED_GET(_u_, _idx_) \
    156     SHR_BITGET(HG_DLB_INFO(_u_)->hg_dlb_flowset_block_bitmap, _idx_)
    157 #define _BCM_HG_DLB_FLOWSET_BLOCK_USED_SET(_u_, _idx_) \
    158     SHR_BITSET(HG_DLB_INFO(_u_)->hg_dlb_flowset_block_bitmap, _idx_)
    159 #define _BCM_HG_DLB_FLOWSET_BLOCK_USED_CLR(_u_, _idx_) \
    160     SHR_BITCLR(HG_DLB_INFO(_u_)->hg_dlb_flowset_block_bitmap, _idx_)
    161 #define _BCM_HG_DLB_FLOWSET_BLOCK_USED_SET_RANGE(_u_, _idx_, _count_) \
    162     SHR_BITSET_RANGE(HG_DLB_INFO(_u_)->hg_dlb_flowset_block_bitmap, _idx_, _count_)
    163 #define _BCM_HG_DLB_FLOWSET_BLOCK_USED_CLR_RANGE(_u_, _idx_, _count_) \
    164     SHR_BITCLR_RANGE(HG_DLB_INFO(_u_)->hg_dlb_flowset_block_bitmap, _idx_, _count_)
    165 #define _BCM_HG_DLB_FLOWSET_BLOCK_TEST_RANGE(_u_, _idx_, _count_, _result_) \
    166     SHR_BITTEST_RANGE(HG_DLB_INFO(_u_)->hg_dlb_flowset_block_bitmap, _idx_, _count_, _result_)
    167 
    168 #ifdef BCM_TRIUMPH3_SUPPORT
    169 #define _BCM_HG_DLB_MEMBER_ID_USED_GET(_u_, _idx_) \
    170     SHR_BITGET(HG_DLB_INFO(_u_)->hg_dlb_member_id_used_bitmap, _idx_)
    171 #define _BCM_HG_DLB_MEMBER_ID_USED_SET(_u_, _idx_) \
    172     SHR_BITSET(HG_DLB_INFO(_u_)->hg_dlb_member_id_used_bitmap, _idx_)
    173 #define _BCM_HG_DLB_MEMBER_ID_USED_CLR(_u_, _idx_) \
    174     SHR_BITCLR(HG_DLB_INFO(_u_)->hg_dlb_member_id_used_bitmap, _idx_)
    175 #endif /* BCM_TRIUMPH3_SUPPORT */
    176 
    177 /* ---------------------------- */
    178 /* Higig trunk override profile */
    179 /* ---------------------------- */
    180 STATIC soc_profile_mem_t *_trident_hg_trunk_override_profile[BCM_MAX_NUM_UNITS];
    181 
    182 /* ----------------------- */
    183 /* Hardware Trunk Failover */
    184 /* ----------------------- */
    185 
    186 /* For the devices which support hardware trunk failover, the failover
    187  * configuration must be retained if it is one of the standard models 
    188  * for the retrieval function to use the same encoding as the set function.
    189  * 
    190  * Note: The trunk members stored in _trident_hw_tinfo_t's modport array do not 
    191  *       include those members with the BCM_TRUNK_MEMBER_EGRESS_DISABLE set.
    192  */
    193 
    194 typedef struct {
    195     uint16        num_ports;
    196     uint8         *psc;
    197     uint16        *modport;
    198     uint32        *flags;
    199 } _trident_hw_tinfo_t;
    200 
    201 typedef struct {
    202     _trident_hw_tinfo_t *hw_tinfo;
    203 } _trident_trunk_hwfail_t;
    204 
    205 STATIC _trident_trunk_hwfail_t *_trident_trunk_hwfail[BCM_MAX_NUM_UNITS];
    206 
    207 /* ----------------------- */
    208 /* Software Trunk Failover */
    209 /* ----------------------- */
    210 
    211 /* Even without hardware failover support, given the high speed link
    212  * change notification possible with trident devices, a port that has been
    213  * indicated as link down can cause the trunk_group table to be immediately
    214  * updated with the link down port removed.  This works well for two cases:
    215  * (1) this is a higig trunk, or (2) the local device is the only device
    216  * in the system.
    217  * 
    218  * Note: The trunk members stored in _trident_tinfo_t's modport array do not 
    219  *       include those members with the BCM_TRUNK_MEMBER_EGRESS_DISABLE set.
    220  *       If a trunk member port is down, it'll be removed from_trident_tinfo_t's
    221  *       modport array by _bcm_trident_trunk_swfailover_trigger. 
    222  */
    223 typedef struct {
    224     uint8         rtag;
    225     uint16        num_ports;
    226     uint16        *modport;
    227     uint32        *member_flags;
    228     uint32        flags;
    229 } _trident_tinfo_t;
    230 
    231 typedef struct {
    232     uint8         mymodid;
    233 #if (SOC_MAX_NUM_PP_PORTS > SOC_MAX_NUM_PORTS)
    234     bcm_trunk_t   trunk[SOC_MAX_NUM_PP_PORTS];
    235 #else
    236     bcm_trunk_t   trunk[SOC_MAX_NUM_PORTS]; /* If port is not a member of any
    237                                                trunk group, trunk = 0; else
    238                                                trunk = trunk id + 1. */
    239 #endif
    240     _trident_tinfo_t *tinfo;
    241 } _trident_trunk_swfail_t;
    242 
    243 STATIC _trident_trunk_swfail_t *_trident_trunk_swfail[BCM_MAX_NUM_UNITS];
    244 
    245 int bcm_trident_trunk_mbr_zero_rsvd[BCM_MAX_NUM_UNITS] = {0};
    246 
    247 /* Function prototypes */
    248 STATIC int _bcm_trident_trunk_set_port_property(int unit,
    249         bcm_module_t mod, bcm_port_t port, int tid);
    250 STATIC int _bcm_trident_trunk_fabric_port_set(int unit,
    251         bcm_trunk_t hgtid, pbmp_t old_ports, pbmp_t new_ports);
    252 STATIC int _bcm_trident_nuc_tpbm_get(int unit,
    253         int num_ports, bcm_module_t *tm, SHR_BITDCL *nuc_tpbm);
    254 STATIC int _bcm_trident_trunk_block_mask(int unit, int nuc_type,
    255         pbmp_t old_ports, pbmp_t new_ports, 
    256         int *localport_array, int localport_count,
    257         SHR_BITDCL *my_modid_bmap, uint32 member_count,
    258         uint32 flags);
    259 STATIC int _bcm_trident_hg_dlb_sample_rate_thresholds_set(int unit,
    260         int sample_rate, int min_th, int max_th);
    261 STATIC int _bcm_trident_hg_dlb_qsize_thresholds_set(int unit,
    262         int min_th, int max_th);
    263 STATIC int _bcm_trident_hg_dlb_quality_assign(int unit, int tx_load_percent,
    264         uint32 *entry_arr);
    265 
    266 /* ----------------------------------------------------------------------------- 
    267  *
    268  * Routines for initialization and de-initialization
    269  *
    270  * ----------------------------------------------------------------------------- 
    271  */
    272 
    273 /*
    274  * Function:
    275  *      _bcm_trident_trunk_member_info_deinit
    276  * Purpose:
    277  *      Deallocate trunk membership info.
    278  * Parameters:
    279  *      unit - (IN)SOC unit number. 
    280  * Returns:
    281  *      None
    282  */
    283 STATIC void
    284 _bcm_trident_trunk_member_info_deinit(int unit)
    285 {
    286     int trunk_num_groups;
    287     int i;
    288 
    289     if (_trident_trunk_member_info[unit]) {
    290         if (_trident_trunk_member_info[unit]->member_info) {
    291             trunk_num_groups = soc_mem_index_count(unit, TRUNK_GROUPm) +
    292                 soc_mem_index_count(unit, HG_TRUNK_GROUPm);
    293             for (i = 0; i < trunk_num_groups; i++) {
    294                 if (MEMBER_INFO(unit, i).modport) {
    295                     sal_free(MEMBER_INFO(unit, i).modport);
    296                     MEMBER_INFO(unit, i).modport = NULL;
    297                 }
    298                 if (MEMBER_INFO(unit, i).member_flags) {
    299                     sal_free(MEMBER_INFO(unit, i).member_flags);
    300                     MEMBER_INFO(unit, i).member_flags = NULL;
    301                 }
    302             }
    303             sal_free(_trident_trunk_member_info[unit]->member_info);
    304             _trident_trunk_member_info[unit]->member_info = NULL;
    305         }
    306         sal_free(_trident_trunk_member_info[unit]);
    307         _trident_trunk_member_info[unit] = NULL;
    308     }
    309 }
    310 
    311 /*
    312  * Function:
    313  *      _bcm_trident_trunk_member_info_init
    314  * Purpose:
    315  *      Allocate and initialize trunk member info.
    316  * Parameters:
    317  *      unit - (IN)SOC unit number. 
    318  * Returns:
    319  *      BCM_X_XXX
    320  */
    321 STATIC int
    322 _bcm_trident_trunk_member_info_init(int unit)
    323 {
    324     int trunk_num_groups;
    325 
    326     if (_trident_trunk_member_info[unit] == NULL) {
    327         _trident_trunk_member_info[unit] =
    328             sal_alloc(sizeof(_trident_trunk_member_info_t), "trunk member info");
    329         if (_trident_trunk_member_info[unit] == NULL) {
    330             return BCM_E_MEMORY;
    331         }
    332     }
    333     sal_memset(_trident_trunk_member_info[unit], 0,
    334             sizeof(_trident_trunk_member_info_t));
    335 
    336     trunk_num_groups = soc_mem_index_count(unit, TRUNK_GROUPm) +
    337                        soc_mem_index_count(unit, HG_TRUNK_GROUPm);
    338     if (_trident_trunk_member_info[unit]->member_info == NULL) {
    339         _trident_trunk_member_info[unit]->member_info =
    340             sal_alloc(sizeof(_trident_member_info_t) * trunk_num_groups,
    341                     "member info");
    342         if (_trident_trunk_member_info[unit]->member_info == NULL) {
    343             _bcm_trident_trunk_member_info_deinit(unit);
    344             return BCM_E_MEMORY;
    345         }
    346     }
    347     sal_memset(_trident_trunk_member_info[unit]->member_info, 0, 
    348                sizeof(_trident_member_info_t) * trunk_num_groups);
    349                                                                                 
    350     /* Note: The maximum number of member ports in a trunk group is 256 in Trident.
    351      *       But it would be quite wasteful to allocate 256 entries to each 
    352      *       _trident_trunk_member_info[unit]->member_info[x].modport/member_flags arrays.
    353      *       These arrays will be allocated as member ports are added to trunk group.
    354      */
    355 
    356     return BCM_E_NONE;
    357 }
    358 
    359 /*
    360  * Function:
    361  *      _bcm_trident_trunk_mod_port_map_deinit
    362  * Purpose:
    363  *      Deinitialize a software cache for the SOURCE_TRUNK_MAP_TABLE.
    364  * Parameters:
    365  *      unit     -  (IN)SOC unit number. 
    366  * Returns:
    367  *      None
    368  */
    369 STATIC void
    370 _bcm_trident_trunk_mod_port_map_deinit(int unit) 
    371 {
    372     if (_trident_mod_port_to_tid_map[unit]) {
    373         sal_free(_trident_mod_port_to_tid_map[unit]);
    374         _trident_mod_port_to_tid_map[unit] = NULL;
    375     }
    376 }
    377 
    378 /*
    379  * Function:
    380  *      _bcm_trident_trunk_mod_port_map_init
    381  * Purpose:
    382  *      Initialize a software cache for the SOURCE_TRUNK_MAP_TABLE.
    383  * Parameters:
    384  *      unit     -  (IN)SOC unit number. 
    385  * Returns:
    386  *      BCM_X_XXX
    387  */
    388 STATIC int 
    389 _bcm_trident_trunk_mod_port_map_init(int unit) 
    390 {
    391     if (_trident_mod_port_to_tid_map[unit] == NULL) {
    392         _trident_mod_port_to_tid_map[unit] = 
    393             sal_alloc(sizeof(uint16) * _BCM_XGS3_TRUNK_MOD_PORT_MAP_IDX_COUNT(unit),
    394                     "_trident_mod_port_to_tid_map"); 
    395         if (_trident_mod_port_to_tid_map[unit] == NULL) {
    396             return BCM_E_MEMORY;
    397         }
    398     }
    399     sal_memset(_trident_mod_port_to_tid_map[unit], 0, 
    400             sizeof(uint16) * _BCM_XGS3_TRUNK_MOD_PORT_MAP_IDX_COUNT(unit));
    401 
    402     return BCM_E_NONE;
    403 }
    404 
    405 /*
    406  * Function:
    407  *      _bcm_trident_trunk_member_bk_deinit
    408  * Purpose:
    409  *      Deallocate _trident_trunk_member_bk
    410  * Parameters:
    411  *      unit - (IN)SOC unit number. 
    412  * Returns:
    413  *      None
    414  */
    415 STATIC void
    416 _bcm_trident_trunk_member_bk_deinit(int unit) 
    417 {
    418     if (_trident_trunk_member_bk[unit]) {
    419         if (_trident_trunk_member_bk[unit]->fp_trunk_member_bitmap) {
    420             sal_free(_trident_trunk_member_bk[unit]->fp_trunk_member_bitmap);
    421             _trident_trunk_member_bk[unit]->fp_trunk_member_bitmap = NULL;
    422         }
    423         if (_trident_trunk_member_bk[unit]->hg_trunk_member_bitmap) {
    424             sal_free(_trident_trunk_member_bk[unit]->hg_trunk_member_bitmap);
    425             _trident_trunk_member_bk[unit]->hg_trunk_member_bitmap = NULL;
    426         }
    427         sal_free(_trident_trunk_member_bk[unit]);
    428         _trident_trunk_member_bk[unit] = NULL;
    429     }
    430 }
    431 
    432 /*
    433  * Function:
    434  *      _bcm_trident_trunk_member_bk_init
    435  * Purpose:
    436  *      Allocate and initialize _trident_trunk_member_bk
    437  * Parameters:
    438  *      unit - (IN)SOC unit number. 
    439  * Returns:
    440  *      BCM_X_XXX
    441  */
    442 STATIC int 
    443 _bcm_trident_trunk_member_bk_init(int unit) 
    444 {
    445     int fp_trunk_member_tbl_size;
    446     int hg_trunk_member_tbl_size;
    447 
    448     if (_trident_trunk_member_bk[unit] == NULL) {
    449         _trident_trunk_member_bk[unit] = 
    450             sal_alloc(sizeof(_trident_trunk_member_bookkeeping_t), "_trident_trunk_member_bk");
    451         if (_trident_trunk_member_bk[unit] == NULL) {
    452             return BCM_E_MEMORY;
    453         }
    454     }
    455     sal_memset(_trident_trunk_member_bk[unit], 0,
    456             sizeof(_trident_trunk_member_bookkeeping_t));
    457 
    458     fp_trunk_member_tbl_size = soc_mem_index_count(unit, TRUNK_MEMBERm);
    459     if (_trident_trunk_member_bk[unit]->fp_trunk_member_bitmap == NULL) {
    460         _trident_trunk_member_bk[unit]->fp_trunk_member_bitmap = 
    461             sal_alloc(SHR_BITALLOCSIZE(fp_trunk_member_tbl_size), "fp_trunk_member_bitmap");
    462         if (_trident_trunk_member_bk[unit]->fp_trunk_member_bitmap == NULL) {
    463             _bcm_trident_trunk_member_bk_deinit(unit);
    464             return BCM_E_MEMORY;
    465         }
    466     }
    467     sal_memset(_trident_trunk_member_bk[unit]->fp_trunk_member_bitmap, 0,
    468             SHR_BITALLOCSIZE(fp_trunk_member_tbl_size));
    469 
    470     if (!SOC_WARM_BOOT(unit)) {
    471         _BCM_FP_TRUNK_MEMBER_USED_SET(unit, 0);
    472         bcm_trident_trunk_mbr_zero_rsvd[unit] = TRUE;
    473     }
    474 
    475     hg_trunk_member_tbl_size = soc_mem_index_count(unit, HG_TRUNK_MEMBERm);
    476     if (_trident_trunk_member_bk[unit]->hg_trunk_member_bitmap == NULL) {
    477         _trident_trunk_member_bk[unit]->hg_trunk_member_bitmap = 
    478             sal_alloc(SHR_BITALLOCSIZE(hg_trunk_member_tbl_size), "hg_trunk_member_bitmap");
    479         if (_trident_trunk_member_bk[unit]->hg_trunk_member_bitmap == NULL) {
    480             _bcm_trident_trunk_member_bk_deinit(unit);
    481             return BCM_E_MEMORY;
    482         }
    483     }
    484     sal_memset(_trident_trunk_member_bk[unit]->hg_trunk_member_bitmap, 0,
    485             SHR_BITALLOCSIZE(hg_trunk_member_tbl_size));
    486 
    487     /* Reserve entry 0 of HG_TRUNK_MEMBERm, as invalid Higig trunk groups have
    488      * their HG_TRUNK_GROUP table entry's BASE_PTR and TG_SIZE fields set to 0.
    489      */ 
    490     if (!SOC_WARM_BOOT(unit)) {
    491         SOC_IF_ERROR_RETURN
    492             (WRITE_HG_TRUNK_MEMBERm(unit, MEM_BLOCK_ALL, 0,
    493                                     soc_mem_entry_null(unit, HG_TRUNK_MEMBERm)));
    494     }
    495 
    496     if (!SOC_IS_KATANAX(unit)) {
    497         /* Katana's HG_TRUNK_MEMBER table only has 8 members.
    498          * It would be too expensive to reserve entry 0.
    499          */
    500         _BCM_HG_TRUNK_MEMBER_USED_SET(unit, 0);
    501     }
    502 
    503     return BCM_E_NONE;
    504 }
    505 
    506 /*
    507  * Function:
    508  *      _bcm_trident_hg_dlb_quality_map_profile_init
    509  * Purpose:
    510  *      Initialize Higig DLB quality mapping profile.
    511  * Parameters:
    512  *      unit - (IN)SOC unit number. 
    513  * Returns:
    514  *      BCM_X_XXX
    515  */
    516 STATIC int 
    517 _bcm_trident_hg_dlb_quality_map_profile_init(int unit) 
    518 {
    519     soc_profile_mem_t *profile;
    520     soc_mem_t mem;
    521     int entry_words;
    522     int entries_per_profile;
    523     int tx_load_percent;
    524     int alloc_size;
    525     uint32 *entry_arr;
    526     int rv = BCM_E_NONE;
    527     void *entries;
    528     uint32 base_index = 0;
    529     int port_count;
    530     bcm_port_t port;
    531     uint32 quantize_control_reg;
    532     int i;
    533 
    534     if (NULL == _trident_hg_dlb_bk[unit]->hg_dlb_quality_map_profile) {
    535         _trident_hg_dlb_bk[unit]->hg_dlb_quality_map_profile =
    536             sal_alloc(sizeof(soc_profile_mem_t),
    537                       "HG DLB Quality Map Profile Mem");
    538         if (NULL == _trident_hg_dlb_bk[unit]->hg_dlb_quality_map_profile) {
    539             return BCM_E_MEMORY;
    540         }
    541     } else {
    542         soc_profile_mem_destroy(unit,
    543                 _trident_hg_dlb_bk[unit]->hg_dlb_quality_map_profile);
    544     }
    545     profile = _trident_hg_dlb_bk[unit]->hg_dlb_quality_map_profile;
    546     soc_profile_mem_t_init(profile);
    547 
    548     if (soc_mem_is_valid(unit, DLB_HGT_PORT_QUALITY_MAPPINGm)) {
    549         mem = DLB_HGT_PORT_QUALITY_MAPPINGm;
    550         entry_words = sizeof(dlb_hgt_port_quality_mapping_entry_t) /
    551             sizeof(uint32);
    552     } else {
    553         mem = DLB_HGT_QUALITY_MAPPINGm;
    554         entry_words = sizeof(dlb_hgt_quality_mapping_entry_t) / sizeof(uint32);
    555     }
    556     SOC_IF_ERROR_RETURN
    557         (soc_profile_mem_create(unit, &mem, &entry_words, 1, profile));
    558 
    559     entries_per_profile = 64;
    560     if (!SOC_WARM_BOOT(unit)) {
    561         alloc_size = entries_per_profile * entry_words * sizeof(uint32);
    562         entry_arr = sal_alloc(alloc_size, "HG DLB Quality Map entries");
    563         if (entry_arr == NULL) {
    564             return BCM_E_MEMORY;
    565         }
    566         sal_memset(entry_arr, 0, alloc_size);
    567 
    568         /* Assign quality in the entry array, with 100% weight for port load,
    569          * 0% for queue size.
    570          */
    571         tx_load_percent = 100;
    572         rv = _bcm_trident_hg_dlb_quality_assign(unit, tx_load_percent,
    573                 entry_arr);
    574         if (BCM_FAILURE(rv)) {
    575             sal_free(entry_arr);
    576             return rv;
    577         }
    578 
    579         entries = entry_arr;
    580         rv = soc_profile_mem_add(unit, profile, &entries, entries_per_profile,
    581                 &base_index);
    582         sal_free(entry_arr);
    583         if (SOC_FAILURE(rv)) {
    584             return rv;
    585         }
    586 
    587 #ifdef BCM_TRIUMPH3_SUPPORT
    588         if (soc_feature(unit, soc_feature_hg_dlb_member_id)) {
    589             int member_id;
    590             dlb_hgt_quality_control_entry_t quality_control_entry;
    591             soc_field_t profile_ptr_f;
    592 
    593             for (member_id = 0;
    594                  member_id < soc_mem_index_count(unit,
    595                         DLB_HGT_QUALITY_CONTROLm);
    596                  member_id++) {
    597                 BCM_IF_ERROR_RETURN
    598                     (READ_DLB_HGT_QUALITY_CONTROLm(unit, MEM_BLOCK_ANY,
    599                                                    member_id,
    600                                                    &quality_control_entry));
    601                 profile_ptr_f = soc_mem_field_valid(unit,
    602                         DLB_HGT_QUALITY_CONTROLm, PROFILE_PTRf) ?
    603                         PROFILE_PTRf : QMT_PROFILE_PTRf;
    604                 soc_DLB_HGT_QUALITY_CONTROLm_field32_set(unit,
    605                         &quality_control_entry, profile_ptr_f,
    606                         base_index / entries_per_profile);
    607                 BCM_IF_ERROR_RETURN
    608                     (WRITE_DLB_HGT_QUALITY_CONTROLm(unit, MEM_BLOCK_ALL,
    609                                                     member_id,
    610                                                     &quality_control_entry));
    611             }  
    612 
    613             for (i = 0; i < entries_per_profile; i++) {
    614                 SOC_PROFILE_MEM_REFERENCE(unit, profile, base_index + i,
    615                         member_id - 1);
    616             }
    617 
    618             HG_DLB_INFO(unit)->
    619                 hg_dlb_load_weight[base_index/entries_per_profile] =
    620                     tx_load_percent;
    621         } else
    622 #endif /* BCM_TRIUMPH3_SUPPORT */
    623         {
    624             port_count = 0;
    625             PBMP_ALL_ITER(unit, port) {
    626                 BCM_IF_ERROR_RETURN
    627                     (READ_DLB_HGT_QUANTIZE_CONTROLr(unit, port,
    628                                                     &quantize_control_reg));
    629                 soc_reg_field_set(unit, DLB_HGT_QUANTIZE_CONTROLr,
    630                         &quantize_control_reg,
    631                         PORT_QUALITY_MAPPING_PROFILE_PTRf,
    632                         base_index / entries_per_profile);
    633                 BCM_IF_ERROR_RETURN
    634                     (WRITE_DLB_HGT_QUANTIZE_CONTROLr(unit, port,
    635                                                      quantize_control_reg));
    636                 port_count++;
    637             }  
    638 
    639             for (i = 0; i < entries_per_profile; i++) {
    640                 SOC_PROFILE_MEM_REFERENCE(unit, profile, base_index + i,
    641                         port_count - 1);
    642             }
    643 
    644             HG_DLB_INFO(unit)->
    645                 hg_dlb_load_weight[base_index/entries_per_profile] =
    646                     tx_load_percent;
    647         } 
    648     } else { /* Warm boot, recover reference counts and entries_per_set */
    649 #ifdef BCM_TRIUMPH3_SUPPORT
    650         if (soc_feature(unit, soc_feature_hg_dlb_member_id)) {
    651             int member_id;
    652             dlb_hgt_quality_control_entry_t quality_control_entry;
    653             soc_field_t profile_ptr_f;
    654 
    655             for (member_id = 0;
    656                  member_id < soc_mem_index_count(unit,
    657                         DLB_HGT_QUALITY_CONTROLm);
    658                  member_id++) {
    659                 BCM_IF_ERROR_RETURN
    660                     (READ_DLB_HGT_QUALITY_CONTROLm(unit, MEM_BLOCK_ANY,
    661                                                    member_id,
    662                                                    &quality_control_entry));
    663                 profile_ptr_f = soc_mem_field_valid(unit,
    664                         DLB_HGT_QUALITY_CONTROLm, PROFILE_PTRf) ?
    665                         PROFILE_PTRf : QMT_PROFILE_PTRf;
    666                 base_index = soc_DLB_HGT_QUALITY_CONTROLm_field32_get(unit,
    667                         &quality_control_entry, profile_ptr_f);
    668 
    669                 base_index *= entries_per_profile;
    670                 for (i = 0; i < entries_per_profile; i++) {
    671                     SOC_PROFILE_MEM_REFERENCE(unit, profile, base_index + i, 1);
    672                     SOC_PROFILE_MEM_ENTRIES_PER_SET(unit, profile,
    673                             base_index + i, entries_per_profile);
    674                 }
    675             }  
    676         } else
    677 #endif /* BCM_TRIUMPH3_SUPPORT */
    678         {
    679             PBMP_ALL_ITER(unit, port) {
    680                 BCM_IF_ERROR_RETURN(READ_DLB_HGT_QUANTIZE_CONTROLr(unit, port,
    681                             &quantize_control_reg));
    682                 base_index = soc_reg_field_get(unit, DLB_HGT_QUANTIZE_CONTROLr,
    683                         quantize_control_reg, PORT_QUALITY_MAPPING_PROFILE_PTRf);
    684                 base_index *= entries_per_profile;
    685                 for (i = 0; i < entries_per_profile; i++) {
    686                     SOC_PROFILE_MEM_REFERENCE(unit, profile, base_index + i, 1);
    687                     SOC_PROFILE_MEM_ENTRIES_PER_SET(unit, profile,
    688                             base_index + i, entries_per_profile);
    689                 }
    690             }
    691         }
    692     }
    693 
    694     return BCM_E_NONE;
    695 }
    696 
    697 /*
    698  * Function:
    699  *      _bcm_trident_hg_dlb_deinit
    700  * Purpose:
    701  *      Deallocate _trident_hg_dlb_bk
    702  * Parameters:
    703  *      unit - (IN)SOC unit number. 
    704  * Returns:
    705  *      None
    706  */
    707 STATIC void
    708 _bcm_trident_hg_dlb_deinit(int unit) 
    709 {
    710     int rv;
    711     soc_field_t dlb_refresh_f;
    712     uint32 arb_control_reg;
    713 
    714     if (_trident_hg_dlb_bk[unit]) {
    715         if (_trident_hg_dlb_bk[unit]->hg_dlb_id_used_bitmap) {
    716             sal_free(_trident_hg_dlb_bk[unit]->hg_dlb_id_used_bitmap);
    717             _trident_hg_dlb_bk[unit]->hg_dlb_id_used_bitmap = NULL;
    718         }
    719         if (_trident_hg_dlb_bk[unit]->hg_dlb_flowset_block_bitmap) {
    720             sal_free(_trident_hg_dlb_bk[unit]->hg_dlb_flowset_block_bitmap);
    721             _trident_hg_dlb_bk[unit]->hg_dlb_flowset_block_bitmap = NULL;
    722         }
    723 #ifdef BCM_TRIUMPH3_SUPPORT
    724         if (soc_feature(unit, soc_feature_hg_dlb_member_id)) {
    725             if (_trident_hg_dlb_bk[unit]->hg_dlb_member_id_used_bitmap) {
    726                 sal_free(_trident_hg_dlb_bk[unit]->hg_dlb_member_id_used_bitmap);
    727                 _trident_hg_dlb_bk[unit]->hg_dlb_member_id_used_bitmap = NULL;
    728             }
    729         }
    730 #endif /* BCM_TRIUMPH3_SUPPORT */
    731         if (_trident_hg_dlb_bk[unit]->hg_dlb_load_weight) {
    732             sal_free(_trident_hg_dlb_bk[unit]->hg_dlb_load_weight);
    733             _trident_hg_dlb_bk[unit]->hg_dlb_load_weight = NULL;
    734         }
    735         if (_trident_hg_dlb_bk[unit]->hg_dlb_quality_map_profile) {
    736             soc_profile_mem_destroy(unit,
    737                     _trident_hg_dlb_bk[unit]->hg_dlb_quality_map_profile);
    738             sal_free(_trident_hg_dlb_bk[unit]->hg_dlb_quality_map_profile);
    739             _trident_hg_dlb_bk[unit]->hg_dlb_quality_map_profile = NULL;
    740         }
    741 
    742         sal_free(_trident_hg_dlb_bk[unit]);
    743         _trident_hg_dlb_bk[unit] = NULL;
    744     }
    745 
    746     /* Disable DLB HGT refresh */
    747     dlb_refresh_f = soc_reg_field_valid(unit, AUX_ARB_CONTROL_2r,
    748             DLB_HGT_REFRESH_ENABLEf) ? DLB_HGT_REFRESH_ENABLEf :
    749             DLB_REFRESH_ENABLEf;
    750     rv = READ_AUX_ARB_CONTROL_2r(unit, &arb_control_reg);
    751     if (BCM_SUCCESS(rv)) {
    752         soc_reg_field_set(unit, AUX_ARB_CONTROL_2r, &arb_control_reg,
    753                 dlb_refresh_f, 0);
    754         if (soc_reg_field_valid(unit, AUX_ARB_CONTROL_2r,
    755                     DLB_HGT_256NS_REFRESH_ENABLEf)) {
    756             soc_reg_field_set(unit, AUX_ARB_CONTROL_2r, &arb_control_reg,
    757                     DLB_HGT_256NS_REFRESH_ENABLEf, 0);
    758         } else if (soc_reg_field_valid(unit, AUX_ARB_CONTROL_2r,
    759                     DLB_1US_TICK_ENABLEf)) {
    760             soc_reg_field_set(unit, AUX_ARB_CONTROL_2r, &arb_control_reg,
    761                     DLB_1US_TICK_ENABLEf, 0);
    762         }
    763         (void)WRITE_AUX_ARB_CONTROL_2r(unit, arb_control_reg);
    764     }
    765 
    766 #ifdef BCM_TRIUMPH3_SUPPORT
    767     if (soc_reg_field_valid(unit, SW2_HW_CONTROLr, ENABLE_HGT_DLBf)) {
    768         uint32 sw2_hw_control_reg;
    769 
    770         rv = READ_SW2_HW_CONTROLr(unit, &sw2_hw_control_reg);
    771         if (BCM_SUCCESS(rv)) {
    772             soc_reg_field_set(unit, SW2_HW_CONTROLr, &sw2_hw_control_reg,
    773                     ENABLE_HGT_DLBf, 0);
    774             (void)WRITE_SW2_HW_CONTROLr(unit, sw2_hw_control_reg);
    775         }
    776     }
    777 #endif /* BCM_TRIUMPH3_SUPPORT */
    778 
    779 }
    780 
    781 /*
    782  * Function:
    783  *      _bcm_trident_hg_dlb_init
    784  * Purpose:
    785  *      Allocate and initialize _trident_hg_dlb_bk
    786  * Parameters:
    787  *      unit - (IN)SOC unit number. 
    788  * Returns:
    789  *      BCM_X_XXX
    790  */
    791 STATIC int 
    792 _bcm_trident_hg_dlb_init(int unit) 
    793 {
    794     int num_hg_dlb_id;
    795     int hg_flowset_tbl_size;
    796     int total_num_blocks;
    797     int rv = BCM_E_NONE;
    798     uint32 quantize_control_reg;
    799     bcm_port_t port;
    800     uint32 measure_update_control_reg;
    801     soc_field_t dlb_refresh_f;
    802     uint32 arb_control_reg;
    803     uint64 arb_control_reg_64;
    804     int num_quality_map_profiles = 0;
    805 
    806     if (_trident_hg_dlb_bk[unit] == NULL) {
    807         _trident_hg_dlb_bk[unit] = sal_alloc(
    808                 sizeof(_trident_hg_dlb_bookkeeping_t), "_trident_hg_dlb_bk");
    809         if (_trident_hg_dlb_bk[unit] == NULL) {
    810             return BCM_E_MEMORY;
    811         }
    812     }
    813     sal_memset(_trident_hg_dlb_bk[unit], 0,
    814             sizeof(_trident_hg_dlb_bookkeeping_t));
    815 
    816     num_hg_dlb_id = soc_mem_index_count(unit, DLB_HGT_GROUP_CONTROLm);
    817     if (_trident_hg_dlb_bk[unit]->hg_dlb_id_used_bitmap == NULL) {
    818         _trident_hg_dlb_bk[unit]->hg_dlb_id_used_bitmap = 
    819             sal_alloc(SHR_BITALLOCSIZE(num_hg_dlb_id), "hg_dlb_id_used_bitmap");
    820         if (_trident_hg_dlb_bk[unit]->hg_dlb_id_used_bitmap == NULL) {
    821             _bcm_trident_hg_dlb_deinit(unit);
    822             return BCM_E_MEMORY;
    823         }
    824     }
    825     sal_memset(_trident_hg_dlb_bk[unit]->hg_dlb_id_used_bitmap, 0,
    826             SHR_BITALLOCSIZE(num_hg_dlb_id));
    827 
    828 #ifdef BCM_TRIUMPH3_SUPPORT
    829     if (soc_feature(unit, soc_feature_hg_dlb_member_id)) {
    830         hg_flowset_tbl_size = soc_mem_index_count(unit, DLB_HGT_FLOWSETm);
    831     } else 
    832 #endif
    833     {
    834         hg_flowset_tbl_size = soc_mem_index_count(unit, DLB_HGT_FLOWSET_PORTm);
    835     }
    836     /* Each bit in hg_dlb_flowset_block_bitmap corresponds to a block of 512
    837      * flow set table entries.
    838      */
    839     total_num_blocks = hg_flowset_tbl_size / 512;
    840     if (_trident_hg_dlb_bk[unit]->hg_dlb_flowset_block_bitmap == NULL) {
    841         _trident_hg_dlb_bk[unit]->hg_dlb_flowset_block_bitmap = 
    842             sal_alloc(SHR_BITALLOCSIZE(total_num_blocks),
    843                     "hg_dlb_flowset_block_bitmap");
    844         if (_trident_hg_dlb_bk[unit]->hg_dlb_flowset_block_bitmap == NULL) {
    845             _bcm_trident_hg_dlb_deinit(unit);
    846             return BCM_E_MEMORY;
    847         }
    848     }
    849     sal_memset(_trident_hg_dlb_bk[unit]->hg_dlb_flowset_block_bitmap, 0,
    850             SHR_BITALLOCSIZE(total_num_blocks));
    851 
    852 #ifdef BCM_TRIUMPH3_SUPPORT
    853     if (soc_feature(unit, soc_feature_hg_dlb_member_id)) {
    854         int num_hg_dlb_member_id;
    855         soc_field_t profile_ptr_f;
    856 
    857         num_hg_dlb_member_id = soc_mem_index_count(unit,
    858                 DLB_HGT_MEMBER_ATTRIBUTEm);
    859         if (_trident_hg_dlb_bk[unit]->hg_dlb_member_id_used_bitmap == NULL) {
    860             _trident_hg_dlb_bk[unit]->hg_dlb_member_id_used_bitmap = 
    861                 sal_alloc(SHR_BITALLOCSIZE(num_hg_dlb_member_id),
    862                         "hg_dlb_member_id_used_bitmap");
    863             if (_trident_hg_dlb_bk[unit]->hg_dlb_member_id_used_bitmap == NULL) {
    864                 _bcm_trident_hg_dlb_deinit(unit);
    865                 return BCM_E_MEMORY;
    866             }
    867         }
    868         sal_memset(_trident_hg_dlb_bk[unit]->hg_dlb_member_id_used_bitmap, 0,
    869                 SHR_BITALLOCSIZE(num_hg_dlb_member_id));
    870 
    871         profile_ptr_f = soc_mem_field_valid(unit, DLB_HGT_QUALITY_CONTROLm,
    872                 PROFILE_PTRf) ? PROFILE_PTRf : QMT_PROFILE_PTRf;
    873         num_quality_map_profiles = 1 << soc_mem_field_length(unit,
    874                 DLB_HGT_QUALITY_CONTROLm, profile_ptr_f);
    875     } else
    876 #endif /* BCM_TRIUMPH3_SUPPORT */
    877     {
    878         num_quality_map_profiles = 1 << soc_reg_field_length(unit,
    879                 DLB_HGT_QUANTIZE_CONTROLr, PORT_QUALITY_MAPPING_PROFILE_PTRf);
    880     }
    881 
    882     if (_trident_hg_dlb_bk[unit]->hg_dlb_load_weight == NULL) {
    883         _trident_hg_dlb_bk[unit]->hg_dlb_load_weight = 
    884             sal_alloc(num_quality_map_profiles * sizeof(uint8),
    885                     "hg_dlb_load_weight");
    886         if (_trident_hg_dlb_bk[unit]->hg_dlb_load_weight == NULL) {
    887             _bcm_trident_hg_dlb_deinit(unit);
    888             return BCM_E_MEMORY;
    889         }
    890     }
    891     sal_memset(_trident_hg_dlb_bk[unit]->hg_dlb_load_weight, 0,
    892             num_quality_map_profiles * sizeof(uint8));
    893 
    894     /* Initialize port quality mapping profile */
    895     rv = _bcm_trident_hg_dlb_quality_map_profile_init(unit);
    896     if (BCM_FAILURE(rv)) {
    897         _bcm_trident_hg_dlb_deinit(unit);
    898         return rv;
    899     }
    900 
    901     if (!SOC_WARM_BOOT(unit)) {
    902         /* Set Higig DLB sampling period and port load thresholds */
    903         rv = _bcm_trident_hg_dlb_sample_rate_thresholds_set(unit, 1000000,
    904                 1250, 8750);
    905         if (BCM_FAILURE(rv)) {
    906             _bcm_trident_hg_dlb_deinit(unit);
    907             return rv;
    908         }
    909 
    910         /* Configure Higig DLB port load EWMA weight */
    911         rv = _bcm_trident_hg_dlb_config_set(unit,
    912                 bcmSwitchFabricTrunkDynamicEgressBytesExponent, 0);
    913         if (BCM_FAILURE(rv)) {
    914             _bcm_trident_hg_dlb_deinit(unit);
    915             return rv;
    916         }
    917 
    918         /* Configure Higig DLB port queue size EWMA weight */
    919         rv = _bcm_trident_hg_dlb_config_set(unit,
    920                 bcmSwitchFabricTrunkDynamicQueuedBytesExponent, 0);
    921         if (BCM_FAILURE(rv)) {
    922             _bcm_trident_hg_dlb_deinit(unit);
    923             return rv;
    924         }
    925 
    926         /* Configure Higig DLB port load cap control */
    927         rv = _bcm_trident_hg_dlb_config_set(unit,
    928                 bcmSwitchFabricTrunkDynamicEgressBytesDecreaseReset, 0);
    929         if (BCM_FAILURE(rv)) {
    930             _bcm_trident_hg_dlb_deinit(unit);
    931             return rv;
    932         }
    933 
    934         /* Configure Higig DLB port queue size cap control */
    935         rv = _bcm_trident_hg_dlb_config_set(unit,
    936                 bcmSwitchFabricTrunkDynamicQueuedBytesDecreaseReset, 0);
    937         if (BCM_FAILURE(rv)) {
    938             _bcm_trident_hg_dlb_deinit(unit);
    939             return rv;
    940         }
    941 
    942         /* Configure Higig DLB port queue size thresholds */
    943         rv = _bcm_trident_hg_dlb_qsize_thresholds_set(unit, 0, 0);
    944         if (BCM_FAILURE(rv)) {
    945             _bcm_trident_hg_dlb_deinit(unit);
    946             return rv;
    947         }
    948 
    949         /* Disable link status override by software */
    950         if (soc_mem_is_valid(unit, DLB_HGT_LINK_CONTROLm)) {
    951             rv = soc_mem_clear(unit, DLB_HGT_LINK_CONTROLm, MEM_BLOCK_ALL, 0);
    952         } else {
    953             rv = soc_mem_clear(unit, DLB_HGT_MEMBER_SW_STATEm, MEM_BLOCK_ALL, 0);
    954         }
    955         if (BCM_FAILURE(rv)) {
    956             _bcm_trident_hg_dlb_deinit(unit);
    957             return rv;
    958         }
    959 
    960         /* Disable all HGT DLB groups */
    961         if (SOC_MEM_IS_VALID(unit, HGT_DLB_CONTROLm)) {
    962             rv = soc_mem_clear(unit, HGT_DLB_CONTROLm, MEM_BLOCK_ALL, 0);
    963             if (BCM_FAILURE(rv)) {
    964                 _bcm_trident_hg_dlb_deinit(unit);
    965                 return rv;
    966             }
    967         } else {
    968             rv = soc_mem_clear(unit, DLB_HGT_GROUP_CONTROLm, MEM_BLOCK_ALL, 0);
    969             if (BCM_FAILURE(rv)) {
    970                 _bcm_trident_hg_dlb_deinit(unit);
    971                 return rv;
    972             }
    973         }
    974 
    975 #ifdef BCM_TRIUMPH3_SUPPORT
    976         if (soc_feature(unit, soc_feature_hg_dlb_member_id)) {
    977             int member_id;
    978             dlb_hgt_quality_control_entry_t quality_control_entry;
    979             soc_field_t enable_credit_collect_f;
    980 
    981             /* Clear group membership */
    982             rv = soc_mem_clear(unit, DLB_HGT_GROUP_MEMBERSHIPm, MEM_BLOCK_ALL, 0);
    983             if (BCM_FAILURE(rv)) {
    984                 _bcm_trident_hg_dlb_deinit(unit);
    985                 return rv;
    986             }
    987 
    988             /* Clear port<->member mapping tables */
    989             rv = soc_mem_clear(unit, DLB_HGT_PORT_MEMBER_MAPm, MEM_BLOCK_ALL, 0);
    990             if (BCM_FAILURE(rv)) {
    991                 _bcm_trident_hg_dlb_deinit(unit);
    992                 return rv;
    993             }
    994             rv = soc_mem_clear(unit, DLB_HGT_MEMBER_ATTRIBUTEm, MEM_BLOCK_ALL, 0);
    995             if (BCM_FAILURE(rv)) {
    996                 _bcm_trident_hg_dlb_deinit(unit);
    997                 return rv;
    998             }
    999 
   1000             /* Clear per member threshold scaling factor and 
   1001              * quality measure update control.
   1002              */
   1003             for (member_id = 0;
   1004                     member_id < soc_mem_index_count(unit,
   1005                         DLB_HGT_QUALITY_CONTROLm);
   1006                     member_id++) {
   1007                 rv = READ_DLB_HGT_QUALITY_CONTROLm(unit, MEM_BLOCK_ANY,
   1008                         member_id, &quality_control_entry);
   1009                 if (SOC_FAILURE(rv)) {
   1010                     _bcm_trident_hg_dlb_deinit(unit);
   1011                     return rv;
   1012                 }
   1013                 soc_DLB_HGT_QUALITY_CONTROLm_field32_set(unit,
   1014                         &quality_control_entry, ENABLE_AVG_CALCf, 0);
   1015                 soc_DLB_HGT_QUALITY_CONTROLm_field32_set(unit,
   1016                         &quality_control_entry, ENABLE_QUALITY_UPDATEf, 0);
   1017                 enable_credit_collect_f = soc_mem_field_valid(unit,
   1018                         DLB_HGT_QUALITY_CONTROLm, ENABLE_CREDIT_COLLECTIONf) ?
   1019                        ENABLE_CREDIT_COLLECTIONf : ENB_CREDIT_COLLECTIONf;
   1020                 soc_DLB_HGT_QUALITY_CONTROLm_field32_set(unit,
   1021                         &quality_control_entry, enable_credit_collect_f, 0);
   1022                 soc_DLB_HGT_QUALITY_CONTROLm_field32_set(unit,
   1023                         &quality_control_entry, LOADING_SCALING_FACTORf, 0);
   1024                 soc_DLB_HGT_QUALITY_CONTROLm_field32_set(unit,
   1025                         &quality_control_entry, QSIZE_SCALING_FACTORf, 0);
   1026                 rv = WRITE_DLB_HGT_QUALITY_CONTROLm(unit, MEM_BLOCK_ALL,
   1027                         member_id, &quality_control_entry);
   1028                 if (SOC_FAILURE(rv)) {
   1029                     _bcm_trident_hg_dlb_deinit(unit);
   1030                     return rv;
   1031                 }
   1032             }
   1033         } else
   1034 #endif /* BCM_TRIUMPH3_SUPPORT */
   1035         {
   1036             /* Clear per port threshold scaling factor and 
   1037              * quality measure update control.
   1038              */
   1039             PBMP_ALL_ITER(unit, port) {
   1040                 rv = READ_DLB_HGT_QUANTIZE_CONTROLr(unit, port,
   1041                         &quantize_control_reg);
   1042                 if (BCM_FAILURE(rv)) {
   1043                     _bcm_trident_hg_dlb_deinit(unit);
   1044                     return rv;
   1045                 }
   1046                 soc_reg_field_set(unit, DLB_HGT_QUANTIZE_CONTROLr,
   1047                         &quantize_control_reg,
   1048                         PORT_LOADING_THRESHOLD_SCALING_FACTORf, 0);
   1049                 soc_reg_field_set(unit, DLB_HGT_QUANTIZE_CONTROLr,
   1050                         &quantize_control_reg,
   1051                         PORT_QSIZE_THRESHOLD_SCALING_FACTORf, 0);
   1052                 rv = WRITE_DLB_HGT_QUANTIZE_CONTROLr(unit, port,
   1053                         quantize_control_reg);
   1054                 if (BCM_FAILURE(rv)) {
   1055                     _bcm_trident_hg_dlb_deinit(unit);
   1056                     return rv;
   1057                 }
   1058 
   1059                 rv = READ_DLB_HGT_PORT_QUALITY_MEASURE_UPDATE_CONTROLr(unit,
   1060                         port, &measure_update_control_reg);
   1061                 if (BCM_FAILURE(rv)) {
   1062                     _bcm_trident_hg_dlb_deinit(unit);
   1063                     return rv;
   1064                 }
   1065                 soc_reg_field_set(unit,
   1066                         DLB_HGT_PORT_QUALITY_MEASURE_UPDATE_CONTROLr,
   1067                         &measure_update_control_reg,
   1068                         ENABLE_MEASURE_COLLECTIONf, 0);
   1069                 soc_reg_field_set(unit,
   1070                         DLB_HGT_PORT_QUALITY_MEASURE_UPDATE_CONTROLr,
   1071                         &measure_update_control_reg,
   1072                         ENABLE_MEASURE_AVERAGE_CALCULATIONf, 0);
   1073                 soc_reg_field_set(unit,
   1074                         DLB_HGT_PORT_QUALITY_MEASURE_UPDATE_CONTROLr,
   1075                         &measure_update_control_reg,
   1076                         ENABLE_PORT_QUALITY_UPDATEf, 0);
   1077                 rv = WRITE_DLB_HGT_PORT_QUALITY_MEASURE_UPDATE_CONTROLr(unit,
   1078                         port, measure_update_control_reg);
   1079                 if (BCM_FAILURE(rv)) {
   1080                     _bcm_trident_hg_dlb_deinit(unit);
   1081                     return rv;
   1082                 }
   1083             }
   1084         }
   1085 
   1086         /* Enable DLB HGT refresh */
   1087         /* coverity[result_independent_of_operands] */
   1088         if (SOC_REG_IS_VALID(unit, AUX_ARB_CONTROL_2r)) {
   1089             dlb_refresh_f = soc_reg_field_valid(unit, AUX_ARB_CONTROL_2r,
   1090                                                 DLB_HGT_REFRESH_ENABLEf) ? 
   1091                             DLB_HGT_REFRESH_ENABLEf : DLB_REFRESH_ENABLEf;
   1092             rv = READ_AUX_ARB_CONTROL_2r(unit, &arb_control_reg);
   1093             if (BCM_SUCCESS(rv)) {
   1094                 soc_reg_field_set(unit, AUX_ARB_CONTROL_2r, &arb_control_reg,
   1095                                   dlb_refresh_f, 1);
   1096                 if (soc_reg_field_valid(unit, AUX_ARB_CONTROL_2r,
   1097                                         DLB_HGT_256NS_REFRESH_ENABLEf)) {
   1098                     soc_reg_field_set(unit, AUX_ARB_CONTROL_2r, &arb_control_reg,
   1099                                       DLB_HGT_256NS_REFRESH_ENABLEf, 1);
   1100                 } else if (soc_reg_field_valid(unit, AUX_ARB_CONTROL_2r,
   1101                                                DLB_1US_TICK_ENABLEf)) {
   1102                     soc_reg_field_set(unit, AUX_ARB_CONTROL_2r, &arb_control_reg,
   1103                                       DLB_1US_TICK_ENABLEf, 1);
   1104                 }
   1105                 rv = WRITE_AUX_ARB_CONTROL_2r(unit, arb_control_reg);
   1106             }
   1107             if (BCM_FAILURE(rv)) {
   1108                 _bcm_trident_hg_dlb_deinit(unit);
   1109                 return rv;
   1110             }
   1111         /* coverity[result_independent_of_operands] */
   1112         } else if (SOC_REG_IS_VALID(unit, AUX_ARB_CONTROL_2_64r)) {
   1113             dlb_refresh_f = soc_reg_field_valid(unit, AUX_ARB_CONTROL_2_64r,
   1114                                                 DLB_HGT_REFRESH_ENABLEf) ? 
   1115                             DLB_HGT_REFRESH_ENABLEf : DLB_REFRESH_ENABLEf;
   1116             rv = READ_AUX_ARB_CONTROL_2_64r(unit, &arb_control_reg_64);
   1117             if (BCM_SUCCESS(rv)) {
   1118                 soc_reg64_field32_set(unit, AUX_ARB_CONTROL_2_64r, &arb_control_reg_64,
   1119                                   dlb_refresh_f, 1);
   1120                 if (soc_reg_field_valid(unit, AUX_ARB_CONTROL_2_64r,
   1121                                         DLB_HGT_256NS_REFRESH_ENABLEf)) {
   1122                     soc_reg64_field32_set(unit, AUX_ARB_CONTROL_2_64r, &arb_control_reg_64,
   1123                                       DLB_HGT_256NS_REFRESH_ENABLEf, 1);
   1124                 } else if (soc_reg_field_valid(unit, AUX_ARB_CONTROL_2_64r,
   1125                                                DLB_1US_TICK_ENABLEf)) {
   1126                     soc_reg64_field32_set(unit, AUX_ARB_CONTROL_2_64r, &arb_control_reg_64,
   1127                                       DLB_1US_TICK_ENABLEf, 1);
   1128                 }
   1129                 rv = WRITE_AUX_ARB_CONTROL_2_64r(unit, arb_control_reg_64);
   1130             }
   1131             if (BCM_FAILURE(rv)) {
   1132                 _bcm_trident_hg_dlb_deinit(unit);
   1133                 return rv;
   1134             }
   1135         }
   1136 
   1137 #ifdef BCM_TRIUMPH3_SUPPORT
   1138         if (soc_reg_field_valid(unit, SW2_HW_CONTROLr, ENABLE_HGT_DLBf)) {
   1139             uint32 sw2_hw_control_reg;
   1140 
   1141             rv = READ_SW2_HW_CONTROLr(unit, &sw2_hw_control_reg);
   1142             if (BCM_SUCCESS(rv)) {
   1143                 soc_reg_field_set(unit, SW2_HW_CONTROLr, &sw2_hw_control_reg,
   1144                         ENABLE_HGT_DLBf, 1);
   1145                 rv = WRITE_SW2_HW_CONTROLr(unit, sw2_hw_control_reg);
   1146             }
   1147             if (BCM_FAILURE(rv)) {
   1148                 _bcm_trident_hg_dlb_deinit(unit);
   1149                 return rv;
   1150             }
   1151         }
   1152 #endif /* BCM_TRIUMPH3_SUPPORT */
   1153 
   1154         /* Configure Ethertype eligibility */
   1155 #ifdef BCM_TRIUMPH3_SUPPORT
   1156         if (soc_mem_is_valid(unit, DLB_HGT_ETHERTYPE_ELIGIBILITY_MAPm)) {
   1157             uint32 measure_control_reg;
   1158 
   1159             rv = soc_mem_clear(unit, DLB_HGT_ETHERTYPE_ELIGIBILITY_MAPm,
   1160                     MEM_BLOCK_ALL, 0);
   1161             if (BCM_FAILURE(rv)) {
   1162                 _bcm_trident_hg_dlb_deinit(unit);
   1163                 return rv;
   1164             }
   1165             rv = READ_DLB_HGT_QUALITY_MEASURE_CONTROLr(unit,
   1166                     &measure_control_reg);
   1167             if (SOC_SUCCESS(rv)) {
   1168                 soc_reg_field_set(unit, DLB_HGT_QUALITY_MEASURE_CONTROLr,
   1169                         &measure_control_reg,
   1170                         ETHERTYPE_ELIGIBILITY_CONFIGf, 0);
   1171                 soc_reg_field_set(unit, DLB_HGT_QUALITY_MEASURE_CONTROLr,
   1172                         &measure_control_reg,
   1173                         INNER_OUTER_ETHERTYPE_SELECTIONf, 0);
   1174                 rv = WRITE_DLB_HGT_QUALITY_MEASURE_CONTROLr(unit,
   1175                         measure_control_reg);
   1176             }
   1177             if (BCM_FAILURE(rv)) {
   1178                 _bcm_trident_hg_dlb_deinit(unit);
   1179                 return rv;
   1180             }
   1181         }
   1182 #endif /* BCM_TRIUMPH3_SUPPORT */
   1183 
   1184     }
   1185 
   1186     return rv;
   1187 }
   1188 
   1189 /*
   1190  * Function:
   1191  *      _bcm_trident_hg_trunk_override_profile_deinit
   1192  * Purpose:
   1193  *      Deallocate _trident_hg_trunk_override_profile
   1194  * Parameters:
   1195  *      unit - (IN)SOC unit number. 
   1196  * Returns:
   1197  *      BCM_X_XXX
   1198  */
   1199 STATIC void
   1200 _bcm_trident_hg_trunk_override_profile_deinit(int unit)
   1201 {
   1202     if (_trident_hg_trunk_override_profile[unit]) {
   1203         (void)soc_profile_mem_destroy(unit, _trident_hg_trunk_override_profile[unit]);
   1204         sal_free(_trident_hg_trunk_override_profile[unit]);
   1205         _trident_hg_trunk_override_profile[unit] = NULL;
   1206     }
   1207 }
   1208 
   1209 /*
   1210  * Function:
   1211  *      _bcm_trident_hg_trunk_override_profile_init
   1212  * Purpose:
   1213  *      Allocate and initialize _trident_hg_trunk_override_profile
   1214  * Parameters:
   1215  *      unit - (IN)SOC unit number. 
   1216  * Returns:
   1217  *      BCM_X_XXX
   1218  */
   1219 STATIC int
   1220 _bcm_trident_hg_trunk_override_profile_init(int unit)
   1221 {
   1222     soc_mem_t mem;
   1223     int       entry_words;
   1224     void      *entry_ptr;
   1225     int       ref_count;
   1226     uint32    index;
   1227     int       i;
   1228     uint32    profile_ptr;
   1229     vlan_tab_entry_t vlan_tab_entry;
   1230     l2mc_entry_t l2mc_entry;
   1231     ipmc_entry_t ipmc_entry;
   1232     ifp_redirection_profile_entry_t ifp_redirection_profile_entry;
   1233 
   1234     if (_trident_hg_trunk_override_profile[unit] == NULL) {
   1235         _trident_hg_trunk_override_profile[unit] = 
   1236             sal_alloc(sizeof(soc_profile_mem_t), "HG Trunk Override Profile Mem");
   1237         if (_trident_hg_trunk_override_profile[unit] == NULL) {
   1238             return BCM_E_MEMORY;
   1239         }
   1240     } else {
   1241         soc_profile_mem_destroy(unit, _trident_hg_trunk_override_profile[unit]);
   1242     }
   1243     soc_profile_mem_t_init(_trident_hg_trunk_override_profile[unit]);
   1244 
   1245     /* Create profile table cache (or re-init if it already exists) */
   1246     mem = ING_HIGIG_TRUNK_OVERRIDE_PROFILEm;
   1247     entry_words = sizeof(ing_higig_trunk_override_profile_entry_t) / sizeof(uint32);
   1248     SOC_IF_ERROR_RETURN
   1249         (soc_profile_mem_create(unit, &mem, &entry_words, 1,
   1250                                 _trident_hg_trunk_override_profile[unit]));
   1251 
   1252     if (!SOC_WARM_BOOT(unit)) {
   1253         /* By default, VLAN, L2MC, IPMC, and IFP Redirection Profile tables' Higig
   1254          * trunk override profile pointer is 0. Add a profile at index 0 of
   1255          * ING_HIGIG_TRUNK_OVERRIDE_PROFILE table with the reference count equal
   1256          * to the number of entries in VLAN, L2MC, IPMC, and IFP Redirection
   1257          * Profile tables.
   1258          */
   1259         entry_ptr = soc_mem_entry_null(unit, ING_HIGIG_TRUNK_OVERRIDE_PROFILEm);
   1260         SOC_IF_ERROR_RETURN
   1261             (soc_profile_mem_add(unit, _trident_hg_trunk_override_profile[unit],
   1262                                  &entry_ptr, 1, &index));
   1263         ref_count = soc_mem_index_count(unit, VLAN_TABm);
   1264         ref_count += soc_mem_index_count(unit, L2MCm);
   1265         ref_count += soc_mem_index_count(unit, L3_IPMCm);
   1266         ref_count += soc_mem_index_count(unit, IFP_REDIRECTION_PROFILEm);
   1267         SOC_PROFILE_MEM_REFERENCE(unit, _trident_hg_trunk_override_profile[unit],
   1268                 index, ref_count - 1);
   1269     } else { /* Warm boot, recover reference counts and entries_per_set */
   1270 
   1271         /* Recover from VLAN_TAB */
   1272         for (i = soc_mem_index_min(unit, VLAN_TABm);
   1273              i <= soc_mem_index_max(unit, VLAN_TABm);
   1274              i++) {
   1275             SOC_IF_ERROR_RETURN
   1276                 (READ_VLAN_TABm(unit, MEM_BLOCK_ANY, i, &vlan_tab_entry));
   1277             profile_ptr = soc_VLAN_TABm_field32_get(unit, &vlan_tab_entry,
   1278                     HIGIG_TRUNK_OVERRIDE_PROFILE_PTRf);
   1279             SOC_PROFILE_MEM_REFERENCE(unit,
   1280                     _trident_hg_trunk_override_profile[unit],
   1281                     profile_ptr, 1);
   1282             SOC_PROFILE_MEM_ENTRIES_PER_SET(unit,
   1283                     _trident_hg_trunk_override_profile[unit],
   1284                     profile_ptr, 1);
   1285         }
   1286 
   1287         /* Recover from L2MC */
   1288         for (i = soc_mem_index_min(unit, L2MCm);
   1289              i <= soc_mem_index_max(unit, L2MCm);
   1290              i++) {
   1291             SOC_IF_ERROR_RETURN
   1292                 (READ_L2MCm(unit, MEM_BLOCK_ANY, i, &l2mc_entry));
   1293             profile_ptr = soc_L2MCm_field32_get(unit, &l2mc_entry,
   1294                     HIGIG_TRUNK_OVERRIDE_PROFILE_PTRf);
   1295             SOC_PROFILE_MEM_REFERENCE(unit,
   1296                     _trident_hg_trunk_override_profile[unit],
   1297                     profile_ptr, 1);
   1298             SOC_PROFILE_MEM_ENTRIES_PER_SET(unit,
   1299                     _trident_hg_trunk_override_profile[unit],
   1300                     profile_ptr, 1);
   1301         }
   1302 
   1303         /* Recover from IPMC */
   1304         for (i = soc_mem_index_min(unit, L3_IPMCm);
   1305              i <= soc_mem_index_max(unit, L3_IPMCm);
   1306              i++) {
   1307             SOC_IF_ERROR_RETURN
   1308                 (READ_L3_IPMCm(unit, MEM_BLOCK_ANY, i, &ipmc_entry));
   1309             profile_ptr = soc_L3_IPMCm_field32_get(unit, &ipmc_entry,
   1310                     HIGIG_TRUNK_OVERRIDE_PROFILE_PTRf);
   1311             SOC_PROFILE_MEM_REFERENCE(unit,
   1312                     _trident_hg_trunk_override_profile[unit],
   1313                     profile_ptr, 1);
   1314             SOC_PROFILE_MEM_ENTRIES_PER_SET(unit,
   1315                     _trident_hg_trunk_override_profile[unit],
   1316                     profile_ptr, 1);
   1317         }
   1318 
   1319         /* Recover from IFP_REDIRECTION_PROFILE */
   1320         for (i = soc_mem_index_min(unit, IFP_REDIRECTION_PROFILEm);
   1321              i <= soc_mem_index_max(unit, IFP_REDIRECTION_PROFILEm);
   1322              i++) {
   1323             SOC_IF_ERROR_RETURN
   1324                 (READ_IFP_REDIRECTION_PROFILEm(unit, MEM_BLOCK_ANY, i,
   1325                                                &ifp_redirection_profile_entry));
   1326             profile_ptr = soc_IFP_REDIRECTION_PROFILEm_field32_get(unit,
   1327                     &ifp_redirection_profile_entry,
   1328                     HIGIG_TRUNK_OVERRIDE_PROFILE_PTRf);
   1329             SOC_PROFILE_MEM_REFERENCE(unit,
   1330                     _trident_hg_trunk_override_profile[unit],
   1331                     profile_ptr, 1);
   1332             SOC_PROFILE_MEM_ENTRIES_PER_SET(unit,
   1333                     _trident_hg_trunk_override_profile[unit],
   1334                     profile_ptr, 1);
   1335         }
   1336     }
   1337 
   1338     return BCM_E_NONE;
   1339 }
   1340 
   1341 /*
   1342  * Function:
   1343  *      _bcm_trident_trunk_hwfailover_deinit
   1344  * Purpose:
   1345  *      Deallocate _trident_trunk_hwfail
   1346  * Parameters:
   1347  *      unit - (IN)SOC unit number. 
   1348  * Returns:
   1349  *      None
   1350  */
   1351 STATIC void
   1352 _bcm_trident_trunk_hwfailover_deinit(int unit)
   1353 {
   1354     int trunk_num_groups;
   1355     int i;
   1356 
   1357     if (_trident_trunk_hwfail[unit]) {
   1358         if (_trident_trunk_hwfail[unit]->hw_tinfo) {
   1359             trunk_num_groups = soc_mem_index_count(unit, TRUNK_GROUPm) +
   1360                 soc_mem_index_count(unit, HG_TRUNK_GROUPm);
   1361             for (i = 0; i < trunk_num_groups; i++) {
   1362                 if (_trident_trunk_hwfail[unit]->hw_tinfo[i].modport) {
   1363                     sal_free(_trident_trunk_hwfail[unit]->hw_tinfo[i].modport);
   1364                     _trident_trunk_hwfail[unit]->hw_tinfo[i].modport = NULL;
   1365                 }
   1366                 if (_trident_trunk_hwfail[unit]->hw_tinfo[i].psc) {
   1367                     sal_free(_trident_trunk_hwfail[unit]->hw_tinfo[i].psc);
   1368                     _trident_trunk_hwfail[unit]->hw_tinfo[i].psc = NULL;
   1369                 }
   1370                 if (_trident_trunk_hwfail[unit]->hw_tinfo[i].flags) {
   1371                     sal_free(_trident_trunk_hwfail[unit]->hw_tinfo[i].flags);
   1372                     _trident_trunk_hwfail[unit]->hw_tinfo[i].flags = NULL;
   1373                 }
   1374             }
   1375             sal_free(_trident_trunk_hwfail[unit]->hw_tinfo);
   1376             _trident_trunk_hwfail[unit]->hw_tinfo = NULL;
   1377         }
   1378         sal_free(_trident_trunk_hwfail[unit]);
   1379         _trident_trunk_hwfail[unit] = NULL;
   1380     }
   1381 }
   1382 
   1383 /*
   1384  * Function:
   1385  *      _bcm_trident_trunk_hwfailover_init
   1386  * Purpose:
   1387  *      Allocate and initialize _trident_trunk_hwfail
   1388  * Parameters:
   1389  *      unit - (IN)SOC unit number. 
   1390  * Returns:
   1391  *      BCM_X_XXX
   1392  */
   1393 STATIC int
   1394 _bcm_trident_trunk_hwfailover_init(int unit)
   1395 {
   1396     int trunk_num_groups;
   1397 
   1398     if (_trident_trunk_hwfail[unit] == NULL) {
   1399         _trident_trunk_hwfail[unit] = sal_alloc(sizeof(_trident_trunk_hwfail_t), 
   1400                 "_trident_trunk_hwfail");
   1401         if (_trident_trunk_hwfail[unit] == NULL) {
   1402             return BCM_E_MEMORY;
   1403         }
   1404     }
   1405     sal_memset(_trident_trunk_hwfail[unit], 0, sizeof(_trident_trunk_hwfail_t));
   1406 
   1407     trunk_num_groups = soc_mem_index_count(unit, TRUNK_GROUPm) +
   1408                        soc_mem_index_count(unit, HG_TRUNK_GROUPm);
   1409     if (_trident_trunk_hwfail[unit]->hw_tinfo == NULL) {
   1410         _trident_trunk_hwfail[unit]->hw_tinfo =
   1411             sal_alloc(sizeof(_trident_hw_tinfo_t) * trunk_num_groups,
   1412                     "_trident_trunk_hwfail_hw_tinfo");
   1413         if (_trident_trunk_hwfail[unit]->hw_tinfo == NULL) {
   1414             _bcm_trident_trunk_hwfailover_deinit(unit);
   1415             return BCM_E_MEMORY;
   1416         }
   1417     }
   1418     sal_memset(_trident_trunk_hwfail[unit]->hw_tinfo, 0, 
   1419                sizeof(_trident_hw_tinfo_t) * trunk_num_groups);
   1420                                                                                 
   1421     /* Note: The maximum number of member ports in a trunk group is 256 in Trident.
   1422      *       But it would be quite wasteful to allocate 256 entries to each 
   1423      *       _trident_trunk_hwfail[unit]->hw_tinfo[x].modport/psc/flags arrays.
   1424      *       These arrays will be allocated as member ports are added to trunk group.
   1425      */
   1426 
   1427     return BCM_E_NONE;
   1428 }
   1429 
   1430 /*
   1431  * Function:
   1432  *      _bcm_trident_trunk_swfailover_deinit
   1433  * Purpose:
   1434  *      Deallocate _trident_trunk_swfail
   1435  * Parameters:
   1436  *      unit - (IN)SOC unit number. 
   1437  * Returns:
   1438  *      None
   1439  */
   1440 STATIC void
   1441 _bcm_trident_trunk_swfailover_deinit(int unit)
   1442 {
   1443     int trunk_num_groups;
   1444     int i;
   1445 
   1446     if (_trident_trunk_swfail[unit]) {
   1447         if (_trident_trunk_swfail[unit]->tinfo) {
   1448             trunk_num_groups = soc_mem_index_count(unit, TRUNK_GROUPm) +
   1449                 soc_mem_index_count(unit, HG_TRUNK_GROUPm);
   1450             for (i = 0; i < trunk_num_groups; i++) {
   1451                 if (_trident_trunk_swfail[unit]->tinfo[i].modport) {
   1452                     sal_free(_trident_trunk_swfail[unit]->tinfo[i].modport);
   1453                     _trident_trunk_swfail[unit]->tinfo[i].modport = NULL;
   1454                 }
   1455             }
   1456             sal_free(_trident_trunk_swfail[unit]->tinfo);
   1457             _trident_trunk_swfail[unit]->tinfo = NULL;
   1458         }
   1459         sal_free(_trident_trunk_swfail[unit]);
   1460         _trident_trunk_swfail[unit] = NULL;
   1461     }
   1462 }
   1463 
   1464 /*
   1465  * Function:
   1466  *      _bcm_trident_trunk_swfailover_init
   1467  * Purpose:
   1468  *      Allocate and initialize _trident_trunk_swfail
   1469  * Parameters:
   1470  *      unit - (IN)SOC unit number. 
   1471  * Returns:
   1472  *      BCM_X_XXX
   1473  */
   1474 STATIC int
   1475 _bcm_trident_trunk_swfailover_init(int unit)
   1476 {
   1477     int trunk_num_groups;
   1478 
   1479     if (_trident_trunk_swfail[unit] == NULL) {
   1480         _trident_trunk_swfail[unit] = sal_alloc(sizeof(_trident_trunk_swfail_t), 
   1481                 "_trident_trunk_swfail");
   1482         if (_trident_trunk_swfail[unit] == NULL) {
   1483             return BCM_E_MEMORY;
   1484         }
   1485     }
   1486     sal_memset(_trident_trunk_swfail[unit], 0, sizeof(_trident_trunk_swfail_t));
   1487 
   1488     trunk_num_groups = soc_mem_index_count(unit, TRUNK_GROUPm) +
   1489                        soc_mem_index_count(unit, HG_TRUNK_GROUPm);
   1490     if (_trident_trunk_swfail[unit]->tinfo == NULL) {
   1491         _trident_trunk_swfail[unit]->tinfo =
   1492             sal_alloc(sizeof(_trident_tinfo_t) * trunk_num_groups,
   1493                     "_trident_trunk_swfail_tinfo");
   1494         if (_trident_trunk_swfail[unit]->tinfo == NULL) {
   1495             _bcm_trident_trunk_swfailover_deinit(unit);
   1496             return BCM_E_MEMORY;
   1497         }
   1498     }
   1499     sal_memset(_trident_trunk_swfail[unit]->tinfo, 0, 
   1500                sizeof(_trident_tinfo_t) * trunk_num_groups);
   1501                                                                                 
   1502     /* Note: The maximum number of member ports in a trunk group is 256 in Trident.
   1503      *       But it would be quite wasteful to allocate 256 entries to each 
   1504      *       _trident_trunk_swfail[unit]->tinfo[x].modport array. The modport
   1505      *       array will be allocated as member ports are added to trunk group.
   1506      */
   1507 
   1508     return BCM_E_NONE;
   1509 }
   1510 
   1511 /*
   1512  * Function:
   1513  *      _bcm_trident_trunk_deinit
   1514  * Purpose:
   1515  *      Deallocate global data structures
   1516  * Parameters:
   1517  *      unit - (IN)SOC unit number.
   1518  * Returns:
   1519  *      BCM_E_xxx
   1520  */
   1521 void
   1522 _bcm_trident_trunk_deinit(int unit)
   1523 {
   1524     _bcm_trident_trunk_member_info_deinit(unit);
   1525 
   1526     _bcm_trident_trunk_mod_port_map_deinit(unit);
   1527 
   1528     _bcm_trident_trunk_member_bk_deinit(unit);
   1529 
   1530     if (soc_feature(unit, soc_feature_hg_dlb) &&
   1531         !soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) {
   1532         _bcm_trident_hg_dlb_deinit(unit);
   1533     }
   1534 
   1535 #ifdef BCM_TRIUMPH3_SUPPORT
   1536     if (soc_feature(unit, soc_feature_lag_dlb) &&
   1537         !soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) {
   1538         bcm_tr3_lag_dlb_deinit(unit);
   1539     }
   1540 #endif /* BCM_TRIUMPH3_SUPPORT */
   1541 
   1542 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT)
   1543     if (soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) {
   1544         bcm_th2_hgt_lag_dlb_deinit(unit);
   1545     }
   1546 #endif /* BCM_TOMAHAWK2_SUPPORT */
   1547 
   1548     _bcm_trident_hg_trunk_override_profile_deinit(unit);
   1549 
   1550     _bcm_trident_trunk_hwfailover_deinit(unit);
   1551 
   1552     _bcm_trident_trunk_swfailover_deinit(unit);
   1553 
   1554 #ifdef BCM_TRIDENT2_SUPPORT
   1555     if (soc_feature(unit, soc_feature_hg_resilient_hash)) {
   1556         bcm_td2_hg_rh_deinit(unit);
   1557     }
   1558     if (soc_feature(unit, soc_feature_lag_resilient_hash)) {
   1559         bcm_td2_lag_rh_deinit(unit);
   1560     }
   1561 #endif /* BCM_TRIDENT2_SUPPORT */
   1562 
   1563 }
   1564 
   1565 /*
   1566  * Function:
   1567  *      _bcm_trident_trunk_init
   1568  * Purpose:
   1569  *      Initialize global data structures
   1570  * Parameters:
   1571  *      unit - (IN)SOC unit number.
   1572  * Returns:
   1573  *      BCM_E_xxx
   1574  */
   1575 int
   1576 _bcm_trident_trunk_init(int unit)
   1577 {
   1578     int rv;
   1579 
   1580     _bcm_trident_trunk_deinit(unit);
   1581 
   1582     rv = _bcm_trident_trunk_member_info_init(unit);
   1583     if (BCM_FAILURE(rv)) {
   1584         _bcm_trident_trunk_deinit(unit);
   1585         return rv;
   1586     }
   1587 
   1588     rv = _bcm_trident_trunk_mod_port_map_init(unit);
   1589     if (BCM_FAILURE(rv)) {
   1590         _bcm_trident_trunk_deinit(unit);
   1591         return rv;
   1592     }
   1593 
   1594     rv = _bcm_trident_trunk_member_bk_init(unit);
   1595     if (BCM_FAILURE(rv)) {
   1596         _bcm_trident_trunk_deinit(unit);
   1597         return rv;
   1598     }
   1599 
   1600     if (soc_feature(unit, soc_feature_hg_dlb) &&
   1601         !soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) {
   1602         rv = _bcm_trident_hg_dlb_init(unit);
   1603         if (BCM_FAILURE(rv)) {
   1604             _bcm_trident_trunk_deinit(unit);
   1605             return rv;
   1606         }
   1607     }
   1608 
   1609 #ifdef BCM_TRIUMPH3_SUPPORT
   1610     if (soc_feature(unit, soc_feature_lag_dlb) &&
   1611         !soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) {
   1612         rv = bcm_tr3_lag_dlb_init(unit);
   1613         if (BCM_FAILURE(rv)) {
   1614             _bcm_trident_trunk_deinit(unit);
   1615             return rv;
   1616         }
   1617     }
   1618 #endif /* BCM_TRIUMPH3_SUPPORT */
   1619 
   1620 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT)
   1621     if (soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) {
   1622         rv = bcm_th2_hgt_lag_dlb_init(unit);
   1623         if (BCM_FAILURE(rv)) {
   1624             bcm_th2_hgt_lag_dlb_deinit(unit);
   1625             return rv;
   1626         }
   1627     }
   1628 #endif /* BCM_TOMAHAWK2_SUPPORT */
   1629 
   1630     rv = _bcm_trident_hg_trunk_override_profile_init(unit);
   1631     if (BCM_FAILURE(rv)) {
   1632         _bcm_trident_trunk_deinit(unit);
   1633         return rv;
   1634     }
   1635 
   1636     rv = _bcm_trident_trunk_hwfailover_init(unit);
   1637     if (BCM_FAILURE(rv)) {
   1638         _bcm_trident_trunk_deinit(unit);
   1639         return rv;
   1640     }
   1641 
   1642     rv = _bcm_trident_trunk_swfailover_init(unit);
   1643     if (BCM_FAILURE(rv)) {
   1644         _bcm_trident_trunk_deinit(unit);
   1645         return rv;
   1646     }
   1647 
   1648 #ifdef BCM_TRIDENT2_SUPPORT
   1649     if (soc_feature(unit, soc_feature_hg_resilient_hash)) {
   1650         rv = bcm_td2_hg_rh_init(unit);
   1651         if (BCM_FAILURE(rv)) {
   1652             _bcm_trident_trunk_deinit(unit);
   1653             return rv;
   1654         }
   1655     }
   1656 
   1657     if (soc_feature(unit, soc_feature_lag_resilient_hash)) {
   1658         rv = bcm_td2_lag_rh_init(unit);
   1659         if (BCM_FAILURE(rv)) {
   1660             _bcm_trident_trunk_deinit(unit);
   1661             return rv;
   1662         }
   1663     }
   1664 #endif /* BCM_TRIDENT2_SUPPORT */
   1665 
   1666     return BCM_E_NONE;
   1667 }
   1668 
   1669 /* ----------------------------------------------------------------------------- 
   1670  *
   1671  * Routines for hardware failover
   1672  *
   1673  * ----------------------------------------------------------------------------- 
   1674  */
   1675 
   1676 static soc_field_t _hg_trunk_failover_portf[8] = {
   1677     PORT0f, PORT1f, PORT2f, PORT3f,
   1678     PORT4f, PORT5f, PORT6f, PORT7f
   1679 };
   1680 
   1681 
   1682 #if defined(BCM_KATANA2_SUPPORT)
   1683 static soc_field_t _hg_trunk_failover_pp_portf[16]= {
   1684     PP_PORT0f, PP_PORT1f, PP_PORT2f, PP_PORT3f,
   1685     PP_PORT4f, PP_PORT5f, PP_PORT6f, PP_PORT7f,
   1686     PP_PORT8f, PP_PORT9f, PP_PORT10f, PP_PORT11f,
   1687     PP_PORT12f, PP_PORT13f, PP_PORT14f, PP_PORT15f
   1688 };
   1689 static soc_field_t _hg_trunk_failover_physical_portf[16]= {
   1690     PHYSICAL_PORT0f, PHYSICAL_PORT1f, PHYSICAL_PORT2f, PHYSICAL_PORT3f,
   1691     PHYSICAL_PORT4f, PHYSICAL_PORT5f, PHYSICAL_PORT6f, PHYSICAL_PORT7f,
   1692     PHYSICAL_PORT8f, PHYSICAL_PORT9f, PHYSICAL_PORT10f, PHYSICAL_PORT11f,
   1693     PHYSICAL_PORT12f, PHYSICAL_PORT13f, PHYSICAL_PORT14f, PHYSICAL_PORT15f
   1694 };
   1695 #endif /* defined(BCM_KATANA2_SUPPORT) */
   1696 
   1697 
   1698 /*
   1699  * Function:
   1700  *      _bcm_trident_trunk_hwfailover_hg_write
   1701  * Purpose:
   1702  *      Set Higig trunk hardware failover config.
   1703  * Parameters:
   1704  *      unit     - (IN) SOC unit number. 
   1705  *      failport - (IN) Fail port.
   1706  *      rtag     - (IN) Port selection criteria for failover port list.
   1707  *      hw_count - (IN) Number of ports in failover port list.
   1708  *      ftp      - (IN) Pointer to failover port list.
   1709  * Returns:
   1710  *      BCM_E_xxx
   1711  */
   1712 STATIC int
   1713 _bcm_trident_trunk_hwfailover_hg_write(int unit,
   1714         bcm_port_t failport, int rtag,
   1715         int hw_count, bcm_port_t *ftp)
   1716 {
   1717     hg_trunk_failover_set_entry_t     fail_entry;
   1718     hg_trunk_failover_enable_entry_t  failover_enable_entry;
   1719     int           ix;
   1720     bcm_pbmp_t    fail_ports;
   1721     int    failover_max_portcnt;
   1722     
   1723     failover_max_portcnt = 1 << soc_mem_field_length(unit,
   1724                 HG_TRUNK_FAILOVER_SETm, FAILOVER_SET_SIZEf);
   1725 
   1726     sal_memset(&fail_entry, 0, sizeof(fail_entry));
   1727 
   1728     if (hw_count) { /* Enabling HG trunk failover */
   1729         soc_HG_TRUNK_FAILOVER_SETm_field32_set(unit, &fail_entry,
   1730                 FAILOVER_SET_SIZEf, hw_count - 1);
   1731         soc_HG_TRUNK_FAILOVER_SETm_field32_set(unit, &fail_entry,
   1732                 RTAGf, rtag);
   1733 
   1734         for (ix = 0; ix < failover_max_portcnt; ix++) {
   1735 #if defined(BCM_KATANA2_SUPPORT)
   1736             if (SOC_IS_KATANA2(unit)) {
   1737                 soc_HG_TRUNK_FAILOVER_SETm_field32_set(unit, &fail_entry,
   1738                         _hg_trunk_failover_pp_portf[ix], ftp[ix % hw_count]);
   1739                 soc_HG_TRUNK_FAILOVER_SETm_field32_set(unit, &fail_entry,
   1740                         _hg_trunk_failover_physical_portf[ix], ftp[ix % hw_count]);
   1741 
   1742             } else
   1743 #endif /*  (defined(BCM_KATANA2_SUPPORT)  */
   1744             { 
   1745                 soc_HG_TRUNK_FAILOVER_SETm_field32_set(unit, &fail_entry,
   1746                         _hg_trunk_failover_portf[ix], ftp[ix % hw_count]);
   1747             }
   1748         }
   1749         SOC_IF_ERROR_RETURN
   1750             (WRITE_HG_TRUNK_FAILOVER_SETm(unit, MEM_BLOCK_ALL, failport,
   1751                                           &fail_entry));
   1752     }
   1753 
   1754     /* Update HG trunk mode selection bitmap */
   1755 
   1756     SOC_IF_ERROR_RETURN
   1757         (READ_HG_TRUNK_FAILOVER_ENABLEm(unit, MEM_BLOCK_ANY, 0,
   1758                                         &failover_enable_entry));
   1759     SOC_PBMP_CLEAR(fail_ports);
   1760     soc_mem_pbmp_field_get(unit, HG_TRUNK_FAILOVER_ENABLEm,
   1761             &failover_enable_entry, BITMAPf, &fail_ports);
   1762 
   1763     if (hw_count) {
   1764         SOC_PBMP_PORT_ADD(fail_ports, failport);
   1765     } else {
   1766         SOC_PBMP_PORT_REMOVE(fail_ports, failport);
   1767     }
   1768 
   1769     soc_mem_pbmp_field_set(unit, HG_TRUNK_FAILOVER_ENABLEm,
   1770             &failover_enable_entry, BITMAPf, &fail_ports);
   1771 
   1772     SOC_IF_ERROR_RETURN
   1773         (WRITE_HG_TRUNK_FAILOVER_ENABLEm(unit, MEM_BLOCK_ALL, 0,
   1774                                          &failover_enable_entry));
   1775 
   1776     return BCM_E_NONE;
   1777 }
   1778 
   1779 /*
   1780  * Function:
   1781  *      _bcm_trident_trunk_hwfailover_hg_read
   1782  * Purpose:
   1783  *      Get trunk hardware failover config.
   1784  * Parameters:
   1785  *      unit     - (IN) SOC unit number. 
   1786  *      failport - (IN) Port ID of the fail port.
   1787  *      array_size  - (IN) Max number of ports in failover port list.
   1788  *      rtag        - (OUT) Pointer to failover rtag.
   1789  *      ftp         - (OUT) Pointer to port IDs in failover port list.
   1790  *      ftm         - (OUT) Pointer to module IDs in failover port list.
   1791  *      array_count - (OUT) Number of ports in failover port list.
   1792  * Returns:
   1793  *      BCM_E_xxx
   1794  */
   1795 STATIC int
   1796 _bcm_trident_trunk_hwfailover_hg_read(int unit,
   1797         bcm_port_t failport, int array_size,
   1798         int *rtag, bcm_port_t *ftp, bcm_module_t *ftm,
   1799         int *array_count)
   1800 {
   1801     hg_trunk_failover_enable_entry_t  failover_enable_entry;
   1802     hg_trunk_failover_set_entry_t     fail_entry;
   1803     bcm_pbmp_t    fail_ports;
   1804     int           ix, hw_count;
   1805 
   1806     SOC_IF_ERROR_RETURN
   1807         (READ_HG_TRUNK_FAILOVER_ENABLEm(unit, MEM_BLOCK_ANY, 0,
   1808                                         &failover_enable_entry));
   1809     SOC_PBMP_CLEAR(fail_ports);
   1810     soc_mem_pbmp_field_get(unit, HG_TRUNK_FAILOVER_ENABLEm,
   1811             &failover_enable_entry, BITMAPf, &fail_ports);
   1812 
   1813     if (SOC_PBMP_MEMBER(fail_ports, failport)) {
   1814         SOC_IF_ERROR_RETURN
   1815             (READ_HG_TRUNK_FAILOVER_SETm(unit, MEM_BLOCK_ALL, failport,
   1816                                          &fail_entry));
   1817         hw_count = 1 + soc_mem_field32_get(unit, HG_TRUNK_FAILOVER_SETm,
   1818                 &fail_entry, FAILOVER_SET_SIZEf);
   1819         if ((hw_count > array_size) && (array_size != 0)) {
   1820             hw_count = array_size;
   1821         }
   1822         for (ix = 0; ix < hw_count; ix++) {
   1823             if (NULL != ftm) {
   1824                 ftm[ix] = 0;
   1825             }
   1826             if (NULL != ftp) {
   1827 #if defined(BCM_KATANA2_SUPPORT)
   1828                 if (SOC_IS_KATANA2(unit)) {
   1829                     ftp[ix] = soc_mem_field32_get(unit, HG_TRUNK_FAILOVER_SETm,
   1830                             &fail_entry,
   1831                             _hg_trunk_failover_pp_portf[ix]);
   1832                     ftp[ix] = soc_mem_field32_get(unit, HG_TRUNK_FAILOVER_SETm,
   1833                             &fail_entry,
   1834                             _hg_trunk_failover_physical_portf[ix]);
   1835                 } else
   1836 #endif /*  (defined(BCM_KATANA2_SUPPORT)  */
   1837                 { 
   1838                     ftp[ix] = soc_mem_field32_get(unit, HG_TRUNK_FAILOVER_SETm,
   1839                             &fail_entry,
   1840                             _hg_trunk_failover_portf[ix]);
   1841                 }
   1842             }
   1843         }
   1844         if (NULL != array_count) {
   1845             *array_count = hw_count;
   1846         }
   1847         if (NULL != rtag) {
   1848             *rtag = soc_mem_field32_get(unit, HG_TRUNK_FAILOVER_SETm,
   1849                                         &fail_entry, RTAGf);
   1850         }
   1851     } else {
   1852         if (NULL != array_count) {
   1853             *array_count = 0;
   1854         }
   1855         if (NULL != rtag) {
   1856             *rtag = 0;
   1857         }
   1858     }
   1859     return BCM_E_NONE;
   1860 }
   1861 
   1862 static soc_field_t _trunk_failover_portf[8] = {
   1863     PORT0f, PORT1f, PORT2f, PORT3f,
   1864     PORT4f, PORT5f, PORT6f, PORT7f
   1865 };
   1866 
   1867 static soc_field_t _trunk_failover_modulef[8] = {
   1868     MODULE0f, MODULE1f, MODULE2f, MODULE3f,
   1869     MODULE4f, MODULE5f, MODULE6f, MODULE7f
   1870 };
   1871 
   1872 /*
   1873  * Function:
   1874  *      _bcm_trident_trunk_hwfailover_write
   1875  * Purpose:
   1876  *      Set front panel trunk hardware failover config.
   1877  * Parameters:
   1878  *      unit     - (IN) SOC unit number. 
   1879  *      failport - (IN) Fail port.
   1880  *      rtag     - (IN) Port selection criteria for failover port list.
   1881  *      hw_count - (IN) Number of ports in failover port list.
   1882  *      ftp      - (IN) Pointer to failover port list port ID.
   1883  *      ftm      - (IN) Pointer to failover port list module ID.
   1884  * Returns:
   1885  *      BCM_E_xxx
   1886  */
   1887 STATIC int
   1888 _bcm_trident_trunk_hwfailover_write(int unit,
   1889         bcm_port_t failport, int rtag,
   1890         int hw_count, bcm_port_t *ftp, bcm_module_t *ftm)
   1891 {
   1892     port_lag_failover_set_entry_t  fail_entry;
   1893     uint64 val64;
   1894     int    ix, mirror_enable;
   1895     int    failover_max_portcnt;
   1896     soc_reg_t lag_failover_status_reg;
   1897     soc_reg_t lag_failover_config_reg;
   1898     int    old_failover_en, new_failover_en;
   1899     int    old_link_status_sel, new_link_status_sel;
   1900     int    old_reset_flow_control, new_reset_flow_control;
   1901     int    failover_status;
   1902 
   1903     if (SOC_USE_PORTCTRL(unit)) {
   1904         BCM_IF_ERROR_RETURN
   1905             (bcmi_esw_portctrl_hwfailover_status_get(unit, failport,
   1906                                                      &failover_status));
   1907     } else {
   1908         lag_failover_status_reg = SOC_REG_IS_VALID(unit, LAG_FAILOVER_STATUSr) ?
   1909                   LAG_FAILOVER_STATUSr: IS_CL_PORT(unit, failport) ? 
   1910                   CLMAC_LAG_FAILOVER_STATUSr : XLMAC_LAG_FAILOVER_STATUSr;
   1911         SOC_IF_ERROR_RETURN
   1912             (soc_reg_get(unit, lag_failover_status_reg, failport, 0, &val64));
   1913 
   1914         failover_status = soc_reg64_field32_get(unit, lag_failover_status_reg, 
   1915                                                 val64, LAG_FAILOVER_LOOPBACKf);
   1916     }
   1917 
   1918     if (failover_status) {
   1919         /*
   1920          * Already in failover mode.  Do not change HW settings!
   1921          * This should be dealt with as part of the port link processing.
   1922          */
   1923         if (hw_count == 0) {
   1924             /* Notify linkscan of port removal from trunk */
   1925             BCM_IF_ERROR_RETURN
   1926                 (_bcm_esw_link_failover_set(unit, failport, FALSE));
   1927             return BCM_E_NONE;
   1928         } else {
   1929             /* Failed port has not yet been removed from the trunk 
   1930                -- do not change the failover configuration */
   1931             return BCM_E_NONE;
   1932         }
   1933     }
   1934 
   1935     if (hw_count) { /* Enabling trunk failover */
   1936         /* We must be in directed mirroring mode to use this feature */
   1937         BCM_IF_ERROR_RETURN
   1938             (bcm_esw_switch_control_get(unit, bcmSwitchDirectedMirroring,
   1939                                         &mirror_enable));
   1940         if (!mirror_enable) {
   1941             return BCM_E_CONFIG;
   1942         }
   1943 
   1944         sal_memset(&fail_entry, 0, sizeof(fail_entry));
   1945         soc_mem_field32_set(unit, PORT_LAG_FAILOVER_SETm,
   1946                 (uint32 *)&fail_entry,
   1947                 FAILOVER_SET_SIZEf, hw_count - 1);
   1948         soc_mem_field32_set(unit, PORT_LAG_FAILOVER_SETm,
   1949                 (uint32 *)&fail_entry, RTAGf, rtag);
   1950 
   1951         failover_max_portcnt = 1 << soc_mem_field_length(unit,
   1952                 PORT_LAG_FAILOVER_SETm, FAILOVER_SET_SIZEf);
   1953         for (ix = 0; ix < failover_max_portcnt; ix++) {
   1954             soc_mem_field32_set(unit, PORT_LAG_FAILOVER_SETm,
   1955                     (uint32 *)&fail_entry,
   1956                     _trunk_failover_portf[ix],
   1957                     ftp[ix % hw_count]);
   1958             soc_mem_field32_set(unit, PORT_LAG_FAILOVER_SETm,
   1959                     (uint32 *)&fail_entry,
   1960                     _trunk_failover_modulef[ix],
   1961                     ftm[ix % hw_count]);
   1962         }
   1963         SOC_IF_ERROR_RETURN
   1964             (WRITE_PORT_LAG_FAILOVER_SETm(unit, MEM_BLOCK_ALL, failport,
   1965                                           &fail_entry));
   1966     }
   1967 
   1968     if (SOC_USE_PORTCTRL(unit)) {
   1969         BCM_IF_ERROR_RETURN
   1970             (bcmi_esw_portctrl_hwfailover_enable_set(unit, failport,
   1971                                                      (hw_count != 0) ? 1 : 0));
   1972     } else {
   1973         lag_failover_config_reg = SOC_REG_IS_VALID(unit, LAG_FAILOVER_CONFIGr) ?
   1974                   LAG_FAILOVER_CONFIGr: IS_CL_PORT(unit, failport) ? 
   1975                   CLMAC_CTRLr : XLMAC_CTRLr;
   1976         SOC_IF_ERROR_RETURN
   1977             (soc_reg_get(unit, lag_failover_config_reg, failport, 0, &val64));
   1978 
   1979         old_failover_en = soc_reg64_field32_get(unit, lag_failover_config_reg,
   1980                 val64, LAG_FAILOVER_ENf);
   1981         new_failover_en = (hw_count != 0) ? 1 : 0;
   1982 
   1983         if (soc_reg_field_valid(unit, lag_failover_config_reg,
   1984                     LINK_STATUS_SELECTf)) {
   1985             old_link_status_sel = soc_reg64_field32_get(unit,
   1986                     lag_failover_config_reg, val64, LINK_STATUS_SELECTf);
   1987             new_link_status_sel = (hw_count != 0) ? 1 : 0;
   1988         } else {
   1989             old_link_status_sel = 0;
   1990             new_link_status_sel = 0;
   1991         }
   1992 
   1993         if (old_failover_en != new_failover_en ||
   1994             old_link_status_sel != new_link_status_sel) {
   1995             soc_reg64_field32_set(unit, lag_failover_config_reg, &val64,
   1996                     LAG_FAILOVER_ENf, new_failover_en);
   1997             if (soc_reg_field_valid(unit, lag_failover_config_reg,
   1998                         LINK_STATUS_SELECTf)) {
   1999                 soc_reg64_field32_set(unit, lag_failover_config_reg, &val64,
   2000                         LINK_STATUS_SELECTf, new_link_status_sel);
   2001             }
   2002             SOC_IF_ERROR_RETURN
   2003                 (soc_reg_set(unit, lag_failover_config_reg, failport, 0, val64));
   2004         }
   2005 
   2006         if (SOC_REG_IS_VALID(unit, XLMAC_RX_LSS_CTRLr) ||
   2007             SOC_REG_IS_VALID(unit, CLMAC_RX_LSS_CTRLr)) {
   2008             soc_reg_t reg = XLMAC_RX_LSS_CTRLr;
   2009 
   2010             if (IS_CL_PORT(unit, failport)) {
   2011                 reg = CLMAC_RX_LSS_CTRLr;
   2012             }
   2013             SOC_IF_ERROR_RETURN
   2014                 (soc_reg_get(unit, reg, failport, 0, &val64));
   2015             if (IS_CL_PORT(unit, failport)) {
   2016                 soc_reg64_field32_set(unit, reg, &val64,
   2017                     DROP_TX_DATA_ON_LINK_INTERRUPTf, 0x1);
   2018             }
   2019             old_reset_flow_control = soc_reg64_field32_get(unit, reg,
   2020                     val64, RESET_FLOW_CONTROL_TIMERS_ON_LINK_DOWNf);
   2021             new_reset_flow_control = (hw_count != 0) ? 1 : 0;
   2022             if (old_reset_flow_control != new_reset_flow_control) {
   2023                 soc_reg64_field32_set(unit, reg, &val64,
   2024                         RESET_FLOW_CONTROL_TIMERS_ON_LINK_DOWNf,
   2025                         new_reset_flow_control);
   2026                 SOC_IF_ERROR_RETURN
   2027                     (soc_reg_set(unit, reg, failport, 0, val64));
   2028             }
   2029         }
   2030     }
   2031 
   2032     /* Notify linkscan of failover status */
   2033     BCM_IF_ERROR_RETURN
   2034         (_bcm_esw_link_failover_set(unit, failport, (hw_count != 0)));
   2035 
   2036     return BCM_E_NONE;
   2037 }
   2038 
   2039 /*
   2040  * Function:
   2041  *      _bcm_trident_trunk_hwfailover_read
   2042  * Purpose:
   2043  *      Get front-panel trunk hardware failover config.
   2044  * Parameters:
   2045  *      unit     - (IN) SOC unit number. 
   2046  *      failport - (IN) Port ID of the fail port.
   2047  *      array_size  - (IN) Max number of ports in failover port list.
   2048  *      rtag        - (OUT) Pointer to fail port RTAG. 
   2049  *      ftp         - (OUT) Pointer to port IDs in failover port list.
   2050  *      ftm         - (OUT) Pointer to module IDs in failover port list.
   2051  *      array_count - (OUT) Number of ports in failover port list.
   2052  * Returns:
   2053  *      BCM_E_xxx
   2054  */
   2055 STATIC int
   2056 _bcm_trident_trunk_hwfailover_read(int unit,
   2057         bcm_port_t failport, int array_size,
   2058         int *rtag, bcm_port_t *ftp, bcm_module_t *ftm,
   2059         int *array_count)
   2060 {
   2061     port_lag_failover_set_entry_t fail_entry;
   2062     uint64 val64;
   2063     int    ix, hw_count, enable = FALSE;
   2064     soc_reg_t lag_failover_config_reg;
   2065 
   2066     if (SOC_USE_PORTCTRL(unit)) {
   2067         BCM_IF_ERROR_RETURN
   2068             (bcmi_esw_portctrl_hwfailover_enable_get(unit, failport,
   2069                                                      &enable));
   2070     } else {
   2071         lag_failover_config_reg = SOC_REG_IS_VALID(unit, LAG_FAILOVER_CONFIGr) ?
   2072                   LAG_FAILOVER_CONFIGr : IS_CL_PORT(unit, failport) ?
   2073                   CLMAC_CTRLr : XLMAC_CTRLr;
   2074         SOC_IF_ERROR_RETURN
   2075             (soc_reg_get(unit, lag_failover_config_reg, failport, 0, &val64));
   2076         enable = soc_reg64_field32_get(unit, lag_failover_config_reg, val64,
   2077                 LAG_FAILOVER_ENf);
   2078     }
   2079 
   2080     if (enable) {
   2081         SOC_IF_ERROR_RETURN
   2082             (READ_PORT_LAG_FAILOVER_SETm(unit, MEM_BLOCK_ALL, failport,
   2083                                          &fail_entry));
   2084         hw_count = 1 + soc_mem_field32_get(unit, PORT_LAG_FAILOVER_SETm,
   2085                 &fail_entry,
   2086                 FAILOVER_SET_SIZEf);
   2087         if ((hw_count > array_size) && (array_size != 0)) {
   2088             hw_count = array_size;
   2089         }
   2090         for (ix = 0; ix < hw_count; ix++) {
   2091             if (NULL != ftp) {
   2092                 ftp[ix] = soc_mem_field32_get(unit, PORT_LAG_FAILOVER_SETm,
   2093                         &fail_entry,
   2094                         _trunk_failover_portf[ix]);
   2095             }
   2096             if (NULL != ftm) {
   2097                 ftm[ix] = soc_mem_field32_get(unit, PORT_LAG_FAILOVER_SETm,
   2098                         &fail_entry,
   2099                         _trunk_failover_modulef[ix]);
   2100             }
   2101         }
   2102         if (NULL != rtag) {
   2103             *rtag = soc_mem_field32_get(unit, PORT_LAG_FAILOVER_SETm,
   2104                         &fail_entry, RTAGf);
   2105         }
   2106         if (NULL != array_count) {
   2107             *array_count = hw_count;
   2108         }
   2109     } else {
   2110         if (NULL != array_count) {
   2111             *array_count = 0;
   2112         }
   2113         if (NULL != rtag) {
   2114             *rtag = 0;
   2115         }
   2116     }
   2117 
   2118     return BCM_E_NONE;
   2119 }
   2120 
   2121 /*
   2122  * Function:
   2123  *	_bcm_trident_trunk_psc_to_rtag
   2124  * Purpose:
   2125  *      Convert PSC to RTAG.
   2126  * Parameters:
   2127  *      unit - (IN) StrataSwitch PCI device unit number (driver internal).
   2128  *      psc  - (OUT) Port selection criteria.
   2129  *      rtag - (OUT) Pointer to RTAG.
   2130  * Returns:
   2131  *	BCM_E_XXX
   2132  */
   2133 STATIC int
   2134 _bcm_trident_trunk_psc_to_rtag(int unit, int psc, int *rtag)
   2135 {
   2136     switch (psc) {
   2137     case BCM_TRUNK_PSC_SRCMAC:
   2138     case BCM_TRUNK_PSC_DSTMAC:
   2139     case BCM_TRUNK_PSC_SRCDSTMAC:
   2140     case BCM_TRUNK_PSC_SRCIP:
   2141     case BCM_TRUNK_PSC_DSTIP:
   2142     case BCM_TRUNK_PSC_SRCDSTIP:
   2143         /* These BCM_TRUNK_PSC_ values match the hardware RTAG values */
   2144         *rtag = psc;
   2145         break;
   2146     case BCM_TRUNK_PSC_PORTINDEX:
   2147         if (!soc_feature(unit, soc_feature_port_trunk_index)) {
   2148             return BCM_E_PARAM;
   2149         }
   2150         *rtag = 7;
   2151         break;
   2152     case BCM_TRUNK_PSC_PORTFLOW:
   2153         if (!soc_feature(unit, soc_feature_port_flow_hash)) {
   2154             return BCM_E_PARAM;
   2155         }
   2156         *rtag = 7;
   2157         break;
   2158     case BCM_TRUNK_PSC_DYNAMIC:
   2159     case BCM_TRUNK_PSC_DYNAMIC_ASSIGNED:
   2160     case BCM_TRUNK_PSC_DYNAMIC_OPTIMAL:
   2161     case BCM_TRUNK_PSC_DYNAMIC_RESILIENT:
   2162         *rtag = 7;
   2163         break;
   2164     case BCM_TRUNK_PSC_ROUND_ROBIN:
   2165     case BCM_TRUNK_PSC_RANDOMIZED:
   2166         *rtag = 0;
   2167         break;
   2168     default:
   2169         return BCM_E_PARAM;
   2170     }
   2171     return BCM_E_NONE;
   2172 }
   2173 
   2174 /*
   2175  * Function:
   2176  *      _bcm_trident_trunk_hwfailover_set
   2177  * Purpose:
   2178  *      Derive hardware failover port list, and
   2179  *      set trunk hardware failover config.
   2180  * Parameters:
   2181  *      unit     - (IN) SOC unit number. 
   2182  *      tid      - (IN) Trunk group ID.
   2183  *      hg_trunk - (IN) Indicate if trunk group is a Higig trunk.
   2184  *      port     - (IN) Port ID of the fail port.
   2185  *      modid    - (IN) Module ID of the fail port.
   2186  *      psc      - (IN) Port selection criteria for failover port list.
   2187  *      flags    - (IN) BCM_TRUNK_FLAG_FAILOVER_xxx
   2188  *      count    - (IN) Number of ports in failover port list.
   2189  *      ftp      - (IN) Pointer to port IDs in failover port list.
   2190  *      ftm      - (IN) Pointer to module IDs in failover port list.
   2191  * Returns:
   2192  *      BCM_E_xxx
   2193  */
   2194 int
   2195 _bcm_trident_trunk_hwfailover_set(int unit,
   2196         bcm_trunk_t tid, int hg_trunk,
   2197         bcm_port_t port, bcm_module_t modid,
   2198         int psc, uint32 flags, int count, 
   2199         bcm_port_t *ftp, bcm_module_t *ftm)
   2200 {
   2201     bcm_trunk_chip_info_t chip_info;
   2202     int rv = BCM_E_NONE;
   2203     int ix, tix, tid_ix, tports, next, local, mod_is_local, hw_count, rtag;
   2204     uint8 tp_mod;
   2205     uint16 fail_modport;
   2206     bcm_gport_t gport;
   2207     bcm_port_t local_port;
   2208     int failover_max_portcnt;
   2209     bcm_port_t *port_list = NULL;
   2210     bcm_module_t *modid_list = NULL;
   2211     _trident_hw_tinfo_t *hwft;
   2212     
   2213     /* Need the HW port number for the table write later */
   2214     if (hg_trunk) {
   2215         fail_modport = local_port = port;
   2216     } else {
   2217         BCM_GPORT_MODPORT_SET(gport, modid, port);
   2218         BCM_IF_ERROR_RETURN
   2219             (bcm_esw_port_local_get(unit, gport, &local_port));
   2220 
   2221         /*For Higig ports that are members of a LAG,
   2222                 it Should not configure a list of failover ports for Higig ports, 
   2223                 since Higig ports do not support LAG failover loopback.
   2224                 However, the Higig ports can still be part of the list of 
   2225                 failover ports for other LAG members.*/
   2226         if (IS_HG_PORT(unit, local_port)) {
   2227             return BCM_E_UNAVAIL;
   2228         }
   2229         /* not supported on Cascaded Physical Ports */
   2230         if ((soc_feature(unit, soc_feature_linkphy_coe) &&
   2231             IS_LP_PORT(unit, local_port)) ||
   2232             (soc_feature(unit, soc_feature_subtag_coe) &&
   2233             IS_SUBTAG_PORT(unit, local_port)) ||
   2234             (soc_feature(unit, soc_feature_hgproxy_subtag_coe) &&
   2235             IS_SUBTAG_PORT (unit, local_port))) {
   2236             return BCM_E_UNAVAIL;
   2237         }
   2238 
   2239 #if defined(BCM_HELIX5_SUPPORT)
   2240         /* Skip q-ports in HX5 since trunk hardware failover is not
   2241          * supported for PM4x10Q.
   2242          */
   2243         if (IS_QSGMII_PORT(unit, local_port)) {
   2244             return BCM_E_UNAVAIL;
   2245         }
   2246 #endif /* BCM_HELIX5_SUPPORT */
   2247 
   2248         fail_modport = (modid << 8) | port;
   2249     }
   2250 
   2251     BCM_IF_ERROR_RETURN(_bcm_trident_trunk_psc_to_rtag(unit, psc, &rtag));
   2252 
   2253     BCM_IF_ERROR_RETURN(bcm_esw_trunk_chip_info_get(unit, &chip_info));
   2254     tid_ix = tid + (hg_trunk ? chip_info.trunk_group_count : 0);
   2255     hwft = &(_trident_trunk_hwfail[unit]->hw_tinfo[tid_ix]);
   2256 
   2257     /* Where is our port in the trunk list? */
   2258     tports = hwft->num_ports;
   2259     for (tix = 0; tix < tports; tix++) {
   2260         if (fail_modport == hwft->modport[tix]) {
   2261             break;
   2262         }
   2263     }
   2264 
   2265     if ((0 != count) && (tix == tports)) {
   2266         /* Port not in trunk! */
   2267         return BCM_E_NOT_FOUND;
   2268     }
   2269 
   2270     if (hg_trunk) {
   2271         failover_max_portcnt = 1 << soc_mem_field_length(unit,
   2272                 HG_TRUNK_FAILOVER_SETm, FAILOVER_SET_SIZEf);
   2273     } else {
   2274         failover_max_portcnt = 1 << soc_mem_field_length(unit,
   2275                 PORT_LAG_FAILOVER_SETm, FAILOVER_SET_SIZEf);
   2276     }
   2277     port_list = sal_alloc(sizeof(bcm_port_t) * failover_max_portcnt,
   2278             "failover port list");
   2279     if (port_list == NULL) {
   2280         return BCM_E_MEMORY;
   2281     }
   2282     modid_list = sal_alloc(sizeof(bcm_module_t) * failover_max_portcnt,
   2283             "failover module list");
   2284     if (modid_list == NULL) {
   2285         sal_free(port_list);
   2286         return BCM_E_MEMORY;
   2287     }
   2288 
   2289     if (flags) {
   2290         switch (flags) {
   2291             case BCM_TRUNK_FLAG_FAILOVER_NEXT_LOCAL:
   2292                 next = TRUE;
   2293                 local = TRUE;
   2294                 break;
   2295             case BCM_TRUNK_FLAG_FAILOVER_NEXT:
   2296                 next = TRUE;
   2297                 local = FALSE;
   2298                 break;
   2299             case BCM_TRUNK_FLAG_FAILOVER_ALL_LOCAL:
   2300                 next = FALSE;
   2301                 local = TRUE;
   2302                 break;
   2303             case BCM_TRUNK_FLAG_FAILOVER_ALL:
   2304                 next = FALSE;
   2305                 local = FALSE;
   2306                 break;
   2307             default:
   2308                 /* Illegal flags setting */
   2309                 sal_free(port_list);
   2310                 sal_free(modid_list);
   2311                 return BCM_E_PARAM;
   2312         }
   2313 
   2314         hw_count = 0;
   2315 
   2316         for (ix = ((tix + 1) % tports);  /* Start after fail port */
   2317                 ix != tix;                  /* Stop when we get back */
   2318                 ix = ((ix + 1) % tports)) { /* Cycle through trunk port list */
   2319             tp_mod = hwft->modport[ix] >> 8;
   2320             if (local && !hg_trunk) {
   2321                 rv = _bcm_esw_modid_is_local(unit, tp_mod, &mod_is_local);
   2322                 if (BCM_FAILURE(rv)) {
   2323                     sal_free(port_list);
   2324                     sal_free(modid_list);
   2325                     return rv;
   2326                 }
   2327                 if (!mod_is_local) {
   2328                     continue;
   2329                 }
   2330             }
   2331             port_list[hw_count] = hwft->modport[ix] & 0xff;
   2332             modid_list[hw_count] = tp_mod;
   2333             hw_count++;
   2334             if (hw_count == failover_max_portcnt) {
   2335                 break;
   2336             }
   2337             if (next) {
   2338                 break;
   2339             }
   2340         }
   2341     } else {
   2342         hw_count = 0;
   2343 
   2344         if (count) {
   2345             for (ix = 0; ix < count && ix < failover_max_portcnt; ix++) {
   2346                 port_list[ix] = ftp[ix];
   2347                 modid_list[ix] = ftm[ix];
   2348             }
   2349             hw_count = ix;
   2350         }
   2351     }
   2352 
   2353     if (hg_trunk) {
   2354         rv = _bcm_trident_trunk_hwfailover_hg_write(unit, local_port, rtag,
   2355                 hw_count, port_list);
   2356     } else {
   2357         rv = _bcm_trident_trunk_hwfailover_write(unit, local_port, rtag,
   2358                 hw_count, port_list, modid_list);
   2359     }
   2360     sal_free(port_list);
   2361     sal_free(modid_list);
   2362     if (BCM_FAILURE(rv)) {
   2363         return rv;
   2364     }
   2365 
   2366     if (tix < hwft->num_ports) {
   2367         hwft->flags[tix] = flags;
   2368         hwft->psc[tix] = psc;
   2369     }
   2370 
   2371     return rv;
   2372 }
   2373 
   2374 /*
   2375  * Function:
   2376  *      _bcm_trident_trunk_hwfailover_get
   2377  * Purpose:
   2378  *      Get trunk hardware failover config.
   2379  * Parameters:
   2380  *      unit     - (IN) SOC unit number. 
   2381  *      tid      - (IN) Trunk group ID.
   2382  *      hg_trunk - (IN) Indicate if trunk group is a Higig trunk.
   2383  *      port     - (IN) Port ID of the fail port.
   2384  *      modid    - (IN) Module ID of the fail port.
   2385  *      psc         - (OUT) Port selection criteria for failover port list.
   2386  *      flags       - (OUT) BCM_TRUNK_FLAG_FAILOVER_xxx
   2387  *      array_size  - (IN) Max number of ports in failover port list.
   2388  *      ftp         - (OUT) Pointer to port IDs in failover port list.
   2389  *      ftm         - (OUT) Pointer to module IDs in failover port list.
   2390  *      array_count - (OUT) Number of ports in failover port list.
   2391  * Returns:
   2392  *      BCM_E_xxx
   2393  */
   2394 int
   2395 _bcm_trident_trunk_hwfailover_get(int unit,
   2396         bcm_trunk_t tid, int hg_trunk,
   2397         bcm_port_t port, bcm_module_t modid,
   2398         int *psc, uint32 *flags, int array_size,
   2399         bcm_port_t *ftp, bcm_module_t *ftm, 
   2400         int *array_count)
   2401 {
   2402     bcm_trunk_chip_info_t chip_info;
   2403     int tix, tid_ix, tports;
   2404     uint16 fail_modport;
   2405     bcm_gport_t gport;
   2406     bcm_port_t local_port;
   2407     _trident_hw_tinfo_t *hwft;
   2408 
   2409     /* Need the HW port number for the table write later */
   2410     if (hg_trunk) {
   2411         fail_modport = local_port = port;
   2412     } else {
   2413         BCM_GPORT_MODPORT_SET(gport, modid, port);
   2414         BCM_IF_ERROR_RETURN
   2415             (bcm_esw_port_local_get(unit, gport, &local_port));
   2416         fail_modport = (modid << 8) | port;
   2417     }
   2418 
   2419     BCM_IF_ERROR_RETURN(bcm_esw_trunk_chip_info_get(unit, &chip_info));
   2420     tid_ix = tid + (hg_trunk ? chip_info.trunk_group_count : 0);
   2421     hwft = &(_trident_trunk_hwfail[unit]->hw_tinfo[tid_ix]);
   2422 
   2423     /* Where is our port in the trunk list? */
   2424     tports = hwft->num_ports;
   2425     for (tix = 0; tix < tports; tix++) {
   2426         if (fail_modport == hwft->modport[tix]) {
   2427             break;
   2428         }
   2429     }
   2430 
   2431     if (tix == tports) {
   2432         /* Port not in trunk! */
   2433         return BCM_E_NOT_FOUND;
   2434     }
   2435 
   2436     *psc = hwft->psc[tix];
   2437 
   2438     if (hwft->flags[tix]) {
   2439         /* Just return the flags value */
   2440         *flags = hwft->flags[tix];
   2441         *array_count = 0;
   2442     } else {
   2443         /* Access the HW to get the list */
   2444         *flags = 0;
   2445         if (hg_trunk) {
   2446             BCM_IF_ERROR_RETURN
   2447                 (_bcm_trident_trunk_hwfailover_hg_read(unit, local_port,
   2448                                                     array_size, NULL,
   2449                                                     ftp, ftm, array_count));
   2450         } else {
   2451             BCM_IF_ERROR_RETURN
   2452                 (_bcm_trident_trunk_hwfailover_read(unit, local_port,
   2453                                                     array_size, NULL,
   2454                                                     ftp, ftm, array_count));
   2455         }
   2456     }
   2457 
   2458     return BCM_E_NONE;
   2459 }
   2460 
   2461 /*
   2462  * Function:
   2463  *      _bcm_trident_trunk_failover_set
   2464  * Purpose:
   2465  *      Disable hardware failover for old trunk ports, and
   2466  *      configure hardware failover for new trunk ports.
   2467  * Parameters:
   2468  *      unit     - (IN) SOC unit number. 
   2469  *      tid      - (IN) Trunk group ID.
   2470  *      hg_trunk - (IN) Indicate if trunk group is a Higig trunk
   2471  *      add_info - (IN) Pointer to trunk add info structure.
   2472  * Returns:
   2473  *      BCM_E_xxx
   2474  */
   2475 STATIC int
   2476 _bcm_trident_trunk_failover_set(int unit, 
   2477         bcm_trunk_t tid, 
   2478         int hg_trunk,
   2479         _esw_trunk_add_info_t *add_info)
   2480 {
   2481     bcm_trunk_chip_info_t chip_info;
   2482     int rv = BCM_E_NONE;
   2483     int tix, mod_is_local, tid_ix;
   2484     bcm_port_t   tp_port, local_port;
   2485     bcm_module_t tp_mod = -1;
   2486     _trident_hw_tinfo_t *hwft;
   2487     bcm_port_t *port_array = NULL;
   2488     bcm_module_t *mod_array = NULL;
   2489     int num_hwft_ports;
   2490     int failover_flags;
   2491     bcm_gport_t gport;
   2492 
   2493     BCM_IF_ERROR_RETURN(bcm_esw_trunk_chip_info_get(unit, &chip_info));
   2494     tid_ix = tid + (hg_trunk ? chip_info.trunk_group_count : 0);
   2495     hwft = &(_trident_trunk_hwfail[unit]->hw_tinfo[tid_ix]);
   2496 
   2497     failover_flags = 0;
   2498     if (add_info != NULL) {
   2499         if (add_info->flags & BCM_TRUNK_FLAG_FAILOVER_NEXT) {
   2500             failover_flags = BCM_TRUNK_FLAG_FAILOVER_NEXT;
   2501         } else if (add_info->flags & BCM_TRUNK_FLAG_FAILOVER_NEXT_LOCAL) {
   2502             failover_flags = BCM_TRUNK_FLAG_FAILOVER_NEXT_LOCAL;
   2503         } else if (add_info->flags & BCM_TRUNK_FLAG_FAILOVER_ALL) {
   2504             failover_flags = BCM_TRUNK_FLAG_FAILOVER_ALL;
   2505         } else if (add_info->flags & BCM_TRUNK_FLAG_FAILOVER_ALL_LOCAL) {
   2506             failover_flags = BCM_TRUNK_FLAG_FAILOVER_ALL_LOCAL;
   2507         }
   2508     }
   2509 
   2510     if ((NULL == add_info) || (0 != failover_flags)) {
   2511         /* Disable hardware failover for old trunk ports */
   2512         for (tix = 0; tix < hwft->num_ports; tix++) {
   2513             tp_port = hwft->modport[tix] & 0xff;
   2514             if (!hg_trunk) {
   2515                 tp_mod = hwft->modport[tix] >> 8;
   2516                 BCM_IF_ERROR_RETURN
   2517                     (_bcm_esw_modid_is_local(unit, tp_mod, &mod_is_local));
   2518                 if (!mod_is_local) {
   2519                     continue;
   2520                 }
   2521 
   2522                 BCM_GPORT_MODPORT_SET(gport, tp_mod, tp_port);
   2523                 BCM_IF_ERROR_RETURN
   2524                 (bcm_esw_port_local_get(unit, gport, &local_port));
   2525                 if (IS_HG_PORT(unit, local_port)) {
   2526                     continue;
   2527                 }
   2528                 /* skip Cascaded Physical Ports */
   2529                 if ((soc_feature(unit, soc_feature_linkphy_coe) &&
   2530                     IS_LP_PORT(unit, local_port)) ||
   2531                     (soc_feature(unit, soc_feature_subtag_coe) &&
   2532                     IS_SUBTAG_PORT(unit, local_port))||
   2533                     (soc_feature(unit, soc_feature_hgproxy_subtag_coe) &&
   2534                      IS_SUBTAG_PORT (unit, local_port))) {
   2535                     continue;
   2536                 }
   2537 
   2538 #if defined(BCM_HELIX5_SUPPORT)
   2539                 /* Skip q-ports in HX5 since trunk hardware failover is not
   2540                  * supported for PM4x10Q.
   2541                  */
   2542                 if (IS_QSGMII_PORT(unit, local_port)) {
   2543                     continue;
   2544                 }
   2545 #endif /* BCM_HELIX5_SUPPORT */
   2546             }
   2547             BCM_IF_ERROR_RETURN
   2548                 (_bcm_trident_trunk_hwfailover_set(unit, tid, hg_trunk,
   2549                                                    tp_port, tp_mod,
   2550                                                    hwft->psc[tix],
   2551                                                    0, 0, NULL, NULL));
   2552         }
   2553     }
   2554     /* Else, updating trunk with failover_flags == 0,
   2555      * do not change failover configuration */
   2556 
   2557     if (hwft->modport) {
   2558         sal_free(hwft->modport);
   2559         hwft->modport = NULL;
   2560     }
   2561     if (hwft->psc) {
   2562         sal_free(hwft->psc);
   2563         hwft->psc = NULL;
   2564     }
   2565     if (hwft->flags) {
   2566         sal_free(hwft->flags);
   2567         hwft->flags = NULL;
   2568     }
   2569     hwft->num_ports = 0;
   2570 
   2571     if (NULL == add_info) {
   2572         /* We're deleting the trunk */
   2573         return BCM_E_NONE;
   2574     }
   2575 
   2576     /* Record new trunk data */
   2577 
   2578     if (hwft->modport == NULL) {
   2579         hwft->modport = sal_alloc(sizeof(uint16) * add_info->num_ports, "hw_tinfo_modport");
   2580         if (hwft->modport == NULL) {
   2581             return BCM_E_MEMORY;
   2582         }
   2583     }
   2584     sal_memset(hwft->modport, 0, sizeof(uint16) * add_info->num_ports);
   2585 
   2586     if (hwft->psc == NULL) {
   2587         hwft->psc = sal_alloc(sizeof(uint8) * add_info->num_ports, "hw_tinfo_psc");
   2588         if (hwft->psc == NULL) {
   2589             sal_free(hwft->modport);
   2590             hwft->modport = NULL;
   2591             return BCM_E_MEMORY;
   2592         }
   2593     }
   2594     sal_memset(hwft->psc, 0, sizeof(uint8) * add_info->num_ports);
   2595 
   2596     if (hwft->flags == NULL) {
   2597         hwft->flags = sal_alloc(sizeof(uint32) * add_info->num_ports, "hw_tinfo_flags");
   2598         if (hwft->flags == NULL) {
   2599             sal_free(hwft->modport);
   2600             hwft->modport = NULL;
   2601             sal_free(hwft->psc);
   2602             hwft->psc = NULL;
   2603             return BCM_E_MEMORY;
   2604         }
   2605     }
   2606     sal_memset(hwft->flags, 0, sizeof(uint32) * add_info->num_ports);
   2607 
   2608     if (mod_array == NULL) {
   2609         mod_array = sal_alloc(sizeof(bcm_module_t) * add_info->num_ports, "mod_array");
   2610         if (mod_array == NULL) {
   2611             sal_free(hwft->modport);
   2612             hwft->modport = NULL;
   2613             sal_free(hwft->psc);
   2614             hwft->psc = NULL;
   2615             sal_free(hwft->flags);
   2616             hwft->flags = NULL;
   2617             return BCM_E_MEMORY;
   2618         }
   2619     }
   2620     sal_memset(mod_array, 0, sizeof(bcm_module_t) * add_info->num_ports);
   2621     
   2622     if (port_array == NULL) {
   2623         port_array = sal_alloc(sizeof(bcm_port_t) * add_info->num_ports, "port_array");
   2624         if (port_array == NULL) {
   2625             sal_free(hwft->modport);
   2626             hwft->modport = NULL;
   2627             sal_free(hwft->psc);
   2628             hwft->psc = NULL;
   2629             sal_free(hwft->flags);
   2630             hwft->flags = NULL;
   2631             sal_free(mod_array);
   2632             return BCM_E_MEMORY;
   2633         }
   2634     }
   2635     sal_memset(port_array, 0, sizeof(bcm_port_t) * add_info->num_ports);
   2636 
   2637     num_hwft_ports = 0;
   2638     for (tix = 0; tix < add_info->num_ports; tix++) {
   2639         if (add_info->member_flags[tix] & BCM_TRUNK_MEMBER_EGRESS_DISABLE) {
   2640             continue;
   2641         }
   2642         hwft->flags[num_hwft_ports] = failover_flags;
   2643         hwft->psc[num_hwft_ports] = add_info->psc;
   2644         hwft->modport[num_hwft_ports] = add_info->tp[tix];
   2645         port_array[num_hwft_ports] = add_info->tp[tix];
   2646         if (!hg_trunk) {
   2647             hwft->modport[num_hwft_ports] |= (add_info->tm[tix] << 8);
   2648             mod_array[num_hwft_ports] = add_info->tm[tix];
   2649         }
   2650         num_hwft_ports++; 
   2651     }
   2652     hwft->num_ports = num_hwft_ports;
   2653 
   2654     /* No failover flags in trunk_set means no failover changes */
   2655     if (0 != failover_flags) {
   2656         /* Configure hardware failover for new trunk ports */
   2657         for (tix = 0; tix < hwft->num_ports; tix++) {
   2658             if (!hg_trunk) {
   2659                 rv = _bcm_esw_modid_is_local(unit, hwft->modport[tix] >> 8,
   2660                         &mod_is_local);
   2661                 if (BCM_FAILURE(rv)) {
   2662                     sal_free(mod_array);
   2663                     sal_free(port_array);
   2664                     return rv;
   2665                 }
   2666                 if (!mod_is_local) {
   2667                     continue;
   2668                 }
   2669 
   2670                 tp_mod = hwft->modport[tix] >> 8;
   2671                 BCM_GPORT_MODPORT_SET(gport, tp_mod, hwft->modport[tix] & 0xff);
   2672                 rv = bcm_esw_port_local_get(unit, gport, &local_port);
   2673                 if (BCM_FAILURE(rv)) {
   2674                     sal_free(mod_array);
   2675                     sal_free(port_array);
   2676                     return rv;
   2677                 }
   2678                 if (IS_HG_PORT(unit, local_port)) {
   2679                     continue;
   2680                 }
   2681                 /* skip Cascaded Physical Ports*/
   2682                 if ((soc_feature(unit, soc_feature_linkphy_coe) &&
   2683                     IS_LP_PORT(unit, local_port)) ||
   2684                     (soc_feature(unit, soc_feature_subtag_coe) &&
   2685                     IS_SUBTAG_PORT(unit, local_port)) ||
   2686                     (soc_feature(unit, soc_feature_hgproxy_subtag_coe) &&
   2687                      IS_SUBTAG_PORT (unit, local_port))) {
   2688                     continue;
   2689                 }
   2690 
   2691 #if defined(BCM_HELIX5_SUPPORT)
   2692                 /* Skip q-ports in HX5 since trunk hardware failover is not
   2693                  * supported for PM4x10Q.
   2694                  */
   2695                 if (IS_QSGMII_PORT(unit, local_port)) {
   2696                     continue;
   2697                 }
   2698 #endif /* BCM_HELIX5_SUPPORT */
   2699             }
   2700             rv = _bcm_trident_trunk_hwfailover_set(unit, tid, hg_trunk, 
   2701                     hwft->modport[tix] & 0xff,
   2702                     hwft->modport[tix] >> 8,
   2703                     hwft->psc[tix],
   2704                     hwft->flags[tix],
   2705                     hwft->num_ports,
   2706                     port_array,
   2707                     mod_array);
   2708             if (BCM_FAILURE(rv)) {
   2709                 sal_free(mod_array);
   2710                 sal_free(port_array);
   2711                 return rv;
   2712             }
   2713         }
   2714     }
   2715 
   2716     sal_free(mod_array);
   2717     sal_free(port_array);
   2718 
   2719     return BCM_E_NONE;
   2720 }
   2721 
   2722 /* ----------------------------------------------------------------------------- 
   2723  *
   2724  * Routines for software failover
   2725  *
   2726  * ----------------------------------------------------------------------------- 
   2727  */
   2728 
   2729 /*
   2730  * Function:
   2731  *      _bcm_trident_trunk_swfailover_fabric_set
   2732  * Purpose:
   2733  *      Set Higig trunk software failover config.
   2734  * Parameters:
   2735  *      unit  - (IN) SOC unit number. 
   2736  *      hgtid - (IN) Higig trunk ID.
   2737  *      rtag  - (IN) Port selection criteria. 
   2738  *      ports - (IN) Higig trunk member ports.
   2739  * Returns:
   2740  *      BCM_E_xxx
   2741  */
   2742 STATIC int
   2743 _bcm_trident_trunk_swfailover_fabric_set(int unit,
   2744         bcm_trunk_t hgtid,
   2745         int rtag,
   2746         bcm_pbmp_t ports)
   2747 {
   2748     bcm_trunk_chip_info_t chip_info;
   2749     _trident_trunk_swfail_t *swf;
   2750     _trident_tinfo_t        *swft;
   2751     bcm_port_t              port;
   2752     int                     i;
   2753     int fabric_trunk_swf_tid_offset = 0;
   2754 
   2755     if (_trident_trunk_swfail[unit] == NULL) {
   2756         return BCM_E_INIT;
   2757     }
   2758 
   2759     swf = _trident_trunk_swfail[unit];
   2760 
   2761     BCM_IF_ERROR_RETURN(bcm_esw_trunk_chip_info_get(unit, &chip_info));
   2762     swft = &swf->tinfo[hgtid + chip_info.trunk_group_count];
   2763     fabric_trunk_swf_tid_offset = chip_info.trunk_group_count + 1;
   2764 
   2765     swft->rtag = rtag;
   2766     SOC_PBMP_COUNT(ports, swft->num_ports);
   2767 
   2768     if (swft->modport) {
   2769         sal_free(swft->modport);
   2770         swft->modport = NULL;
   2771     }
   2772 
   2773     if (swft->num_ports > 0) {
   2774         swft->modport = sal_alloc(sizeof(uint16) * swft->num_ports,
   2775                 "swfail_tinfo_modport");
   2776         if (swft->modport == NULL) {
   2777             return BCM_E_MEMORY;
   2778         }
   2779 
   2780         i = 0;
   2781         SOC_PBMP_ITER(ports, port) {
   2782             swft->modport[i++] = port;
   2783         }
   2784     }
   2785 
   2786     PBMP_ALL_ITER(unit, port) {
   2787         if (BCM_PBMP_MEMBER(ports, port)) {
   2788             swf->trunk[port] = hgtid + fabric_trunk_swf_tid_offset;
   2789         } else if (swf->trunk[port] ==
   2790                 (hgtid + fabric_trunk_swf_tid_offset)) {
   2791             swf->trunk[port] = 0;       /* remove stale pointers to tid */
   2792         }
   2793     }
   2794     return BCM_E_NONE;
   2795 }   
   2796 
   2797 /*
   2798  * Function:
   2799  *      _bcm_trident_trunk_swfailover_fp_set
   2800  * Purpose:
   2801  *      Set front panel trunk software failover config.
   2802  * Parameters:
   2803  *      unit   - (IN) SOC unit number. 
   2804  *      tid    - (IN) Trunk ID.
   2805  *      rtag   - (IN) Port selection criteria. 
   2806  *      nports - (IN) Number of trunk members. 
   2807  *      mods   - (IN) Trunk member module ID array.
   2808  *      ports  - (IN) Trunk member port ID array.
   2809  *      member_flags - (IN) Trunk member flags array.
   2810  *      flags  - (IN) Trunk group flags.
   2811  * Returns:
   2812  *      BCM_E_xxx
   2813  */
   2814 STATIC int
   2815 _bcm_trident_trunk_swfailover_fp_set(int unit,
   2816         bcm_trunk_t tid,
   2817         int rtag,
   2818         int nports,
   2819         int *mods,
   2820         int *ports,
   2821         uint32 *member_flags,
   2822         uint32 flags)
   2823 {
   2824     _trident_trunk_swfail_t *swf;
   2825     _trident_tinfo_t        *swft;
   2826     bcm_pbmp_t          localports;
   2827     bcm_port_t          port;
   2828     bcm_module_t        my_modid;
   2829     int                 i;
   2830     bcm_pbmp_t          all_pbmp;
   2831 #if defined(BCM_KATANA2_SUPPORT)
   2832     int                 pp_port;
   2833 #endif
   2834 #if defined(BCM_HGPROXY_COE_SUPPORT)
   2835     int                 phy_port = 0;
   2836 #endif
   2837 
   2838     if (_trident_trunk_swfail[unit] == NULL) {
   2839         return BCM_E_INIT;
   2840     }
   2841 
   2842     BCM_IF_ERROR_RETURN
   2843         (bcm_esw_stk_my_modid_get(unit, &my_modid));
   2844 
   2845     swf = _trident_trunk_swfail[unit];
   2846     swft = &swf->tinfo[tid];
   2847 
   2848     swf->mymodid = my_modid;
   2849     swft->rtag = rtag;
   2850     swft->num_ports = nports;
   2851     swft->flags = flags;
   2852 
   2853     if (swft->modport) {
   2854         sal_free(swft->modport);
   2855         swft->modport = NULL;
   2856     }
   2857     if (swft->member_flags) {
   2858         sal_free(swft->member_flags);
   2859         swft->member_flags = NULL;
   2860     }
   2861 
   2862     BCM_PBMP_CLEAR(localports);
   2863     if (swft->num_ports > 0) {
   2864         swft->modport = sal_alloc(sizeof(uint16) * swft->num_ports,
   2865                 "swfail_tinfo_modport");
   2866         if (swft->modport == NULL) {
   2867             return BCM_E_MEMORY;
   2868         }
   2869         swft->member_flags = sal_alloc(sizeof(uint32) * swft->num_ports,
   2870                 "swfail_tinfo_member_flags");
   2871         if (swft->member_flags == NULL) {
   2872             sal_free(swft->modport);
   2873             swft->modport = NULL;
   2874             return BCM_E_MEMORY;
   2875         }
   2876 
   2877         for (i = 0; i < nports; i++) {
   2878             swft->modport[i] = (mods[i] << 8) | ports[i];
   2879             if (mods[i] == my_modid) {
   2880                 BCM_PBMP_PORT_ADD(localports, ports[i]);
   2881             }
   2882 
   2883 #if defined(BCM_HGPROXY_COE_SUPPORT)
   2884             if (soc_feature(unit, soc_feature_hgproxy_subtag_coe)) {
   2885                 if(_bcm_xgs5_subport_coe_mod_local(unit, mods[i])) {
   2886 
   2887                     BCM_IF_ERROR_RETURN(
   2888                         _bcmi_coe_subport_mod_port_physical_port_get(unit,
   2889                                                                      mods[i],
   2890                                                                      ports[i],
   2891                                                                      &phy_port));
   2892                          BCM_PBMP_PORT_ADD(localports, phy_port);
   2893                 }
   2894             }
   2895 #endif
   2896             if (soc_feature(unit, soc_feature_linkphy_coe) ||
   2897                 soc_feature(unit, soc_feature_subtag_coe)) {
   2898 #if defined(BCM_KATANA2_SUPPORT)
   2899                 if (_bcm_kt2_mod_is_coe_mod_check(unit, mods[i]) == BCM_E_NONE) {
   2900                     pp_port = 0;
   2901                     BCM_IF_ERROR_RETURN(_bcm_kt2_modport_to_pp_port_get(
   2902                                             unit, mods[i], ports[i], &pp_port));
   2903 #if defined BCM_METROLITE_SUPPORT
   2904                     if (soc_feature(unit, soc_feature_discontinuous_pp_port)) {
   2905                         if (_SOC_IS_PP_PORT_LINKPHY_SUBTAG(unit, pp_port)) {
   2906                             BCM_PBMP_PORT_ADD(localports, pp_port);
   2907                         }
   2908                     } else
   2909 #endif
   2910                     {
   2911                         if ((pp_port >= SOC_INFO(unit).pp_port_index_min) &&
   2912                             (pp_port <= SOC_INFO(unit).pp_port_index_max)) {
   2913                             BCM_PBMP_PORT_ADD(localports, pp_port);
   2914                         }
   2915                     }
   2916                 }
   2917 #endif
   2918             }
   2919             swft->member_flags[i] = member_flags[i];
   2920         }
   2921     }
   2922 
   2923     BCM_PBMP_CLEAR(all_pbmp);
   2924     BCM_PBMP_ASSIGN(all_pbmp, PBMP_ALL(unit));
   2925 
   2926 #if defined(BCM_KATANA2_SUPPORT)
   2927         if (soc_feature(unit, soc_feature_linkphy_coe) ||
   2928             soc_feature(unit, soc_feature_subtag_coe)) {
   2929             _bcm_kt2_subport_pbmp_update(unit, &all_pbmp);
   2930         }
   2931         if (SOC_IS_KATANA2(unit) && soc_feature(unit, soc_feature_flex_port)) {
   2932             BCM_IF_ERROR_RETURN(_bcm_kt2_flexio_pbmp_update (unit, &all_pbmp));
   2933         }
   2934 #endif
   2935 
   2936     PBMP_ITER(all_pbmp, port) {
   2937         if (BCM_PBMP_MEMBER(localports, port)) {
   2938             /* coverity[overrun-local : FALSE] */
   2939             swf->trunk[port] = tid + 1;
   2940         } else if (swf->trunk[port] == tid + 1) {
   2941             swf->trunk[port] = 0;       /* remove stale pointers to tid */
   2942         }
   2943     }
   2944     return BCM_E_NONE;
   2945 }
   2946 
   2947 #ifdef BCM_TRUNK_FAILOVER_SUPPORT
   2948 
   2949 /*
   2950  * Function:
   2951  *      _bcm_trident_trunk_fabric_swfailover_trigger
   2952  * Purpose:
   2953  *      Delete failed port from Higig trunk config.
   2954  * Parameters:
   2955  *      unit  - (IN) SOC unit number. 
   2956  *      port  - (IN) Failed port number. 
   2957  *      hgtid - (IN) Higig trunk ID.
   2958  *      swf   - (IN) Pointer to software failover info.
   2959  * Returns:
   2960  *      BCM_E_xxx
   2961  */
   2962 STATIC int 
   2963 _bcm_trident_trunk_fabric_swfailover_trigger(int unit,
   2964         bcm_port_t port,
   2965         int hgtid,
   2966         _trident_trunk_swfail_t *swf)
   2967 {
   2968     bcm_trunk_chip_info_t chip_info;
   2969     _trident_tinfo_t *swft;
   2970     int i, j, nmp;
   2971     hg_trunk_group_entry_t  hg_trunk_group_entry;
   2972     hg_trunk_member_entry_t hg_trunk_member_entry;
   2973     hg_trunk_bitmap_entry_t hg_trunk_bitmap_entry;
   2974     int old_base_ptr, old_tg_size, old_rtag;
   2975     int max_base_ptr, base_ptr;
   2976     int num_entries, old_num_entries;
   2977     pbmp_t old_trunk_pbmp, new_trunk_pbmp;
   2978     SHR_BITDCL occupied;
   2979 #if defined(BCM_HGPROXY_COE_SUPPORT)
   2980     int entry_type = 0;
   2981 #endif
   2982     BCM_IF_ERROR_RETURN(bcm_esw_trunk_chip_info_get(unit, &chip_info));
   2983     swft = &swf->tinfo[hgtid + chip_info.trunk_group_count];
   2984 
   2985     /* update the _trident_trunk_swfail entry */
   2986     nmp = swft->num_ports;
   2987     for (i = j = 0; i < nmp; i++) {
   2988         if (swft->modport[i] != port) {
   2989             if (i != j) {
   2990                 swft->modport[j] = swft->modport[i];
   2991             }
   2992             j += 1;
   2993         }
   2994     }
   2995 
   2996     if (j == nmp) {
   2997         return BCM_E_NONE; /* no changes, so no need to write out */
   2998     }
   2999 
   3000     swft->num_ports = nmp = j;
   3001 
   3002     /* Update Higig trunk tables */
   3003 
   3004     SOC_IF_ERROR_RETURN
   3005         (READ_HG_TRUNK_GROUPm(unit, MEM_BLOCK_ANY, hgtid, &hg_trunk_group_entry));
   3006     old_base_ptr = soc_HG_TRUNK_GROUPm_field32_get(unit, &hg_trunk_group_entry, BASE_PTRf);
   3007     old_tg_size = 1 + soc_HG_TRUNK_GROUPm_field32_get(unit, &hg_trunk_group_entry, TG_SIZEf);
   3008     old_rtag = soc_HG_TRUNK_GROUPm_field32_get(unit, &hg_trunk_group_entry, RTAGf);
   3009 #if defined(BCM_HGPROXY_COE_SUPPORT)
   3010     if (soc_mem_field_valid(unit, HG_TRUNK_GROUPm, ENTRY_TYPEf)) {
   3011         entry_type = soc_HG_TRUNK_GROUPm_field32_get(unit, &hg_trunk_group_entry, ENTRY_TYPEf);
   3012     }
   3013 #endif
   3014 
   3015     if (nmp == 0) {
   3016         soc_HG_TRUNK_GROUPm_field32_set(unit, &hg_trunk_group_entry, BASE_PTRf, 0);
   3017         soc_HG_TRUNK_GROUPm_field32_set(unit, &hg_trunk_group_entry, TG_SIZEf, 0);
   3018         soc_HG_TRUNK_GROUPm_field32_set(unit, &hg_trunk_group_entry, RTAGf, swft->rtag);
   3019         SOC_IF_ERROR_RETURN
   3020             (WRITE_HG_TRUNK_GROUPm(unit, MEM_BLOCK_ALL, hgtid, &hg_trunk_group_entry));
   3021     } else {
   3022 
   3023         /* Find a contiguous region of HG_TRUNK_MEMBERm table that's large
   3024          * enough to hold all of the Higig trunk group's member ports.
   3025          */
   3026         num_entries = nmp;
   3027 
   3028         /* If RTAG is 1-6, Trident A0 and Katana ignore the TG_SIZE field and 
   3029          * assume the Higig trunk group occupies FABRIC_TRUNK_RTAG1_6_MAX_PORTCNT
   3030          * contiguous entries in HG_TRUNK_MEMBER table.
   3031          */
   3032         if (swft->rtag >= 1 && swft->rtag <= 6) {
   3033 #ifdef BCM_KATANA_SUPPORT
   3034             if(SOC_IS_KATANAX(unit)) {
   3035                 num_entries = _BCM_KATANA_FABRIC_TRUNK_RTAG1_6_MAX_PORTCNT;
   3036             } else
   3037 #endif
   3038             if (soc_feature(unit,
   3039                         soc_feature_rtag1_6_max_portcnt_less_than_rtag7)) { 
   3040                 num_entries = _BCM_TD_FABRIC_TRUNK_RTAG1_6_MAX_PORTCNT;
   3041             }
   3042         } 
   3043 
   3044         max_base_ptr = soc_mem_index_count(unit, HG_TRUNK_MEMBERm) - num_entries;
   3045         for (base_ptr = 0; base_ptr <= max_base_ptr; base_ptr++) {
   3046             /* Check if the contiguous region of HG_TRUNK_MEMBERm table from
   3047              * index base_ptr to (base_ptr + num_entries - 1) is free. 
   3048              */
   3049             _BCM_HG_TRUNK_MEMBER_TEST_RANGE(unit, base_ptr, num_entries, occupied); 
   3050             if (!occupied) {
   3051                 break;
   3052             }
   3053         }
   3054 
   3055         if (base_ptr > max_base_ptr) {
   3056             /* A contiguous region of the desired size could not be found in
   3057              * HG_TRUNK_MEMBERm table.
   3058              */
   3059             return BCM_E_RESOURCE;
   3060         }
   3061 
   3062         for (i = 0; i < num_entries; i++) {
   3063             sal_memset(&hg_trunk_member_entry, 0, sizeof(hg_trunk_member_entry_t));
   3064 #if defined(BCM_KATANA2_SUPPORT)
   3065             if (SOC_IS_KATANA2(unit)) {
   3066                 soc_HG_TRUNK_MEMBERm_field32_set(unit, &hg_trunk_member_entry,
   3067                         PHYSICAL_PORTf, swft->modport[i%nmp] & 0xff);
   3068                 soc_HG_TRUNK_MEMBERm_field32_set(unit, &hg_trunk_member_entry,
   3069                        PP_PORTf, swft->modport[i%nmp] & 0xff);
   3070             } else
   3071 #endif /*  (defined(BCM_KATANA2_SUPPORT)  */
   3072             {
   3073                 soc_HG_TRUNK_MEMBERm_field32_set
   3074                     (unit, &hg_trunk_member_entry, PORT_NUMf, swft->modport[i%nmp] & 0xff);
   3075             }
   3076             SOC_IF_ERROR_RETURN
   3077                 (WRITE_HG_TRUNK_MEMBERm(unit, MEM_BLOCK_ALL, base_ptr + i,
   3078                                         &hg_trunk_member_entry)); 
   3079         }
   3080 
   3081         /* Set hg_trunk_member_bitmap */
   3082         _BCM_HG_TRUNK_MEMBER_USED_SET_RANGE(unit, base_ptr, num_entries);
   3083 
   3084         soc_HG_TRUNK_GROUPm_field32_set
   3085             (unit, &hg_trunk_group_entry, BASE_PTRf, base_ptr);
   3086         soc_HG_TRUNK_GROUPm_field32_set
   3087             (unit, &hg_trunk_group_entry, TG_SIZEf, nmp-1);
   3088         soc_HG_TRUNK_GROUPm_field32_set
   3089             (unit, &hg_trunk_group_entry, RTAGf, swft->rtag);
   3090 #if defined(BCM_HGPROXY_COE_SUPPORT)
   3091         if (soc_mem_field_valid(unit, HG_TRUNK_GROUPm, ENTRY_TYPEf)) {
   3092             soc_HG_TRUNK_GROUPm_field32_set
   3093                              (unit, &hg_trunk_group_entry, ENTRY_TYPEf, entry_type);
   3094         }
   3095 #endif
   3096         SOC_IF_ERROR_RETURN
   3097             (WRITE_HG_TRUNK_GROUPm(unit, MEM_BLOCK_ALL, hgtid, &hg_trunk_group_entry));
   3098     }
   3099 
   3100     SOC_IF_ERROR_RETURN
   3101         (READ_HG_TRUNK_BITMAPm(unit, MEM_BLOCK_ANY, hgtid, &hg_trunk_bitmap_entry));
   3102     SOC_PBMP_CLEAR(old_trunk_pbmp);
   3103     soc_mem_pbmp_field_get(unit, HG_TRUNK_BITMAPm, &hg_trunk_bitmap_entry,
   3104             HIGIG_TRUNK_BITMAPf, &old_trunk_pbmp);
   3105 
   3106     SOC_PBMP_ASSIGN(new_trunk_pbmp, old_trunk_pbmp);
   3107     SOC_PBMP_PORT_REMOVE(new_trunk_pbmp, port);
   3108 
   3109     soc_mem_pbmp_field_set(unit, HG_TRUNK_BITMAPm, &hg_trunk_bitmap_entry,
   3110             HIGIG_TRUNK_BITMAPf, &new_trunk_pbmp);
   3111     SOC_IF_ERROR_RETURN
   3112         (WRITE_HG_TRUNK_BITMAPm(unit, MEM_BLOCK_ALL, hgtid, &hg_trunk_bitmap_entry));
   3113 
   3114     BCM_IF_ERROR_RETURN
   3115         (_bcm_trident_trunk_fabric_port_set(unit,
   3116                                             hgtid,
   3117                                             old_trunk_pbmp,
   3118                                             new_trunk_pbmp));
   3119 
   3120     /* Clear the previously used region in HG_TRUNK_MEMBERm and hg_trunk_member_bitmap. */
   3121     old_num_entries = old_tg_size;
   3122     if (old_rtag >= 1 && old_rtag <= 6) {
   3123 #ifdef BCM_KATANA_SUPPORT
   3124         if(SOC_IS_KATANAX(unit)) {
   3125             old_num_entries = _BCM_KATANA_FABRIC_TRUNK_RTAG1_6_MAX_PORTCNT;
   3126         } else
   3127 #endif
   3128         if (soc_feature(unit, soc_feature_rtag1_6_max_portcnt_less_than_rtag7)) { 
   3129             old_num_entries = _BCM_TD_FABRIC_TRUNK_RTAG1_6_MAX_PORTCNT;
   3130         }
   3131     } 
   3132     _BCM_HG_TRUNK_MEMBER_USED_CLR_RANGE(unit, old_base_ptr, old_num_entries);
   3133     for (i = 0; i < old_num_entries; i++) {
   3134         sal_memset(&hg_trunk_member_entry, 0, sizeof(hg_trunk_member_entry_t));
   3135         SOC_IF_ERROR_RETURN
   3136             (WRITE_HG_TRUNK_MEMBERm(unit, MEM_BLOCK_ALL, old_base_ptr + i,
   3137                                     soc_mem_entry_null(unit, HG_TRUNK_MEMBERm))); 
   3138     }
   3139 
   3140     return BCM_E_NONE;
   3141 }
   3142 
   3143 /*
   3144  * Function:
   3145  *      _bcm_trident_trunk_swfailover_nonuc_update
   3146  * Purpose:
   3147  *      Update non-unicast trunk block mask table for
   3148  *      software failover.
   3149  * Parameters:
   3150  *      unit           - (IN) SOC unit number. 
   3151  *      num_ports      - (IN) Number of ports remaining in the trunk group,
   3152  *                            excluding the failed port. 
   3153  *      swft           - (IN) Software failover trunk group info, excluding
   3154  *                            the failed port.
   3155  *      mymodid        - (IN) Local module ID.
   3156  *      old_trunk_pbmp - (IN) Trunk port bitmap before removing failed port.
   3157  *      new_trunk_pbmp - (IN) Trunk port bitmap after removing failed port.
   3158  * Returns:
   3159  *      BCM_E_xxx
   3160  */
   3161 STATIC int
   3162 _bcm_trident_trunk_swfailover_nonuc_update(int unit,
   3163         int num_ports,
   3164         _trident_tinfo_t *swft,
   3165         int mymodid,
   3166         pbmp_t old_trunk_pbmp,
   3167         pbmp_t new_trunk_pbmp)
   3168 {
   3169     int          rv = BCM_E_NONE;
   3170     bcm_module_t *mods = NULL;
   3171     int          i;
   3172     SHR_BITDCL   *nuc_tpbm = NULL;
   3173     SHR_BITDCL   *ipmc_tpbm = NULL;
   3174     SHR_BITDCL   *l2mc_tpbm = NULL;
   3175     SHR_BITDCL   *bcast_tpbm = NULL;
   3176     SHR_BITDCL   *dlf_tpbm = NULL;
   3177     SHR_BITDCL   *ipmc_my_modid_bmap = NULL;
   3178     SHR_BITDCL   *l2mc_my_modid_bmap = NULL;
   3179     SHR_BITDCL   *bcast_my_modid_bmap = NULL;
   3180     SHR_BITDCL   *dlf_my_modid_bmap = NULL;
   3181     uint32       ipmc_member_count;
   3182     uint32       l2mc_member_count;
   3183     uint32       bcast_member_count;
   3184     uint32       dlf_member_count;
   3185     bcm_port_t   loc_port;
   3186     int          *ipmc_localport_array = NULL;
   3187     int          *l2mc_localport_array = NULL;
   3188     int          *bcast_localport_array = NULL;
   3189     int          *dlf_localport_array = NULL;
   3190     int          ipmc_localport_count;
   3191     int          l2mc_localport_count;
   3192     int          bcast_localport_count;
   3193     int          dlf_localport_count;
   3194 
   3195     if (num_ports > 0) {
   3196         /* Derive a member bitmap of non-unicast eligible members */
   3197         mods = sal_alloc(sizeof(bcm_module_t) * num_ports, "mods");
   3198         if (mods == NULL) {
   3199             rv = BCM_E_MEMORY;
   3200             goto cleanup;
   3201         }
   3202         for (i = 0; i < num_ports; i++) {
   3203             mods[i] = swft->modport[i] >> 8;
   3204         }
   3205 
   3206         nuc_tpbm = sal_alloc(SHR_BITALLOCSIZE(num_ports), "nuc_tpbm");
   3207         if (nuc_tpbm == NULL) {
   3208             rv = BCM_E_MEMORY;
   3209             goto cleanup;
   3210         }
   3211         sal_memset(nuc_tpbm, 0, SHR_BITALLOCSIZE(num_ports));
   3212         rv = _bcm_trident_nuc_tpbm_get(unit, num_ports, mods, nuc_tpbm);
   3213         if (BCM_FAILURE(rv)) {
   3214             goto cleanup;
   3215         }
   3216 
   3217         /* Copy the non-unicast eligible member bitmap to IPMC, L2MC,
   3218          * broadcast, and DLF eligible member bitmaps.
   3219          */
   3220         ipmc_tpbm = sal_alloc(SHR_BITALLOCSIZE(num_ports), "ipmc_tpbm");
   3221         if (ipmc_tpbm == NULL) {
   3222             rv = BCM_E_MEMORY;
   3223             goto cleanup;
   3224         }
   3225         sal_memcpy(ipmc_tpbm, nuc_tpbm, SHR_BITALLOCSIZE(num_ports));
   3226 
   3227         l2mc_tpbm = sal_alloc(SHR_BITALLOCSIZE(num_ports), "l2mc_tpbm");
   3228         if (l2mc_tpbm == NULL) {
   3229             rv = BCM_E_MEMORY;
   3230             goto cleanup;
   3231         }
   3232         sal_memcpy(l2mc_tpbm, nuc_tpbm, SHR_BITALLOCSIZE(num_ports));
   3233 
   3234         bcast_tpbm = sal_alloc(SHR_BITALLOCSIZE(num_ports), "bcast_tpbm");
   3235         if (bcast_tpbm == NULL) {
   3236             rv = BCM_E_MEMORY;
   3237             goto cleanup;
   3238         }
   3239         sal_memcpy(bcast_tpbm, nuc_tpbm, SHR_BITALLOCSIZE(num_ports));
   3240 
   3241         dlf_tpbm = sal_alloc(SHR_BITALLOCSIZE(num_ports), "dlf_tpbm");
   3242         if (dlf_tpbm == NULL) {
   3243             rv = BCM_E_MEMORY;
   3244             goto cleanup;
   3245         }
   3246         sal_memcpy(dlf_tpbm, nuc_tpbm, SHR_BITALLOCSIZE(num_ports));
   3247 
   3248         /* Iterate through the trunk member list to get port bitmaps
   3249          * of IPMC/L2MC/BCAST/DLF eligible local members.
   3250          */
   3251         ipmc_my_modid_bmap = sal_alloc(SHR_BITALLOCSIZE(num_ports),
   3252                 "ipmc_my_modid_bmap");
   3253         if (ipmc_my_modid_bmap == NULL) {
   3254             rv = BCM_E_MEMORY;
   3255             goto cleanup;
   3256         }
   3257         sal_memset(ipmc_my_modid_bmap, 0, SHR_BITALLOCSIZE(num_ports));
   3258 
   3259         l2mc_my_modid_bmap = sal_alloc(SHR_BITALLOCSIZE(num_ports),
   3260                 "l2mc_my_modid_bmap");
   3261         if (l2mc_my_modid_bmap == NULL) {
   3262             rv = BCM_E_MEMORY;
   3263             goto cleanup;
   3264         }
   3265         sal_memset(l2mc_my_modid_bmap, 0, SHR_BITALLOCSIZE(num_ports));
   3266 
   3267         bcast_my_modid_bmap = sal_alloc(SHR_BITALLOCSIZE(num_ports),
   3268                 "bcast_my_modid_bmap");
   3269         if (bcast_my_modid_bmap == NULL) {
   3270             rv = BCM_E_MEMORY;
   3271             goto cleanup;
   3272         }
   3273         sal_memset(bcast_my_modid_bmap, 0, SHR_BITALLOCSIZE(num_ports));
   3274 
   3275         dlf_my_modid_bmap = sal_alloc(SHR_BITALLOCSIZE(num_ports),
   3276                 "dlf_my_modid_bmap");
   3277         if (dlf_my_modid_bmap == NULL) {
   3278             rv = BCM_E_MEMORY;
   3279             goto cleanup;
   3280         }
   3281         sal_memset(dlf_my_modid_bmap, 0, SHR_BITALLOCSIZE(num_ports));
   3282 
   3283         ipmc_localport_array = sal_alloc(num_ports * sizeof(int),
   3284                                          "ipmc_localport_array");
   3285         if (ipmc_localport_array == NULL) {
   3286             rv = BCM_E_MEMORY;
   3287             goto cleanup;
   3288         }
   3289         sal_memset(ipmc_localport_array, 0, num_ports * sizeof(int));
   3290         l2mc_localport_array = sal_alloc(num_ports * sizeof(int),
   3291                                          "l2mc_localport_array");
   3292         if (l2mc_localport_array == NULL) {
   3293             rv = BCM_E_MEMORY;
   3294             goto cleanup;
   3295         }
   3296         sal_memset(l2mc_localport_array, 0, num_ports * sizeof(int));
   3297         bcast_localport_array = sal_alloc(num_ports * sizeof(int),
   3298                                           "bcast_localport_array");
   3299         if (bcast_localport_array == NULL) {
   3300             rv = BCM_E_MEMORY;
   3301             goto cleanup;
   3302         }
   3303         sal_memset(bcast_localport_array, 0, num_ports * sizeof(int));
   3304         dlf_localport_array = sal_alloc(num_ports * sizeof(int),
   3305                                         "dlf_localport_array");
   3306         if (dlf_localport_array == NULL) {
   3307             rv = BCM_E_MEMORY;
   3308             goto cleanup;
   3309         }
   3310         sal_memset(dlf_localport_array, 0, num_ports * sizeof(int));
   3311         
   3312         ipmc_member_count = 0;
   3313         l2mc_member_count = 0;
   3314         bcast_member_count = 0;
   3315         dlf_member_count = 0;
   3316         ipmc_localport_count = 0;
   3317         l2mc_localport_count = 0;
   3318         bcast_localport_count = 0;
   3319         dlf_localport_count = 0;
   3320 
   3321         for (i= 0; i < num_ports; i++) {
   3322             if (swft->member_flags[i] &
   3323                     BCM_TRUNK_MEMBER_IPMC_EGRESS_DISABLE) {
   3324                 SHR_BITCLR(ipmc_tpbm, i);
   3325             }
   3326             if (swft->member_flags[i] &
   3327                     BCM_TRUNK_MEMBER_L2MC_EGRESS_DISABLE) {
   3328                 SHR_BITCLR(l2mc_tpbm, i);
   3329             }
   3330             if (swft->member_flags[i] &
   3331                     BCM_TRUNK_MEMBER_BCAST_EGRESS_DISABLE) {
   3332                 SHR_BITCLR(bcast_tpbm, i);
   3333             }
   3334             if (swft->member_flags[i] &
   3335                     BCM_TRUNK_MEMBER_DLF_EGRESS_DISABLE) {
   3336                 SHR_BITCLR(dlf_tpbm, i);
   3337             }
   3338 
   3339             if (mymodid == (swft->modport[i] >> 8)) {
   3340                 /* local port */
   3341                 loc_port = swft->modport[i] & 0xff;
   3342                 if (SHR_BITGET(ipmc_tpbm, i)) {
   3343                     ipmc_localport_array[ipmc_localport_count++] = loc_port;
   3344                     SHR_BITSET(ipmc_my_modid_bmap, ipmc_member_count);
   3345                 }
   3346                 if (SHR_BITGET(l2mc_tpbm, i)) {
   3347                     l2mc_localport_array[l2mc_localport_count++] = loc_port;
   3348                     SHR_BITSET(l2mc_my_modid_bmap, l2mc_member_count);
   3349                 }
   3350                 if (SHR_BITGET(bcast_tpbm, i)) {
   3351                     bcast_localport_array[bcast_localport_count++] = loc_port;
   3352                     SHR_BITSET(bcast_my_modid_bmap, bcast_member_count);
   3353                 }
   3354                 if (SHR_BITGET(dlf_tpbm, i)) {
   3355                     dlf_localport_array[dlf_localport_count++] = loc_port;
   3356                     SHR_BITSET(dlf_my_modid_bmap, dlf_member_count);
   3357                 }
   3358             }
   3359 
   3360             if (SHR_BITGET(ipmc_tpbm, i)) {
   3361                 /* Eligible for IPMC forwarding */
   3362                 ipmc_member_count++;
   3363             }
   3364             if (SHR_BITGET(l2mc_tpbm, i)) {
   3365                 /* Eligible for L2MC forwarding */
   3366                 l2mc_member_count++;
   3367             }
   3368             if (SHR_BITGET(bcast_tpbm, i)) {
   3369                 /* Eligible for broadcast forwarding */
   3370                 bcast_member_count++;
   3371             }
   3372             if (SHR_BITGET(dlf_tpbm, i)) {
   3373                 /* Eligible for DLF forwarding */
   3374                 dlf_member_count++;
   3375             }
   3376         }
   3377 
   3378         /* Update trunk block masks */
   3379         rv = _bcm_trident_trunk_block_mask(unit,
   3380                 TRUNK_BLOCK_MASK_TYPE_IPMC,
   3381                 old_trunk_pbmp,
   3382                 new_trunk_pbmp,
   3383                 ipmc_localport_array,
   3384                 ipmc_localport_count,
   3385                 ipmc_my_modid_bmap,
   3386                 ipmc_member_count,
   3387                 swft->flags);
   3388         if (BCM_FAILURE(rv)) {
   3389             goto cleanup;
   3390         }
   3391         rv = _bcm_trident_trunk_block_mask(unit,
   3392                 TRUNK_BLOCK_MASK_TYPE_L2MC,
   3393                 old_trunk_pbmp,
   3394                 new_trunk_pbmp,
   3395                 l2mc_localport_array,
   3396                 l2mc_localport_count,
   3397                 l2mc_my_modid_bmap,
   3398                 l2mc_member_count,
   3399                 swft->flags);
   3400         if (BCM_FAILURE(rv)) {
   3401             goto cleanup;
   3402         }
   3403         rv = _bcm_trident_trunk_block_mask(unit,
   3404                 TRUNK_BLOCK_MASK_TYPE_BCAST,
   3405                 old_trunk_pbmp,
   3406                 new_trunk_pbmp,
   3407                 bcast_localport_array,
   3408                 bcast_localport_count,
   3409                 bcast_my_modid_bmap,
   3410                 bcast_member_count,
   3411                 swft->flags);
   3412         if (BCM_FAILURE(rv)) {
   3413             goto cleanup;
   3414         }
   3415         rv = _bcm_trident_trunk_block_mask(unit,
   3416                 TRUNK_BLOCK_MASK_TYPE_DLF,
   3417                 old_trunk_pbmp,
   3418                 new_trunk_pbmp,
   3419                 dlf_localport_array,
   3420                 dlf_localport_count,
   3421                 dlf_my_modid_bmap,
   3422                 dlf_member_count,
   3423                 swft->flags);
   3424         if (BCM_FAILURE(rv)) {
   3425             goto cleanup;
   3426         }
   3427     } else {
   3428         rv = _bcm_trident_trunk_block_mask(unit, 
   3429                 TRUNK_BLOCK_MASK_TYPE_IPMC,
   3430                 old_trunk_pbmp,
   3431                 new_trunk_pbmp,   
   3432                 NULL, 0,
   3433                 NULL,
   3434                 0,
   3435                 swft->flags);
   3436         if (BCM_FAILURE(rv)) {
   3437             goto cleanup;
   3438         }
   3439         rv = _bcm_trident_trunk_block_mask(unit, 
   3440                 TRUNK_BLOCK_MASK_TYPE_L2MC,
   3441                 old_trunk_pbmp,
   3442                 new_trunk_pbmp,   
   3443                 NULL, 0,
   3444                 NULL,
   3445                 0,
   3446                 swft->flags);
   3447         if (BCM_FAILURE(rv)) {
   3448             goto cleanup;
   3449         }
   3450         rv = _bcm_trident_trunk_block_mask(unit, 
   3451                 TRUNK_BLOCK_MASK_TYPE_BCAST,
   3452                 old_trunk_pbmp,
   3453                 new_trunk_pbmp,   
   3454                 NULL, 0,
   3455                 NULL,
   3456                 0,
   3457                 swft->flags);
   3458         if (BCM_FAILURE(rv)) {
   3459             goto cleanup;
   3460         }
   3461         rv = _bcm_trident_trunk_block_mask(unit, 
   3462                 TRUNK_BLOCK_MASK_TYPE_DLF,
   3463                 old_trunk_pbmp,
   3464                 new_trunk_pbmp,   
   3465                 NULL, 0,
   3466                 NULL,
   3467                 0,
   3468                 swft->flags);
   3469         if (BCM_FAILURE(rv)) {
   3470             goto cleanup;
   3471         }
   3472     }
   3473 
   3474 #if defined(BCM_TRIUMPH3_SUPPORT) && defined(INCLUDE_L3)
   3475     if (soc_feature(unit, soc_feature_axp)) {
   3476         rv = _bcm_tr3_wlan_trunk_block_mask_update(unit);
   3477         if (BCM_FAILURE(rv)) {
   3478             goto cleanup;
   3479         }
   3480     }
   3481 #endif /* BCM_TRIUMPH3_SUPPORT && defined(INCLUDE_L3) */
   3482 
   3483 
   3484 cleanup:
   3485     if (mods) {
   3486         sal_free(mods);
   3487     }                          
   3488     if (nuc_tpbm) {
   3489         sal_free(nuc_tpbm);
   3490     }
   3491     if (ipmc_tpbm) {
   3492         sal_free(ipmc_tpbm);
   3493     }
   3494     if (l2mc_tpbm) {
   3495         sal_free(l2mc_tpbm);
   3496     }
   3497     if (bcast_tpbm) {
   3498         sal_free(bcast_tpbm);
   3499     }
   3500     if (dlf_tpbm) {
   3501         sal_free(dlf_tpbm);
   3502     }
   3503     if (ipmc_my_modid_bmap) {
   3504         sal_free(ipmc_my_modid_bmap);
   3505     }
   3506     if (l2mc_my_modid_bmap) {
   3507         sal_free(l2mc_my_modid_bmap);
   3508     }
   3509     if (bcast_my_modid_bmap) {
   3510         sal_free(bcast_my_modid_bmap);
   3511     }
   3512     if (dlf_my_modid_bmap) {
   3513         sal_free(dlf_my_modid_bmap);
   3514     }
   3515     if (ipmc_localport_array) {
   3516         sal_free(ipmc_localport_array);
   3517     }
   3518     if (l2mc_localport_array) {
   3519         sal_free(l2mc_localport_array);
   3520     }
   3521     if (bcast_localport_array) {
   3522         sal_free(bcast_localport_array);
   3523     }
   3524     if (dlf_localport_array) {
   3525         sal_free(dlf_localport_array);
   3526     }
   3527 
   3528     return rv;
   3529 }
   3530 
   3531 /*
   3532  * Function:
   3533  *      _bcm_trident_trunk_swfailover_trigger
   3534  * Purpose:
   3535  *      Delete failed port from trunk config.
   3536  * Parameters:
   3537  *      unit  - (IN) SOC unit number. 
   3538  *      ports_active - (IN) Port bitmap of active ports. 
   3539  *      ports_status - (IN) Bitmap of ports status. 
   3540  * Returns:
   3541  *      BCM_E_xxx
   3542  */
   3543 int
   3544 _bcm_trident_trunk_swfailover_trigger(int unit,
   3545         bcm_pbmp_t ports_active,
   3546         bcm_pbmp_t ports_status)
   3547 {
   3548     bcm_trunk_chip_info_t chip_info;
   3549     bcm_port_t           port;
   3550     int                  tid;
   3551     _trident_trunk_swfail_t *swf;
   3552     _trident_tinfo_t        *swft;
   3553     int fabric_trunk_swf_tid_offset;
   3554 
   3555     swf = _trident_trunk_swfail[unit];
   3556 
   3557     if (swf == NULL) {
   3558         return BCM_E_NONE;
   3559     }
   3560 
   3561     BCM_IF_ERROR_RETURN(bcm_esw_trunk_chip_info_get(unit, &chip_info));
   3562     fabric_trunk_swf_tid_offset = chip_info.trunk_group_count + 1;
   3563 
   3564     PBMP_ITER(ports_active, port) {
   3565         if (BCM_PBMP_MEMBER(ports_status, port)) {
   3566             continue;   /* link up */
   3567         }
   3568 
   3569         /* link down */
   3570         tid = swf->trunk[port];
   3571         swf->trunk[port] = 0;
   3572         if (tid <= 0) {
   3573             continue;   /* already removed */
   3574         }        
   3575 
   3576         if (tid >= 1 && tid <= chip_info.trunk_group_count) {
   3577             pbmp_t               new_trunk_pbmp;
   3578             pbmp_t               old_trunk_pbmp;
   3579             uint16               modport;
   3580             int                  i, j, nmp, rv;
   3581             int                  uc_nmp;
   3582             int                  old_base_ptr, old_tg_size, old_rtag;
   3583             int                  max_base_ptr, base_ptr;
   3584             int                  num_entries, old_num_entries;
   3585             SHR_BITDCL           occupied;
   3586             trunk_member_entry_t trunk_member_entry;
   3587             trunk_group_entry_t  tg_entry;
   3588             trunk_bitmap_entry_t trunk_bitmap_entry;
   3589             uint16               *uc_modport = NULL;
   3590 
   3591             tid = tid - 1;
   3592             swft = &swf->tinfo[tid];
   3593             SOC_PBMP_CLEAR(new_trunk_pbmp);
   3594 
   3595             /* update _trident_trunk_swfail: remove matching ports, update size */
   3596 
   3597             modport = (swf->mymodid << 8) | port;
   3598             nmp = swft->num_ports;
   3599 
   3600             for (i = j = 0; i < nmp; i++) {
   3601                 if (swft->modport[i] != modport) {
   3602                     if (i != j) {
   3603                         swft->modport[j] = swft->modport[i];
   3604                         swft->member_flags[j] = swft->member_flags[i];
   3605                     }
   3606                     j += 1;
   3607                 }
   3608             }
   3609             if (j == nmp) {
   3610                 continue;       /* no changes, so no need to write out */
   3611             }
   3612             swft->num_ports = nmp = j;
   3613 
   3614             /* Get unicast egress trunk member ports */
   3615             uc_modport = sal_alloc(sizeof(uint16) * nmp, "uc_modport");
   3616             if (uc_modport == NULL) {
   3617                 return BCM_E_MEMORY;
   3618             }
   3619             uc_nmp = 0;
   3620             for (i = 0; i < nmp; i++) {
   3621                 if (swft->member_flags[i] &
   3622                         BCM_TRUNK_MEMBER_UNICAST_EGRESS_DISABLE) {
   3623                     continue;
   3624                 }
   3625                 uc_modport[uc_nmp++] = swft->modport[i];
   3626             }
   3627 
   3628             /* Convert _trident_trunk_swfail into trunk_group, trunk_member,
   3629              * and trunk_bitmap tables
   3630              */
   3631             rv = READ_TRUNK_GROUPm(unit, MEM_BLOCK_ANY, tid, &tg_entry);
   3632             if (BCM_FAILURE(rv)) {
   3633                 sal_free(uc_modport);
   3634                 return rv;
   3635             }
   3636             old_base_ptr = soc_TRUNK_GROUPm_field32_get(unit, &tg_entry,
   3637                     BASE_PTRf);
   3638             old_tg_size = 1 + soc_TRUNK_GROUPm_field32_get(unit, &tg_entry,
   3639                     TG_SIZEf);
   3640             old_rtag = soc_TRUNK_GROUPm_field32_get(unit, &tg_entry, RTAGf);
   3641 
   3642             if (uc_nmp == 0) {
   3643                 soc_TRUNK_GROUPm_field32_set(unit, &tg_entry, BASE_PTRf, 0);
   3644                 soc_TRUNK_GROUPm_field32_set(unit, &tg_entry, TG_SIZEf, 0);
   3645                 soc_TRUNK_GROUPm_field32_set(unit, &tg_entry, RTAGf, 0);
   3646                 rv = WRITE_TRUNK_GROUPm(unit, MEM_BLOCK_ALL, tid, &tg_entry);
   3647                 if (BCM_FAILURE(rv)) {
   3648                     sal_free(uc_modport);
   3649                     return rv;
   3650                 }
   3651             } else {
   3652                 /* Find a contiguous region of TRUNK_MEMBERm table that's large
   3653                  * enough to hold all of the trunk group's member ports.
   3654                  */
   3655                 num_entries = uc_nmp;
   3656 
   3657                 /* If RTAG is 1-6, Trident A0 and Katana ignore the TG_SIZE field 
   3658                  * and assume the trunk group occupies FP_TRUNK_RTAG1_6_MAX_PORTCNT
   3659                  * contiguous entries in TRUNK_MEMBER table.
   3660                  */
   3661                 if (swft->rtag >= 1 && swft->rtag <= 6) {
   3662 #ifdef BCM_KATANA_SUPPORT
   3663                     if(SOC_IS_KATANAX(unit)) {
   3664                         num_entries = _BCM_KATANA_FP_TRUNK_RTAG1_6_MAX_PORTCNT;
   3665                     } else
   3666 #endif
   3667                     if (soc_feature(unit,
   3668                                 soc_feature_rtag1_6_max_portcnt_less_than_rtag7)) { 
   3669                         num_entries = _BCM_TD_FP_TRUNK_RTAG1_6_MAX_PORTCNT;
   3670                     }
   3671                 } 
   3672 
   3673                 max_base_ptr = soc_mem_index_count(unit, TRUNK_MEMBERm) - num_entries;
   3674                 for (base_ptr = 0; base_ptr <= max_base_ptr; base_ptr++) {
   3675                     /* Check if the contiguous region of TRUNK_MEMBERm table from
   3676                      * index base_ptr to (base_ptr + num_entries - 1) is free. 
   3677                      */
   3678                     _BCM_FP_TRUNK_MEMBER_TEST_RANGE(unit, base_ptr, num_entries, occupied); 
   3679                     if (!occupied) {
   3680                         break;
   3681                     }
   3682                 }
   3683 
   3684                 if (base_ptr > max_base_ptr) {
   3685                     /* A contiguous region of the desired size could not be found in
   3686                      * TRUNK_MEMBERm table.
   3687                      */
   3688                     sal_free(uc_modport);
   3689                     return BCM_E_RESOURCE;
   3690                 }
   3691 
   3692                 for (i = 0; i < num_entries; i++) {
   3693                     sal_memset(&trunk_member_entry, 0, sizeof(trunk_member_entry_t));
   3694                     soc_TRUNK_MEMBERm_field32_set(unit, &trunk_member_entry,
   3695                             MODULE_IDf, uc_modport[i%uc_nmp] >> 8);
   3696                     soc_TRUNK_MEMBERm_field32_set(unit, &trunk_member_entry,
   3697                             PORT_NUMf, uc_modport[i%uc_nmp] & 0xff);
   3698                     rv = WRITE_TRUNK_MEMBERm(unit, MEM_BLOCK_ALL, base_ptr + i,
   3699                             &trunk_member_entry); 
   3700                     if (BCM_FAILURE(rv)) {
   3701                         sal_free(uc_modport);
   3702                         return rv;
   3703                     }
   3704                 }
   3705 
   3706                 /* Set fp_trunk_member_bitmap */
   3707                 _BCM_FP_TRUNK_MEMBER_USED_SET_RANGE(unit, base_ptr, num_entries);
   3708 
   3709                 soc_TRUNK_GROUPm_field32_set(unit, &tg_entry, BASE_PTRf, base_ptr);
   3710                 soc_TRUNK_GROUPm_field32_set(unit, &tg_entry, TG_SIZEf, uc_nmp-1);
   3711                 soc_TRUNK_GROUPm_field32_set(unit, &tg_entry, RTAGf, swft->rtag);
   3712                 rv = WRITE_TRUNK_GROUPm(unit, MEM_BLOCK_ALL, tid, &tg_entry);
   3713                 if (BCM_FAILURE(rv)) {
   3714                     sal_free(uc_modport);
   3715                     return rv;
   3716                 }
   3717             }
   3718 
   3719             sal_free(uc_modport);
   3720             uc_modport = NULL;
   3721 
   3722             rv = READ_TRUNK_BITMAPm(unit, MEM_BLOCK_ANY, tid, &trunk_bitmap_entry);
   3723             if (BCM_FAILURE(rv)) {
   3724                 return rv;
   3725             }
   3726             SOC_PBMP_CLEAR(old_trunk_pbmp);
   3727             soc_mem_pbmp_field_get(unit, TRUNK_BITMAPm, &trunk_bitmap_entry,
   3728                     TRUNK_BITMAPf, &old_trunk_pbmp);
   3729 
   3730             SOC_PBMP_ASSIGN(new_trunk_pbmp, old_trunk_pbmp);
   3731             SOC_PBMP_PORT_REMOVE(new_trunk_pbmp, port);
   3732             soc_mem_pbmp_field_set(unit, TRUNK_BITMAPm, &trunk_bitmap_entry,
   3733                     TRUNK_BITMAPf, &new_trunk_pbmp);
   3734             rv = WRITE_TRUNK_BITMAPm(unit, MEM_BLOCK_ALL, tid, &trunk_bitmap_entry);
   3735             if (BCM_FAILURE(rv)) {
   3736                 return rv;
   3737             }
   3738 
   3739             /* Update SOURCE_TRUNK_MAP table */
   3740             rv = _bcm_trident_trunk_set_port_property(unit, swf->mymodid, port, -1);
   3741             if (BCM_FAILURE(rv)) {
   3742                 return rv;
   3743             }
   3744 
   3745             /* Clear the previously used region in TRUNK_MEMBERm and fp_trunk_member_bitmap. */
   3746             if (old_rtag != 0) {
   3747                 old_num_entries = old_tg_size;
   3748                 if (old_rtag >= 1 && old_rtag <= 6) {
   3749 #ifdef BCM_KATANA_SUPPORT
   3750                     if (SOC_IS_KATANAX(unit)) {
   3751                         old_num_entries = _BCM_KATANA_FP_TRUNK_RTAG1_6_MAX_PORTCNT;
   3752                     } else
   3753 #endif
   3754                     if (soc_feature(unit,
   3755                                 soc_feature_rtag1_6_max_portcnt_less_than_rtag7)) { 
   3756                         old_num_entries = _BCM_TD_FP_TRUNK_RTAG1_6_MAX_PORTCNT;
   3757                     }
   3758                 }
   3759 
   3760                 _BCM_FP_TRUNK_MEMBER_USED_CLR_RANGE(unit, old_base_ptr, old_num_entries);
   3761                 for (i = 0; i < old_num_entries; i++) {
   3762                     rv = WRITE_TRUNK_MEMBERm(unit, MEM_BLOCK_ALL, old_base_ptr + i,
   3763                             soc_mem_entry_null(unit, TRUNK_MEMBERm)); 
   3764                     if (BCM_FAILURE(rv)) {
   3765                         return rv;
   3766                     }
   3767                 }
   3768             }
   3769 
   3770             /* update non uc trunk block mask table */
   3771             rv = _bcm_trident_trunk_swfailover_nonuc_update(unit, nmp, swft,
   3772                     swf->mymodid, old_trunk_pbmp, new_trunk_pbmp);
   3773             if (BCM_FAILURE(rv)) {
   3774                 return rv;
   3775             }
   3776 
   3777         } else if ((tid >= fabric_trunk_swf_tid_offset) && 
   3778                 (tid <= (chip_info.trunk_fabric_id_max + 1))) {
   3779             /* higig trunk */
   3780             BCM_IF_ERROR_RETURN(
   3781                     _bcm_trident_trunk_fabric_swfailover_trigger
   3782                     (unit,
   3783                      port,
   3784                      tid - fabric_trunk_swf_tid_offset,
   3785                      swf));
   3786         }
   3787     }
   3788 
   3789     return BCM_E_NONE;
   3790 }
   3791 #endif /* BCM_TRUNK_FAILOVER_SUPPORT */
   3792 
   3793 /* ----------------------------------------------------------------------------- 
   3794  *
   3795  * Routines for front panel trunking 
   3796  *
   3797  * ----------------------------------------------------------------------------- 
   3798  */
   3799 
   3800 /*
   3801  * Function:
   3802  *      _bcm_trident_lag_slb_free_resource
   3803  * Purpose:
   3804  *      Free resources for a LAG static load balancing group.
   3805  * Parameters:
   3806  *      unit  - (IN) SOC unit number. 
   3807  *      tid - (IN) Trunk group ID.
   3808  * Returns:
   3809  *      BCM_E_xxx
   3810  */
   3811 STATIC int
   3812 _bcm_trident_lag_slb_free_resource(int unit, int tid)
   3813 {
   3814     trunk_group_entry_t tg_entry;
   3815     int base_ptr;
   3816     int tg_size;
   3817     int rtag;
   3818     int num_entries;
   3819     int trunk_mode = 0;
   3820  
   3821     SOC_IF_ERROR_RETURN
   3822         (READ_TRUNK_GROUPm(unit, MEM_BLOCK_ANY, tid, &tg_entry));
   3823     base_ptr = soc_TRUNK_GROUPm_field32_get(unit, &tg_entry,
   3824             BASE_PTRf);
   3825     tg_size = 1 + soc_TRUNK_GROUPm_field32_get(unit, &tg_entry,
   3826             TG_SIZEf);
   3827     rtag = soc_TRUNK_GROUPm_field32_get(unit, &tg_entry,
   3828             RTAGf);
   3829     if (soc_mem_field_valid(unit, TRUNK_GROUPm, TRUNK_MODEf)) {
   3830         trunk_mode = soc_TRUNK_GROUPm_field32_get(unit, &tg_entry,
   3831                      TRUNK_MODEf);
   3832     }
   3833 
   3834     if ((rtag != 0) || (trunk_mode != 0)) {
   3835         num_entries = tg_size;
   3836         if (rtag >= 1 && rtag <= 6) {
   3837 #ifdef BCM_KATANA_SUPPORT
   3838             if (SOC_IS_KATANAX(unit)) {
   3839                 num_entries = _BCM_KATANA_FP_TRUNK_RTAG1_6_MAX_PORTCNT;
   3840             } else
   3841 #endif
   3842             if (soc_feature(unit,
   3843                         soc_feature_rtag1_6_max_portcnt_less_than_rtag7)) { 
   3844                 num_entries = _BCM_TD_FP_TRUNK_RTAG1_6_MAX_PORTCNT;
   3845             }
   3846         } 
   3847 
   3848         _BCM_FP_TRUNK_MEMBER_USED_CLR_RANGE(unit, base_ptr, num_entries);
   3849     }
   3850 
   3851     return BCM_E_NONE;
   3852 }
   3853 
   3854 /*
   3855  * Function:
   3856  *      _bcm_trident_lag_slb_set
   3857  * Purpose:
   3858  *      Configure a LAG static load balancing group.
   3859  * Parameters:
   3860  *      unit  - (IN) SOC unit number. 
   3861  *      tid   - (IN) Trunk group ID.
   3862  *      num_uc_egr_ports - (IN) Number of trunk member ports eligible for
   3863  *                              unicast egress
   3864  *      uc_egr_hwmod  - (IN) Array of module IDs
   3865  *      uc_egr_hwport - (IN) Array of port IDs
   3866  *      t_info        - (IN) Pointer to trunk info.
   3867  * Returns:
   3868  *      BCM_E_xxx
   3869  */
   3870 STATIC int
   3871 _bcm_trident_lag_slb_set(int unit, int tid, int num_uc_egr_ports,
   3872         int *uc_egr_hwmod, int *uc_egr_hwport, trunk_private_t *t_info)
   3873 {
   3874     int i;
   3875     int num_entries;
   3876     int max_base_ptr;
   3877     int base_ptr;
   3878     SHR_BITDCL occupied;
   3879     trunk_member_entry_t trunk_member_entry;
   3880     trunk_group_entry_t  tg_entry;
   3881 #ifdef BCM_TOMAHAWK_SUPPORT
   3882     trunk_rr_cnt_entry_t rrlb_cnt_entry;
   3883     uint16 seed=0;
   3884     soc_reg_t reg;
   3885     uint32 rval;
   3886     int pipe;
   3887 #endif
   3888 
   3889     if (num_uc_egr_ports == 0) {
   3890         SOC_IF_ERROR_RETURN
   3891             (READ_TRUNK_GROUPm(unit, MEM_BLOCK_ANY, tid, &tg_entry));
   3892         soc_TRUNK_GROUPm_field32_set(unit, &tg_entry, BASE_PTRf, 0);
   3893         soc_TRUNK_GROUPm_field32_set(unit, &tg_entry, TG_SIZEf, 0);
   3894         soc_TRUNK_GROUPm_field32_set(unit, &tg_entry, RTAGf, 0);
   3895         SOC_IF_ERROR_RETURN
   3896             (WRITE_TRUNK_GROUPm(unit, MEM_BLOCK_ALL, tid, &tg_entry));
   3897         return BCM_E_NONE;
   3898     }
   3899 
   3900     /* Find a contiguous region of TRUNK_MEMBERm table that's large
   3901      * enough to hold all of the trunk group's egress member ports.
   3902      */
   3903 
   3904     num_entries = num_uc_egr_ports;
   3905 
   3906     /* If RTAG is 1-6, Trident A0 and Katana ignore the TG_SIZE field and 
   3907      * assume the trunk group occupies FP_TRUNK_RTAG1_6_MAX_PORTCNT
   3908      * contiguous entries in TRUNK_MEMBER table.
   3909      */
   3910     if (t_info->rtag >= 1 && t_info->rtag <= 6) {
   3911 #ifdef BCM_KATANA_SUPPORT
   3912         if (SOC_IS_KATANAX(unit)) {
   3913             num_entries = _BCM_KATANA_FP_TRUNK_RTAG1_6_MAX_PORTCNT;
   3914         } else
   3915 #endif
   3916         if (soc_feature(unit,
   3917                     soc_feature_rtag1_6_max_portcnt_less_than_rtag7)) { 
   3918             num_entries = _BCM_TD_FP_TRUNK_RTAG1_6_MAX_PORTCNT;
   3919         }
   3920     } 
   3921 
   3922     max_base_ptr = soc_mem_index_count(unit, TRUNK_MEMBERm) - num_entries;
   3923     for (base_ptr = 0; base_ptr <= max_base_ptr; base_ptr++) {
   3924         /* Check if the contiguous region of TRUNK_MEMBERm table from
   3925          * index base_ptr to (base_ptr + num_entries - 1) is free. 
   3926          */
   3927         _BCM_FP_TRUNK_MEMBER_TEST_RANGE(unit, base_ptr, num_entries, occupied); 
   3928         if (!occupied) {
   3929             break;
   3930         }
   3931     }
   3932 
   3933     if (base_ptr > max_base_ptr) {
   3934         /* A contiguous region of the desired size could not be found in
   3935          * TRUNK_MEMBERm table.
   3936          */
   3937         return BCM_E_RESOURCE;
   3938     }
   3939 
   3940     for (i = 0; i < num_entries; i++) {
   3941         sal_memset(&trunk_member_entry, 0, sizeof(trunk_member_entry_t));
   3942         soc_TRUNK_MEMBERm_field32_set
   3943             (unit, &trunk_member_entry, MODULE_IDf,
   3944              uc_egr_hwmod[i % num_uc_egr_ports]);
   3945         soc_TRUNK_MEMBERm_field32_set
   3946             (unit, &trunk_member_entry, PORT_NUMf,
   3947              uc_egr_hwport[i % num_uc_egr_ports]);
   3948         SOC_IF_ERROR_RETURN(WRITE_TRUNK_MEMBERm(unit, MEM_BLOCK_ALL,
   3949                     base_ptr + i, &trunk_member_entry)); 
   3950     }
   3951 
   3952     /* Set fp_trunk_member_bitmap */
   3953     _BCM_FP_TRUNK_MEMBER_USED_SET_RANGE(unit, base_ptr, num_entries);
   3954 
   3955     /* Update TRUNK_GROUP table */
   3956 
   3957     SOC_IF_ERROR_RETURN
   3958         (READ_TRUNK_GROUPm(unit, MEM_BLOCK_ANY, tid, &tg_entry));
   3959     soc_TRUNK_GROUPm_field32_set(unit, &tg_entry, BASE_PTRf, base_ptr);
   3960     soc_TRUNK_GROUPm_field32_set(unit, &tg_entry, TG_SIZEf,
   3961             num_uc_egr_ports-1);
   3962     soc_TRUNK_GROUPm_field32_set(unit, &tg_entry, RTAGf, t_info->rtag);
   3963 
   3964 #ifdef BCM_APACHE_SUPPORT
   3965     if (t_info->psc == BCM_TRUNK_PSC_ROUND_ROBIN) {
   3966         if (soc_feature(unit, soc_feature_apache_round_robin_fp_lag)) {
   3967            soc_TRUNK_GROUPm_field32_set(unit, &tg_entry, RR_LB_ENABLEf, 0x1);
   3968            soc_TRUNK_GROUPm_field32_set(unit, &tg_entry, RR_LB_COUNTER_SELECTf, t_info->rr_lag_select);
   3969         }
   3970     }
   3971 #endif /* BCM_APACHE_SUPPORT  */
   3972 
   3973 #ifdef BCM_TOMAHAWK_SUPPORT
   3974     if (t_info->psc == BCM_TRUNK_PSC_ROUND_ROBIN) {
   3975         if (soc_feature(unit, soc_feature_round_robin_load_balance)) {
   3976            soc_TRUNK_GROUPm_field32_set(unit, &tg_entry, TRUNK_MODEf, 0x2);
   3977 
   3978             BCM_IF_ERROR_RETURN(READ_TRUNK_RR_CNTm(unit, MEM_BLOCK_ANY,
   3979                     tid, &rrlb_cnt_entry));
   3980             soc_TRUNK_RR_CNTm_field32_set(unit, &rrlb_cnt_entry,
   3981                             RRLB_CNTf, 0);
   3982             BCM_IF_ERROR_RETURN(WRITE_TRUNK_RR_CNTm(unit, MEM_BLOCK_ALL,
   3983                             tid, &rrlb_cnt_entry));
   3984         }
   3985     } else if (t_info->psc == BCM_TRUNK_PSC_RANDOMIZED) {
   3986         if (soc_feature(unit, soc_feature_randomized_load_balance)) {
   3987            soc_TRUNK_GROUPm_field32_set(unit, &tg_entry, TRUNK_MODEf, 0x1);
   3988            /* Configure Rand LB Seed */
   3989             seed = (sal_rand()) % 0xFFFF;
   3990             rval = 0;
   3991             for (pipe = 0; pipe < NUM_PIPE(unit); pipe++) {
   3992                 reg = SOC_REG_UNIQUE_ACC(unit, TRUNK_RAND_LB_SEEDr)[pipe];
   3993                 soc_reg_field_set(unit, reg, &rval, SEEDf, seed);
   3994                 SOC_IF_ERROR_RETURN
   3995                     (soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval));
   3996             }
   3997         }
   3998     } else if (t_info->psc != BCM_TRUNK_PSC_DYNAMIC_RESILIENT) {
   3999         if (soc_mem_field_valid(unit, TRUNK_GROUPm, TRUNK_MODEf)) {
   4000             soc_TRUNK_GROUPm_field32_set(unit, &tg_entry, TRUNK_MODEf, 0x0);
   4001         }
   4002     }
   4003 #endif
   4004 
   4005     SOC_IF_ERROR_RETURN
   4006         (WRITE_TRUNK_GROUPm(unit, MEM_BLOCK_ALL, tid, &tg_entry));
   4007 
   4008     return BCM_E_NONE;
   4009 }
   4010 
   4011 /*
   4012  * Function:
   4013  *      _bcm_trident_trunk_block_mask
   4014  * Purpose:
   4015  *      Update the trunk block mask table.
   4016  *      Old ports are cleared and new ports are added to each entry.
   4017  *      Each hash index location entry is owned by a specific unit/modid
   4018  *      across all units in a stack. Hash index location entry owned by
   4019  *      local unit/modid is provided by my_modid_bmap. member_count is
   4020  *      the number of NUC forwarding eligible ports in the trunk group.
   4021  *      Each eligible entry also has a rolling port that is not masked
   4022  *      from among the new NUC forwarding eligible ports (nuc_ports).
   4023  *      This is what spreads non-unicast traffic across multiple ports.
   4024  * Parameters:
   4025  *      unit - (IN) SOC unit number. 
   4026  *      nuc_type - (IN) Type of non-unicast: IPMC, L2MC, BCAST, or DLF.
   4027  *      old_ports - (IN) Old local trunk member ports.
   4028  *      new_ports - (IN) New local trunk member ports.
   4029  *      nuc_ports - (IN) New local trunk member ports eligible for non-unicast.
   4030  *      my_modid_bmap - (IN) Bitmap indicating which non-unicast eligible trunk
   4031  *                           member port is local.
   4032  *      member_count  - (IN) Number of new non-unicast eligible trunk member
   4033  *                           ports, including both local and remote members.
   4034  *      flags - (IN) Trunk group flags.
   4035  * Returns:
   4036  *      BCM_E_xxx
   4037  */
   4038 STATIC int
   4039 _bcm_trident_trunk_block_mask(int unit,
   4040         int nuc_type,
   4041         pbmp_t old_ports,
   4042         pbmp_t new_ports,
   4043         int *localport_array,
   4044         int localport_count,
   4045         SHR_BITDCL *my_modid_bmap,
   4046         uint32 member_count,
   4047         uint32 flags)
   4048 {
   4049     int        all_local;
   4050     int        i, imin, imax, rv;
   4051     int        index_count; 
   4052     soc_mem_t  mem;
   4053     bcm_pbmp_t pbmp, old_pbmp;
   4054     nonucast_trunk_block_mask_entry_t *mask_entry;
   4055     nonucast_trunk_block_mask_entry_t *mask_table;
   4056     int        region_size;
   4057 
   4058     rv = BCM_E_NONE;
   4059 
   4060     all_local = FALSE;
   4061     if ((localport_count > 0) && (localport_count == member_count)) {
   4062         all_local = TRUE;
   4063     }
   4064 
   4065     /* The NONUCAST_TRUNK_BLOCK_MASK table is divided into 4 regions:
   4066      * IPMC, L2MC, broadcast, and unknown unicast/multicast.
   4067      */
   4068     mem = NONUCAST_TRUNK_BLOCK_MASKm;
   4069     region_size = soc_mem_index_count(unit, mem) / 4;
   4070     if (nuc_type == TRUNK_BLOCK_MASK_TYPE_IPMC) {
   4071         imin = 0;
   4072     } else if (nuc_type == TRUNK_BLOCK_MASK_TYPE_L2MC) {
   4073         imin = region_size;
   4074     } else if (nuc_type == TRUNK_BLOCK_MASK_TYPE_BCAST) {
   4075         imin = region_size * 2;
   4076     } else if (nuc_type == TRUNK_BLOCK_MASK_TYPE_DLF) {
   4077         imin = region_size * 3;
   4078     } else {
   4079         return BCM_E_PARAM;
   4080     }
   4081     imax = imin + region_size - 1;
   4082 
   4083     mask_table = soc_cm_salloc(unit,
   4084                                sizeof(nonucast_trunk_block_mask_entry_t) * region_size,
   4085                                "nonuc trunk mask tbl dma");
   4086     if (NULL == mask_table) {
   4087         return BCM_E_MEMORY;
   4088     }
   4089 
   4090     soc_mem_lock(unit, mem);
   4091 
   4092     if ((rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY, 
   4093                                  imin, imax, mask_table)) < 0) {
   4094         soc_mem_unlock(unit, mem);
   4095         soc_cm_sfree(unit, mask_table);
   4096         return rv;
   4097     }
   4098 
   4099     index_count = 0;
   4100     for (i = imin; i <= imax; i++) {
   4101         mask_entry = soc_mem_table_idx_to_pointer(unit, mem,
   4102                                                   nonucast_trunk_block_mask_entry_t *,
   4103                                                   mask_table, i - imin);
   4104         soc_mem_pbmp_field_get(unit, mem, mask_entry, BLOCK_MASKf, &pbmp);
   4105         SOC_PBMP_ASSIGN(old_pbmp, pbmp);
   4106         SOC_PBMP_REMOVE(pbmp, old_ports);
   4107         if (nuc_type == TRUNK_BLOCK_MASK_TYPE_IPMC &&
   4108                 (flags & BCM_TRUNK_FLAG_IPMC_CLEAVE)) {
   4109             /* If the flag BCM_TRUNK_FLAG_IPMC_CLEAVE is set,
   4110              * IPMC trunk resolution is disabled, and the bits in
   4111              * pbmp corresponding to new_ports are not set.
   4112              */
   4113         } else {
   4114             SOC_PBMP_OR(pbmp, new_ports);
   4115             if (localport_count > 0) {
   4116                 if (all_local || (member_count > BCM_SWITCH_TRUNK_MAX_PORTCNT)) {
   4117                     if (SHR_BITGET(my_modid_bmap,
   4118                                    ((i % region_size) % member_count))) {
   4119                         SOC_PBMP_PORT_REMOVE(
   4120                             pbmp, localport_array[index_count % localport_count]);
   4121                         index_count++;
   4122                     }
   4123                 } else {
   4124                     /* Not all trunk members are local, and number of
   4125                      * members is BCM_SWITCH_TRUNK_MAX_PORTCNT or less.
   4126                      * We need to conservatively configure
   4127                      * NONUCAST_TRUNK_BLOCK_MASK table to interoperate
   4128                      * with pre-Trident XGS3 devices.
   4129                      */
   4130                     if ((i % 16) == 0) {
   4131                         index_count = 0;
   4132                     }
   4133                     if (SHR_BITGET(my_modid_bmap, ((i % 16) % member_count))) {
   4134                         SOC_PBMP_PORT_REMOVE(
   4135                             pbmp, localport_array[index_count % localport_count]);
   4136                         index_count++;
   4137                     }
   4138                 }
   4139             }
   4140         }
   4141         if (SOC_PBMP_EQ(pbmp, old_pbmp)) {
   4142             continue;
   4143         }
   4144 
   4145         soc_mem_pbmp_field_set(unit, mem, mask_entry, BLOCK_MASKf, &pbmp);
   4146     }
   4147 
   4148     rv = soc_mem_write_range(unit, mem, MEM_BLOCK_ANY, imin, imax, mask_table);
   4149 
   4150     soc_mem_unlock(unit, mem);
   4151     soc_cm_sfree(unit, mask_table);
   4152 
   4153     return rv;
   4154 }
   4155 
   4156 /*
   4157  * Function:
   4158  *      _bcm_trident_trunk_mod_port_map_set
   4159  * Purpose:
   4160  *      Set  (mod, port) to  trunk id map.
   4161  *      Map implements a software cache for the SOURCE_TRUNK_MAP_TABLE.
   4162  * Parameters:
   4163  *      unit     -  (IN) BCM device number. 
   4164  *      modid    -  (IN) Member port module id.  
   4165  *      port     -  (IN) Member port number.  
   4166  *      trunk_id -  (IN) Trunk number or negative value for reset.  
   4167  * Returns:
   4168  *      BCM_X_XXX
   4169  */
   4170 STATIC int 
   4171 _bcm_trident_trunk_mod_port_map_set(int unit,
   4172         bcm_module_t modid, 
   4173         bcm_port_t port,
   4174         bcm_trunk_t trunk_id)  
   4175 {
   4176     int   idx;               /* Map array index. */
   4177 
   4178     if (NULL == _trident_mod_port_to_tid_map[unit]) {
   4179         return (BCM_E_INIT);
   4180     }
   4181 
   4182     /* Trunk id range check, only 16 bits are allocated per trunk ID in
   4183      * _trident_mod_port_to_tid_map
   4184      */
   4185     if (trunk_id >= 0xffff) {
   4186         return (BCM_E_INTERNAL);
   4187     }
   4188 
   4189     idx = modid * SOC_MAX_NUM_PORTS + port;
   4190     if (idx >= _BCM_XGS3_TRUNK_MOD_PORT_MAP_IDX_COUNT(unit)) { 
   4191         return (BCM_E_PARAM);
   4192     }
   4193 
   4194     _trident_mod_port_to_tid_map[unit][idx] = (trunk_id < 0) ? 0 : (++trunk_id);
   4195 
   4196     return (BCM_E_NONE);
   4197 }
   4198 
   4199 /*
   4200  * Function:
   4201  *      _bcm_trident_trunk_mod_port_map_get
   4202  * Purpose:
   4203  *      Read mapping (mod, port) to trunk id from software cache 
   4204  *      for the SOURCE_TRUNK_MAP_TABLE.
   4205  * Parameters:
   4206  *      unit     -  (IN) BCM device number. 
   4207  *      modid    -  (IN) Member port module id.  
   4208  *      port     -  (IN) Member port number.  
   4209  *      trunk_id -  (OUT) Trunk number or negative value for reset.  
   4210  * Returns:
   4211  *      BCM_X_XXX
   4212  */
   4213 STATIC int 
   4214 _bcm_trident_trunk_mod_port_map_get(int unit,
   4215         bcm_module_t modid, 
   4216         bcm_port_t port,
   4217         bcm_trunk_t *trunk_id)  
   4218 {
   4219     int              idx;      /* Map array index.         */
   4220     bcm_module_t     mymodid;  /* Local module id.         */
   4221     int              isLocal;  /* Local module id flag.    */
   4222     int              rv;       /* Operation return status. */
   4223     int              is_local_subport = FALSE;
   4224 
   4225     if (NULL == _trident_mod_port_to_tid_map[unit]) {
   4226         return (BCM_E_INIT);
   4227     }
   4228 
   4229     rv = _bcm_esw_modid_is_local(unit, modid, &isLocal);
   4230     BCM_IF_ERROR_RETURN(rv);
   4231 
   4232 #if defined(BCM_HGPROXY_COE_SUPPORT)
   4233     if (soc_feature(unit, soc_feature_hgproxy_subtag_coe)) {
   4234         if(_bcm_xgs5_subport_coe_mod_port_local(unit, modid, port)) {        
   4235             is_local_subport = TRUE;
   4236         }
   4237     }
   4238 #endif
   4239     if (isLocal && !is_local_subport) {
   4240         rv = bcm_esw_stk_my_modid_get(unit, &mymodid);
   4241         BCM_IF_ERROR_RETURN(rv);
   4242         if (mymodid != modid) {
   4243             modid = mymodid;
   4244             port += 32;
   4245         }
   4246     }
   4247 
   4248     idx = modid * SOC_MAX_NUM_PORTS + port;
   4249     if (idx >= _BCM_XGS3_TRUNK_MOD_PORT_MAP_IDX_COUNT(unit)) { 
   4250         return (BCM_E_PARAM);
   4251     }
   4252 
   4253     *trunk_id = _trident_mod_port_to_tid_map[unit][idx] - 1;
   4254 
   4255     return (_trident_mod_port_to_tid_map[unit][idx]) ? BCM_E_NONE : BCM_E_NOT_FOUND;
   4256 }
   4257 
   4258 /*
   4259  * Function:
   4260  *      _bcm_trident_trunk_set_port_property
   4261  * Purpose:
   4262  *      Mark a mod/port pair as being in a particular trunk (or not)
   4263  *      A negative tid sets the mod/port back to non-trunk status.
   4264  * Parameters:
   4265  *      unit - (IN) SOC unit number. 
   4266  *      mod  - (IN) Module ID.
   4267  *      port - (IN) Port number.
   4268  *      tid  - (IN) Trunk group ID.
   4269  * Returns:
   4270  *      BCM_E_xxx
   4271  */
   4272 STATIC int
   4273 _bcm_trident_trunk_set_port_property(int unit,
   4274         bcm_module_t mod,
   4275         bcm_port_t port,
   4276         int tid)
   4277 {
   4278     int       ptype_get, ptype_set, tid_get, tid_set;
   4279     int       idx;
   4280     soc_mem_t mem;
   4281     source_trunk_map_table_entry_t stm;
   4282     egr_gpp_attributes_entry_t ega;
   4283     int       rv;
   4284     soc_field_t tgid_f = TGIDf;
   4285 
   4286     if (tid < 0) {
   4287         ptype_set = 0;                /* normal port */
   4288         tid_set = 0;
   4289     } else {
   4290         ptype_set = 1;                /* trunk port */
   4291         tid_set = tid;
   4292     }
   4293 
   4294     BCM_IF_ERROR_RETURN
   4295         (_bcm_esw_src_mod_port_table_index_get(unit, mod, port, &idx));
   4296 
   4297     mem = SOURCE_TRUNK_MAP_TABLEm;
   4298     if (soc_mem_field_valid(unit, mem, SRC_TGIDf)) {
   4299         tgid_f = SRC_TGIDf;
   4300     }
   4301     soc_mem_lock(unit, mem);
   4302     rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, idx, &stm);
   4303     if (BCM_SUCCESS(rv)) {
   4304         ptype_get = soc_mem_field32_get(unit, mem, &stm, PORT_TYPEf);
   4305         tid_get = soc_mem_field32_get(unit, mem, &stm, tgid_f);
   4306         if ((ptype_get != ptype_set) || (tid_get != tid_set)) {
   4307             soc_mem_field32_set(unit, mem, &stm, PORT_TYPEf, ptype_set);
   4308             soc_mem_field32_set(unit, mem, &stm, tgid_f, tid_set);
   4309             rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, idx, &stm);
   4310         }
   4311     }
   4312     soc_mem_unlock(unit, mem);
   4313 
   4314     if(!SOC_IS_KATANA(unit)) {
   4315         mem = EGR_GPP_ATTRIBUTESm;
   4316         soc_mem_lock(unit, mem);
   4317         rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, idx, &ega);
   4318         if (BCM_SUCCESS(rv)) {
   4319             ptype_get = soc_mem_field32_get(unit, mem, &ega, ISTRUNKf);
   4320             tid_get = soc_mem_field32_get(unit, mem, &ega, TGIDf);
   4321             if ((ptype_get != ptype_set) || (tid_get != tid_set)) {
   4322                 soc_mem_field32_set(unit, mem, &ega, ISTRUNKf, ptype_set);
   4323                 soc_mem_field32_set(unit, mem, &ega, TGIDf, tid_set);
   4324                 rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, idx, &ega);
   4325             }
   4326         }
   4327         soc_mem_unlock(unit, mem);
   4328     }
   4329     /* Update SW module, port to tid mapping. */
   4330     if (BCM_SUCCESS(rv)) {
   4331         rv = _bcm_trident_trunk_mod_port_map_set(unit, mod, port, tid);  
   4332     }
   4333 
   4334     return rv;
   4335 }
   4336 
   4337 /*
   4338  * Function:
   4339  *      _bcm_trident_trunk_get_port_property
   4340  * Purpose:
   4341  *      Get trunk group ID for a mod/port pair.
   4342  * Parameters:
   4343  *      unit - (IN) SOC unit number. 
   4344  *      mod  - (IN) Module ID.
   4345  *      port - (IN) Port number.
   4346  *      tid  - (OUT) Trunk group ID.
   4347  * Returns:
   4348  *      BCM_E_xxx
   4349  */
   4350 int
   4351 _bcm_trident_trunk_get_port_property(int unit,
   4352         bcm_module_t mod,
   4353         bcm_port_t port,
   4354         int *tid)
   4355 {
   4356     return  _bcm_trident_trunk_mod_port_map_get(unit, mod, port, tid);  
   4357 }
   4358 
   4359 /*
   4360  * Function:
   4361  *      _bcm_trident_nuc_tpbm_get
   4362  * Purpose:
   4363  *      Get non-unicast panel trunk members.
   4364  * Parameters:
   4365  *      unit      - (IN) SOC unit number. 
   4366  *      num_ports - (IN) Number of ports in trunk group.
   4367  *      tm        - (IN) Pointer to array of module IDs.
   4368  *      nuc_tpbm  - (OUT) Bitmap of ports eligible for non-unicast.
   4369  * Returns:
   4370  *      BCM_E_xxx
   4371  */
   4372 STATIC
   4373 int _bcm_trident_nuc_tpbm_get(int unit,
   4374                       int num_ports,
   4375                       bcm_module_t *tm,
   4376                       SHR_BITDCL *nuc_tpbm)
   4377 {
   4378     int    rv = BCM_E_NONE;
   4379     int    i, mod = -1;
   4380     uint32 mod_type;
   4381     int    all_equal = 1;
   4382 
   4383     SHR_BITDCL *xgs12_tpbm = NULL;
   4384     SHR_BITDCL *xgs3_tpbm = NULL;
   4385     SHR_BITDCL *unknown_tpbm = NULL;
   4386 
   4387     SHR_BITDCL xgs12_tpbm_result;
   4388     SHR_BITDCL xgs3_tpbm_result;
   4389     SHR_BITDCL unknown_tpbm_result;
   4390 
   4391     xgs12_tpbm = sal_alloc(SHR_BITALLOCSIZE(num_ports), "xgs12_tpbm");
   4392     if (xgs12_tpbm == NULL) {
   4393         return BCM_E_MEMORY;
   4394     }
   4395     sal_memset(xgs12_tpbm, 0, SHR_BITALLOCSIZE(num_ports));
   4396 
   4397     xgs3_tpbm = sal_alloc(SHR_BITALLOCSIZE(num_ports), "xgs3_tpbm");
   4398     if (xgs3_tpbm == NULL) {
   4399         sal_free(xgs12_tpbm);
   4400         return BCM_E_MEMORY;
   4401     }
   4402     sal_memset(xgs3_tpbm, 0, SHR_BITALLOCSIZE(num_ports));
   4403 
   4404     unknown_tpbm = sal_alloc(SHR_BITALLOCSIZE(num_ports), "unknown_tpbm");
   4405     if (unknown_tpbm == NULL) {
   4406         sal_free(xgs12_tpbm);
   4407         sal_free(xgs3_tpbm);
   4408         return BCM_E_MEMORY;
   4409     }
   4410     sal_memset(unknown_tpbm, 0, SHR_BITALLOCSIZE(num_ports));
   4411 
   4412     SHR_BITSET(nuc_tpbm, 0);
   4413     for (i = 0; i < num_ports; i++) {
   4414         if (i == 0) {
   4415             mod = tm[i];
   4416         } else if (mod != tm[i]) {
   4417             all_equal = 0;
   4418         }
   4419         rv = _bcm_switch_module_type_get(unit, tm[i], &mod_type);
   4420         if (BCM_FAILURE(rv)) {
   4421             sal_free(xgs12_tpbm);
   4422             sal_free(xgs3_tpbm);
   4423             sal_free(unknown_tpbm);
   4424             return rv;
   4425         }
   4426         switch(mod_type) {
   4427             case BCM_SWITCH_MODULE_XGS1:
   4428                 /* passthru */
   4429             case BCM_SWITCH_MODULE_XGS2:
   4430                 SHR_BITSET(xgs12_tpbm, i);
   4431                 break;
   4432             case BCM_SWITCH_MODULE_XGS3:
   4433                 SHR_BITSET(xgs3_tpbm, i);
   4434                 break;
   4435             case BCM_SWITCH_MODULE_UNKNOWN:
   4436                 /* passthru */
   4437             default:
   4438                 SHR_BITSET(unknown_tpbm, i);
   4439                 break;
   4440         }
   4441     }
   4442 
   4443     /* tpbm_result will be 0 if all bits in the range are 0 */
   4444     SHR_BITTEST_RANGE(xgs12_tpbm, 0, num_ports, xgs12_tpbm_result);
   4445     SHR_BITTEST_RANGE(xgs3_tpbm, 0, num_ports, xgs3_tpbm_result);
   4446     SHR_BITTEST_RANGE(unknown_tpbm, 0, num_ports, unknown_tpbm_result);
   4447 
   4448     if (all_equal) {
   4449         SHR_BITSET_RANGE(nuc_tpbm, 0, num_ports);
   4450     } else if (xgs12_tpbm_result || unknown_tpbm_result) {
   4451         SHR_BITSET(nuc_tpbm, 0);
   4452     } else if (xgs3_tpbm_result) {
   4453         SHR_BITCOPY_RANGE(nuc_tpbm, 0, xgs3_tpbm, 0, num_ports);
   4454     }
   4455 
   4456     sal_free(xgs12_tpbm);
   4457     sal_free(xgs3_tpbm);
   4458     sal_free(unknown_tpbm);
   4459 
   4460     return rv;
   4461 }
   4462 
   4463 /* Macro to free memory and return code */
   4464 
   4465 #define _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(_r_) \
   4466     if (nuc_tpbm) {                                    \
   4467         sal_free(nuc_tpbm);                            \
   4468     }                                                  \
   4469     if (ipmc_tpbm) {                                   \
   4470         sal_free(ipmc_tpbm);                           \
   4471     }                                                  \
   4472     if (l2mc_tpbm) {                                   \
   4473         sal_free(l2mc_tpbm);                           \
   4474     }                                                  \
   4475     if (bcast_tpbm) {                                  \
   4476         sal_free(bcast_tpbm);                          \
   4477     }                                                  \
   4478     if (dlf_tpbm) {                                    \
   4479         sal_free(dlf_tpbm);                            \
   4480     }                                                  \
   4481     if (ipmc_my_modid_bmap) {                          \
   4482         sal_free(ipmc_my_modid_bmap);                  \
   4483     }                                                  \
   4484     if (l2mc_my_modid_bmap) {                          \
   4485         sal_free(l2mc_my_modid_bmap);                  \
   4486     }                                                  \
   4487     if (bcast_my_modid_bmap) {                         \
   4488         sal_free(bcast_my_modid_bmap);                 \
   4489     }                                                  \
   4490     if (dlf_my_modid_bmap) {                           \
   4491         sal_free(dlf_my_modid_bmap);                   \
   4492     }                                                  \
   4493     if (hwmod) {                                       \
   4494         sal_free(hwmod);                               \
   4495     }                                                  \
   4496     if (hwport) {                                      \
   4497         sal_free(hwport);                              \
   4498     }                                                  \
   4499     if (egr_hwmod) {                                   \
   4500         sal_free(egr_hwmod);                           \
   4501     }                                                  \
   4502     if (egr_hwport) {                                  \
   4503         sal_free(egr_hwport);                          \
   4504     }                                                  \
   4505     if (egr_member_flags) {                            \
   4506         sal_free(egr_member_flags);                    \
   4507     }                                                  \
   4508     if (egr_scaling_factor) {                          \
   4509         sal_free(egr_scaling_factor);                  \
   4510     }                                                  \
   4511     if (egr_load_weight) {                             \
   4512         sal_free(egr_load_weight);                     \
   4513     }                                                  \
   4514     if (egr_qsize_weight) {                            \
   4515         sal_free(egr_qsize_weight);                    \
   4516     }                                                  \
   4517     if (uc_egr_hwmod) {                                \
   4518         sal_free(uc_egr_hwmod);                        \
   4519     }                                                  \
   4520     if (uc_egr_hwport) {                               \
   4521         sal_free(uc_egr_hwport);                       \
   4522     }                                                  \
   4523     if (uc_egr_scaling_factor) {                       \
   4524         sal_free(uc_egr_scaling_factor);               \
   4525     }                                                  \
   4526     if (uc_egr_load_weight) {                          \
   4527         sal_free(uc_egr_load_weight);                  \
   4528     }                                                  \
   4529     if (uc_egr_qsize_weight) {                         \
   4530         sal_free(uc_egr_qsize_weight);                 \
   4531     }                                                  \
   4532     if (leaving_members) {                             \
   4533         sal_free(leaving_members);                     \
   4534     }                                                  \
   4535     if (staying_members) {                             \
   4536         sal_free(staying_members);                     \
   4537     }                                                  \
   4538     if (joining_members) {                             \
   4539         sal_free(joining_members);                     \
   4540     }                                                  \
   4541     if (ipmc_localport_array) {                        \
   4542         sal_free(ipmc_localport_array);                \
   4543     }                                                  \
   4544     if (l2mc_localport_array) {                        \
   4545         sal_free(l2mc_localport_array);                \
   4546     }                                                  \
   4547     if (bcast_localport_array) {                       \
   4548         sal_free(bcast_localport_array);               \
   4549     }                                                  \
   4550     if (dlf_localport_array) {                         \
   4551         sal_free(dlf_localport_array);                 \
   4552     }                                                  \
   4553     return _r_;                             
   4554 
   4555 /*
   4556  * Function:
   4557  *      _bcm_trident_trunk_fp_set
   4558  * Purpose:
   4559  *      Set front panel trunk members.
   4560  * Parameters:
   4561  *      unit     - (IN) SOC unit number. 
   4562  *      tid      - (IN) Trunk group ID.
   4563  *      add_info - (IN) Pointer to trunk add info structure.
   4564  *      t_info   - (IN) Pointer to trunk info.
   4565  *      op       - (IN) Type of operation: TRUNK_MEMBER_OP_SET, ADD or DELETE.
   4566  *      member   - (IN) Member to add or delete.
   4567  * Returns:
   4568  *      BCM_E_xxx
   4569  */
   4570 STATIC int
   4571 _bcm_trident_trunk_fp_modify(int unit,
   4572         bcm_trunk_t tid,
   4573         _esw_trunk_add_info_t *add_info,
   4574         trunk_private_t *t_info,
   4575         trunk_private_t *stored_info,
   4576         int op,
   4577         bcm_trunk_member_t *member)
   4578 {
   4579     int                  rv = BCM_E_NONE;
   4580     SHR_BITDCL           *nuc_tpbm = NULL;
   4581     SHR_BITDCL           *ipmc_tpbm = NULL;
   4582     SHR_BITDCL           *l2mc_tpbm = NULL;
   4583     SHR_BITDCL           *bcast_tpbm = NULL;
   4584     SHR_BITDCL           *dlf_tpbm = NULL;
   4585     SHR_BITDCL           *ipmc_my_modid_bmap = NULL;
   4586     SHR_BITDCL           *l2mc_my_modid_bmap = NULL;
   4587     SHR_BITDCL           *bcast_my_modid_bmap = NULL;
   4588     SHR_BITDCL           *dlf_my_modid_bmap = NULL;
   4589     int                  *hwmod = NULL;
   4590     int                  *hwport = NULL;
   4591     int                  num_egr_ports = 0;
   4592     int                  *egr_hwmod = NULL;
   4593     int                  *egr_hwport = NULL;
   4594     uint32               *egr_member_flags = NULL;
   4595     int                  *egr_scaling_factor = NULL;
   4596     int                  *egr_load_weight = NULL;
   4597     int                  *egr_qsize_weight = NULL;
   4598     int                  num_uc_egr_ports = 0;
   4599     int                  *uc_egr_hwmod = NULL;
   4600     int                  *uc_egr_hwport = NULL;
   4601     int                  *uc_egr_scaling_factor = NULL;
   4602     int                  *uc_egr_load_weight = NULL;
   4603     int                  *uc_egr_qsize_weight = NULL;
   4604     int                  negr_disable_port = 0;
   4605     int                  num_uc_egr_disable_port = 0;
   4606     pbmp_t               new_trunk_pbmp;
   4607     uint32               ipmc_member_count;
   4608     uint32               l2mc_member_count;
   4609     uint32               bcast_member_count;
   4610     uint32               dlf_member_count;
   4611     int                  mod, port, mod_out, port_out;
   4612     bcm_gport_t          gport;
   4613     bcm_port_t           loc_port = BCM_GPORT_INVALID;
   4614     int                  i;
   4615     trunk_bitmap_entry_t trunk_bitmap_entry;
   4616     pbmp_t               old_trunk_pbmp;
   4617     int                  j, k, remove_trunk_port;
   4618     int                  num_leaving_members = 0;
   4619     bcm_gport_t          *leaving_members = NULL;
   4620     int                  match_leaving_members;
   4621     int                  num_staying_members = 0;
   4622     bcm_gport_t          *staying_members = NULL;
   4623     int                  match_staying_members;
   4624     int                  num_joining_members = 0;
   4625     bcm_gport_t          *joining_members = NULL;
   4626     int                  match_joining_members;
   4627     bcm_trunk_chip_info_t chip_info;
   4628     int                  is_local;
   4629     int                  is_local_subport = 0;
   4630     int                  *ipmc_localport_array = NULL;
   4631     int                  *l2mc_localport_array = NULL;
   4632     int                  *bcast_localport_array = NULL;
   4633     int                  *dlf_localport_array = NULL;
   4634     int                  ipmc_localport_count;
   4635     int                  l2mc_localport_count;
   4636     int                  bcast_localport_count;
   4637     int                  dlf_localport_count;
   4638 
   4639     BCM_IF_ERROR_RETURN(bcm_esw_trunk_chip_info_get(unit, &chip_info));
   4640     if (add_info->num_ports > chip_info.trunk_ports_max ||
   4641             add_info->num_ports < 1) {
   4642         return BCM_E_PARAM;
   4643     }
   4644  
   4645     /* On Trident A0, the max number of trunk members for RTAG 1-6 is smaller
   4646      * than for RTAG 7.
   4647      */
   4648     if (soc_feature(unit, soc_feature_rtag1_6_max_portcnt_less_than_rtag7)) { 
   4649         if (t_info->rtag >= 1 && t_info->rtag <= 6) {
   4650             if (add_info->num_ports > _BCM_TD_FP_TRUNK_RTAG1_6_MAX_PORTCNT) {
   4651                 return BCM_E_PARAM;
   4652             }
   4653         }
   4654     }
   4655 
   4656     /* Audit unsupported flag combination */
   4657     for (i = 0; i < add_info->num_ports; i++) {
   4658         if (add_info->member_flags[i] & BCM_TRUNK_MEMBER_EGRESS_DISABLE) {
   4659             if (add_info->member_flags[i] & BCM_TRUNK_MEMBER_INGRESS_DISABLE) {
   4660                 return BCM_E_PARAM;
   4661             }
   4662             if (add_info->member_flags[i] &
   4663                     BCM_TRUNK_MEMBER_UNICAST_EGRESS_DISABLE) {
   4664                 return BCM_E_PARAM;
   4665             }
   4666             if (add_info->member_flags[i] &
   4667                     BCM_TRUNK_MEMBER_IPMC_EGRESS_DISABLE) {
   4668                 return BCM_E_PARAM;
   4669             }
   4670             if (add_info->member_flags[i] &
   4671                     BCM_TRUNK_MEMBER_L2MC_EGRESS_DISABLE) {
   4672                 return BCM_E_PARAM;
   4673             }
   4674             if (add_info->member_flags[i] &
   4675                     BCM_TRUNK_MEMBER_BCAST_EGRESS_DISABLE) {
   4676                 return BCM_E_PARAM;
   4677             }
   4678             if (add_info->member_flags[i] &
   4679                     BCM_TRUNK_MEMBER_DLF_EGRESS_DISABLE) {
   4680                 return BCM_E_PARAM;
   4681             }
   4682         }
   4683         if (add_info->member_flags[i] & BCM_TRUNK_MEMBER_IPMC_EGRESS_DISABLE) {
   4684             if (add_info->ipmc_index != BCM_TRUNK_UNSPEC_INDEX) {
   4685                 return BCM_E_PARAM;
   4686             }
   4687         }
   4688         if (add_info->member_flags[i] & BCM_TRUNK_MEMBER_L2MC_EGRESS_DISABLE) {
   4689             if (add_info->mc_index != BCM_TRUNK_UNSPEC_INDEX) {
   4690                 return BCM_E_PARAM;
   4691             }
   4692         }
   4693         if (add_info->member_flags[i] & BCM_TRUNK_MEMBER_BCAST_EGRESS_DISABLE) {
   4694             if (add_info->dlf_index != BCM_TRUNK_UNSPEC_INDEX) {
   4695                 return BCM_E_PARAM;
   4696             }
   4697         }
   4698         if (add_info->member_flags[i] & BCM_TRUNK_MEMBER_DLF_EGRESS_DISABLE) {
   4699             if (add_info->dlf_index != BCM_TRUNK_UNSPEC_INDEX) {
   4700                 return BCM_E_PARAM;
   4701             }
   4702         }
   4703     }
   4704 
   4705     if (add_info->dlf_index >= add_info->num_ports) {
   4706         return BCM_E_PARAM;
   4707     }
   4708 
   4709     /* Derive a member bitmap of non-unicast eligible members */
   4710     nuc_tpbm = sal_alloc(SHR_BITALLOCSIZE(add_info->num_ports), "nuc_tpbm");
   4711     if (nuc_tpbm == NULL) {
   4712         _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(BCM_E_MEMORY);
   4713     }
   4714     sal_memset(nuc_tpbm, 0, SHR_BITALLOCSIZE(add_info->num_ports));
   4715     if (add_info->dlf_index == -1) {
   4716         rv = _bcm_trident_nuc_tpbm_get(unit, add_info->num_ports, 
   4717                 add_info->tm, nuc_tpbm);
   4718         if (BCM_FAILURE(rv)) {
   4719             _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(rv);
   4720         }
   4721     } else {
   4722         SHR_BITSET(nuc_tpbm, add_info->dlf_index);
   4723     }
   4724 
   4725     /* Copy the non-unicast eligible member bitmap to IPMC, L2MC, broadcast,
   4726      * and DLF eligible member bitmaps.
   4727      */
   4728     ipmc_tpbm = sal_alloc(SHR_BITALLOCSIZE(add_info->num_ports), "ipmc_tpbm");
   4729     if (ipmc_tpbm == NULL) {
   4730         _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(BCM_E_MEMORY);
   4731     }
   4732     sal_memcpy(ipmc_tpbm, nuc_tpbm, SHR_BITALLOCSIZE(add_info->num_ports));
   4733 
   4734     l2mc_tpbm = sal_alloc(SHR_BITALLOCSIZE(add_info->num_ports), "l2mc_tpbm");
   4735     if (l2mc_tpbm == NULL) {
   4736         _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(BCM_E_MEMORY);
   4737     }
   4738     sal_memcpy(l2mc_tpbm, nuc_tpbm, SHR_BITALLOCSIZE(add_info->num_ports));
   4739 
   4740     bcast_tpbm = sal_alloc(SHR_BITALLOCSIZE(add_info->num_ports), "bcast_tpbm");
   4741     if (bcast_tpbm == NULL) {
   4742         _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(BCM_E_MEMORY);
   4743     }
   4744     sal_memcpy(bcast_tpbm, nuc_tpbm, SHR_BITALLOCSIZE(add_info->num_ports));
   4745 
   4746     dlf_tpbm = sal_alloc(SHR_BITALLOCSIZE(add_info->num_ports), "dlf_tpbm");
   4747     if (dlf_tpbm == NULL) {
   4748         _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(BCM_E_MEMORY);
   4749     }
   4750     sal_memcpy(dlf_tpbm, nuc_tpbm, SHR_BITALLOCSIZE(add_info->num_ports));
   4751 
   4752     /* Iterate through the trunk member list to get module ID and port
   4753      * number of each member, a port bitmap of local members, and
   4754      * port bitmaps of IPMC/L2MC/BCAST/DLF eligible local members.
   4755      */
   4756     hwmod = sal_alloc(sizeof(int) * (add_info->num_ports), "hwmod");
   4757     if (hwmod == NULL) {
   4758         _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(BCM_E_MEMORY);
   4759     }
   4760     sal_memset(hwmod, 0, sizeof(int) * (add_info->num_ports));
   4761 
   4762     hwport = sal_alloc(sizeof(int) * (add_info->num_ports), "hwport");
   4763     if (hwport == NULL) {
   4764         _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(BCM_E_MEMORY);
   4765     }
   4766     sal_memset(hwport, 0, sizeof(int) * (add_info->num_ports));
   4767 
   4768     ipmc_my_modid_bmap = sal_alloc(SHR_BITALLOCSIZE(add_info->num_ports),
   4769             "ipmc_my_modid_bmap");
   4770     if (ipmc_my_modid_bmap == NULL) {
   4771         _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(BCM_E_MEMORY);
   4772     }
   4773     sal_memset(ipmc_my_modid_bmap, 0, SHR_BITALLOCSIZE(add_info->num_ports));
   4774 
   4775     l2mc_my_modid_bmap = sal_alloc(SHR_BITALLOCSIZE(add_info->num_ports),
   4776             "l2mc_my_modid_bmap");
   4777     if (l2mc_my_modid_bmap == NULL) {
   4778         _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(BCM_E_MEMORY);
   4779     }
   4780     sal_memset(l2mc_my_modid_bmap, 0, SHR_BITALLOCSIZE(add_info->num_ports));
   4781 
   4782     bcast_my_modid_bmap = sal_alloc(SHR_BITALLOCSIZE(add_info->num_ports),
   4783             "bcast_my_modid_bmap");
   4784     if (bcast_my_modid_bmap == NULL) {
   4785         _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(BCM_E_MEMORY);
   4786     }
   4787     sal_memset(bcast_my_modid_bmap, 0, SHR_BITALLOCSIZE(add_info->num_ports));
   4788 
   4789     dlf_my_modid_bmap = sal_alloc(SHR_BITALLOCSIZE(add_info->num_ports),
   4790             "dlf_my_modid_bmap");
   4791     if (dlf_my_modid_bmap == NULL) {
   4792         _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(BCM_E_MEMORY);
   4793     }
   4794     sal_memset(dlf_my_modid_bmap, 0, SHR_BITALLOCSIZE(add_info->num_ports));
   4795     ipmc_localport_array = sal_alloc(add_info->num_ports * sizeof(int),
   4796                                      "ipmc_localport_array");
   4797     if (ipmc_localport_array == NULL) {
   4798         _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(BCM_E_MEMORY);
   4799     }
   4800     sal_memset(ipmc_localport_array, 0, add_info->num_ports * sizeof(int));
   4801     l2mc_localport_array = sal_alloc(add_info->num_ports * sizeof(int),
   4802                                      "l2mc_localport_array");
   4803     if (l2mc_localport_array == NULL) {
   4804         _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(BCM_E_MEMORY);
   4805     }
   4806     sal_memset(l2mc_localport_array, 0, add_info->num_ports * sizeof(int));
   4807     bcast_localport_array = sal_alloc(add_info->num_ports * sizeof(int),
   4808                                       "bcast_localport_array");
   4809     if (bcast_localport_array == NULL) {
   4810         _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(BCM_E_MEMORY);
   4811     }
   4812     sal_memset(bcast_localport_array, 0, add_info->num_ports * sizeof(int));
   4813     dlf_localport_array = sal_alloc(add_info->num_ports * sizeof(int),
   4814                                     "dlf_localport_array");
   4815     if (dlf_localport_array == NULL) {
   4816         _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(BCM_E_MEMORY);
   4817     }
   4818     sal_memset(dlf_localport_array, 0, add_info->num_ports * sizeof(int));
   4819 
   4820     SOC_PBMP_CLEAR(new_trunk_pbmp);
   4821     ipmc_member_count = 0;
   4822     l2mc_member_count = 0;
   4823     bcast_member_count = 0;
   4824     dlf_member_count = 0;
   4825     negr_disable_port = 0;
   4826     num_uc_egr_disable_port = 0;
   4827     ipmc_localport_count = 0;
   4828     l2mc_localport_count = 0;
   4829     bcast_localport_count = 0;
   4830     dlf_localport_count = 0;
   4831 
   4832     for (i = 0; i < add_info->num_ports; i++) {
   4833         mod = add_info->tm[i];
   4834         port = add_info->tp[i];
   4835         /*In case of feature not supported on chip return E_PARAM*/
   4836         if (!soc_feature(unit, soc_feature_shared_trunk_member_table)) {
   4837              _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(BCM_E_PARAM);
   4838         }
   4839         rv = _bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_SET,
   4840                                     mod, port,
   4841                                     &mod_out, &port_out);
   4842         if (BCM_FAILURE(rv)) {
   4843             _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(rv);
   4844         }
   4845         if (!SOC_MODID_ADDRESSABLE(unit, mod_out)) {
   4846             _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(BCM_E_BADID);
   4847         }
   4848         if (!SOC_PORT_ADDRESSABLE(unit, port_out)) {
   4849             _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(BCM_E_PORT);
   4850         }
   4851         hwmod[i] = mod_out;
   4852         hwport[i] = port_out;
   4853 
   4854         if (add_info->member_flags[i] & BCM_TRUNK_MEMBER_EGRESS_DISABLE) {
   4855             SHR_BITCLR(ipmc_tpbm, i);
   4856             SHR_BITCLR(l2mc_tpbm, i);
   4857             SHR_BITCLR(bcast_tpbm, i);
   4858             SHR_BITCLR(dlf_tpbm, i);
   4859             negr_disable_port++;
   4860         } else {
   4861             if (add_info->member_flags[i] &
   4862                     BCM_TRUNK_MEMBER_UNICAST_EGRESS_DISABLE) {
   4863                 num_uc_egr_disable_port++;
   4864             }
   4865             if (add_info->member_flags[i] &
   4866                     BCM_TRUNK_MEMBER_IPMC_EGRESS_DISABLE) {
   4867                 SHR_BITCLR(ipmc_tpbm, i);
   4868             }
   4869             if (add_info->member_flags[i] &
   4870                     BCM_TRUNK_MEMBER_L2MC_EGRESS_DISABLE) {
   4871                 SHR_BITCLR(l2mc_tpbm, i);
   4872             }
   4873             if (add_info->member_flags[i] &
   4874                     BCM_TRUNK_MEMBER_BCAST_EGRESS_DISABLE) {
   4875                 SHR_BITCLR(bcast_tpbm, i);
   4876             }
   4877             if (add_info->member_flags[i] &
   4878                     BCM_TRUNK_MEMBER_DLF_EGRESS_DISABLE) {
   4879                 SHR_BITCLR(dlf_tpbm, i);
   4880             }
   4881         }
   4882 
   4883         BCM_GPORT_MODPORT_SET(gport, mod_out, port_out);
   4884         loc_port = BCM_GPORT_INVALID;
   4885         if (BCM_SUCCESS(bcm_esw_port_local_get(unit, gport, &loc_port))) {
   4886 
   4887             if (soc_feature(unit, soc_feature_hgproxy_subtag_coe)) {
   4888 #if defined(BCM_HGPROXY_COE_SUPPORT)
   4889                 if(_bcm_xgs5_subport_coe_mod_port_local(unit, mod_out,
   4890                                                         port_out)) {
   4891 
   4892                     is_local_subport = 1;
   4893                 }
   4894 #endif
   4895             } else
   4896 
   4897             if (soc_feature(unit, soc_feature_linkphy_coe) ||
   4898                 soc_feature(unit, soc_feature_subtag_coe)) {
   4899 #if defined(BCM_KATANA2_SUPPORT)
   4900                 BCM_IF_ERROR_RETURN(_bcm_kt2_modport_is_local_coe_subport(unit,
   4901                     mod_out, port_out, &is_local_subport));
   4902 #endif
   4903             }
   4904             if (!is_local_subport) {
   4905                 if (!(IS_E_PORT(unit, loc_port) || IS_HG_PORT(unit, loc_port)) ||
   4906                     /* Cascaded physical ports are not considered as front-panel port */
   4907                     (soc_feature(unit, soc_feature_linkphy_coe) &&
   4908                         IS_LP_PORT(unit, loc_port)) ||
   4909                     (soc_feature(unit, soc_feature_subtag_coe) &&
   4910                         IS_SUBTAG_PORT(unit, loc_port)) || 
   4911                     (soc_feature(unit, soc_feature_hgproxy_subtag_coe) &&
   4912                      IS_SUBTAG_PORT (unit, loc_port))) {
   4913                     _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(BCM_E_PARAM);
   4914                 }
   4915             }
   4916             SOC_PBMP_PORT_ADD(new_trunk_pbmp, loc_port);
   4917             if (SHR_BITGET(ipmc_tpbm, i)) {
   4918                 ipmc_localport_array[ipmc_localport_count++] = loc_port;
   4919                 SHR_BITSET(ipmc_my_modid_bmap, ipmc_member_count);
   4920             }
   4921             if (SHR_BITGET(l2mc_tpbm, i)) {
   4922                 l2mc_localport_array[l2mc_localport_count++] = loc_port;
   4923                 SHR_BITSET(l2mc_my_modid_bmap, l2mc_member_count);
   4924             }
   4925             if (SHR_BITGET(bcast_tpbm, i)) {
   4926                 bcast_localport_array[bcast_localport_count++] = loc_port;
   4927                 SHR_BITSET(bcast_my_modid_bmap, bcast_member_count);
   4928             }
   4929             if (SHR_BITGET(dlf_tpbm, i)) {
   4930                 dlf_localport_array[dlf_localport_count++] = loc_port;
   4931                 SHR_BITSET(dlf_my_modid_bmap, dlf_member_count);
   4932             }
   4933         }
   4934 
   4935         if (SHR_BITGET(ipmc_tpbm, i)) {
   4936             /* Eligible for IPMC forwarding */
   4937             ipmc_member_count++;
   4938         }
   4939         if (SHR_BITGET(l2mc_tpbm, i)) {
   4940             /* Eligible for L2MC forwarding */
   4941             l2mc_member_count++;
   4942         }
   4943         if (SHR_BITGET(bcast_tpbm, i)) {
   4944             /* Eligible for broadcast forwarding */
   4945             bcast_member_count++;
   4946         }
   4947         if (SHR_BITGET(dlf_tpbm, i)) {
   4948             /* Eligible for DLF forwarding */
   4949             dlf_member_count++;
   4950         }
   4951     }
   4952 
   4953     /* Figure out which trunk ports are eligible for egress and
   4954      * unicast egress
   4955      */
   4956     num_egr_ports = add_info->num_ports - negr_disable_port;
   4957     if (num_egr_ports > 0) {
   4958         egr_hwmod = sal_alloc(sizeof(bcm_module_t) * num_egr_ports,
   4959                 "egr_hwmod");
   4960         if (egr_hwmod == NULL) {
   4961             _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(BCM_E_MEMORY);
   4962         }
   4963         egr_hwport = sal_alloc(sizeof(bcm_port_t) * num_egr_ports,
   4964                 "egr_hwport");
   4965         if (egr_hwport == NULL) {
   4966             _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(BCM_E_MEMORY);
   4967         }
   4968         egr_member_flags = sal_alloc(sizeof(uint32) * num_egr_ports,
   4969                 "egr_member_flags");
   4970         if (egr_member_flags == NULL) {
   4971             _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(BCM_E_MEMORY);
   4972         }
   4973         egr_scaling_factor = sal_alloc(sizeof(int) * num_egr_ports,
   4974                 "egr_scaling_factor");
   4975         if (egr_scaling_factor == NULL) {
   4976             _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(BCM_E_MEMORY);
   4977         }
   4978         egr_load_weight = sal_alloc(sizeof(int) * num_egr_ports,
   4979                 "egr_load_weight");
   4980         if (egr_load_weight == NULL) {
   4981             _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(BCM_E_MEMORY);
   4982         }
   4983         egr_qsize_weight = sal_alloc(sizeof(int) * num_egr_ports,
   4984                 "egr_qsize_weight");
   4985         if (egr_qsize_weight == NULL) {
   4986             _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(BCM_E_MEMORY);
   4987         }
   4988         for (i = 0, j = 0; i < add_info->num_ports; i++) {
   4989             if (add_info->member_flags[i] & BCM_TRUNK_MEMBER_EGRESS_DISABLE) {
   4990                 continue;
   4991             }
   4992             egr_hwmod[j] = hwmod[i];
   4993             egr_hwport[j] = hwport[i];
   4994             egr_member_flags[j] = add_info->member_flags[i];
   4995             egr_scaling_factor[j] = add_info->dynamic_scaling_factor[i];
   4996             egr_load_weight[j] = add_info->dynamic_load_weight[i];
   4997             egr_qsize_weight[j] = add_info->dynamic_queue_size_weight[i];
   4998             j++;
   4999         }
   5000 
   5001         num_uc_egr_ports = num_egr_ports - num_uc_egr_disable_port;
   5002         if (num_uc_egr_ports > 0 ) {
   5003             uc_egr_hwmod = sal_alloc(sizeof(bcm_module_t) * num_uc_egr_ports,
   5004                     "uc_egr_hwmod");
   5005             if (uc_egr_hwmod == NULL) {
   5006                 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(BCM_E_MEMORY);
   5007             }
   5008             uc_egr_hwport = sal_alloc(sizeof(bcm_port_t) * num_uc_egr_ports,
   5009                     "uc_egr_hwport");
   5010             if (uc_egr_hwport == NULL) {
   5011                 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(BCM_E_MEMORY);
   5012             }
   5013             uc_egr_scaling_factor = sal_alloc(sizeof(int) * num_uc_egr_ports,
   5014                     "uc_egr_scaling_factor");
   5015             if (uc_egr_scaling_factor == NULL) {
   5016                 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(BCM_E_MEMORY);
   5017             }
   5018             uc_egr_load_weight = sal_alloc(sizeof(int) * num_uc_egr_ports,
   5019                     "uc_egr_load_weight");
   5020             if (uc_egr_load_weight == NULL) {
   5021                 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(BCM_E_MEMORY);
   5022             }
   5023             uc_egr_qsize_weight = sal_alloc(sizeof(int) * num_uc_egr_ports,
   5024                     "uc_egr_qsize_weight");
   5025             if (uc_egr_qsize_weight == NULL) {
   5026                 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(BCM_E_MEMORY);
   5027             }
   5028             for (i = 0, k = 0; i < j; i++) {
   5029                 if (egr_member_flags[i] &
   5030                         BCM_TRUNK_MEMBER_UNICAST_EGRESS_DISABLE) {
   5031                     continue;
   5032                 }
   5033                 uc_egr_hwmod[k] = egr_hwmod[i];
   5034                 uc_egr_hwport[k] = egr_hwport[i];
   5035                 uc_egr_scaling_factor[k] = egr_scaling_factor[i];
   5036                 uc_egr_load_weight[k] = egr_load_weight[i];
   5037                 uc_egr_qsize_weight[k] = egr_qsize_weight[i];
   5038                 k++;
   5039             }
   5040         }
   5041     } else {
   5042         /* Time to use entry 0 reserved for this purpose.
   5043          * Set mod and port to inavlid values in entry */
   5044         if (bcm_trident_trunk_mbr_zero_rsvd[unit] == TRUE) {
   5045             trunk_member_entry_t trunk_member_entry;
   5046             sal_memset(&trunk_member_entry, 0, sizeof(trunk_member_entry_t));
   5047             soc_TRUNK_MEMBERm_field32_set(unit,&trunk_member_entry,
   5048                                           MODULE_IDf,0xff);
   5049             soc_TRUNK_MEMBERm_field32_set(unit,&trunk_member_entry,
   5050                                           PORT_NUMf, 0x7f);
   5051             SOC_IF_ERROR_RETURN
   5052                 (WRITE_TRUNK_MEMBERm(unit, MEM_BLOCK_ALL,
   5053                                      0,&trunk_member_entry));
   5054         }
   5055     }
   5056 
   5057     /* Configure static load balancing */
   5058     if (t_info->in_use) {
   5059         rv = _bcm_trident_lag_slb_free_resource(unit, tid);
   5060         if (BCM_FAILURE(rv)) {
   5061             _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(rv);
   5062         }
   5063     }
   5064     rv = _bcm_trident_lag_slb_set(unit, tid, num_uc_egr_ports,
   5065             uc_egr_hwmod, uc_egr_hwport, t_info); 
   5066     if (BCM_FAILURE(rv)) {
   5067         _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(rv);
   5068     }
   5069 
   5070 #ifdef BCM_TRIUMPH3_SUPPORT
   5071     /* Configure dynamic load balancing */
   5072     if (soc_feature(unit, soc_feature_lag_dlb) &&
   5073         !soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) {
   5074         if (t_info->in_use) {
   5075             rv = bcm_tr3_lag_dlb_free_resource(unit, tid);
   5076             if (BCM_FAILURE(rv)) {
   5077                 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(rv);
   5078             }
   5079         }
   5080         rv = bcm_tr3_lag_dlb_set(unit, tid, add_info, num_uc_egr_ports,
   5081                 uc_egr_hwmod, uc_egr_hwport, uc_egr_scaling_factor,
   5082                 uc_egr_load_weight);
   5083         if (BCM_FAILURE(rv)) {
   5084             _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(rv);
   5085         }
   5086     }
   5087 #endif /* BCM_TRIUMPH3_SUPPORT */
   5088 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT)
   5089     /* Configure dynamic load balancing */
   5090     if (soc_feature(unit, soc_feature_lag_dlb) &&
   5091         soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) {
   5092         if (t_info->in_use) {
   5093             rv = bcm_th2_hgt_lag_dlb_free_resource(unit, tid, 0);
   5094             if (BCM_FAILURE(rv)) {
   5095                 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(rv);
   5096             }
   5097         }
   5098         rv = bcm_th2_hgt_lag_dlb_set(unit, tid, 0, add_info, num_uc_egr_ports,
   5099                 uc_egr_hwmod, uc_egr_hwport, uc_egr_scaling_factor,
   5100                 uc_egr_load_weight, uc_egr_qsize_weight);
   5101         if (BCM_FAILURE(rv)) {
   5102             _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(rv);
   5103         }
   5104     }
   5105 #endif /* BCM_TOMAHAWK2_SUPPORT */
   5106 #ifdef BCM_TRIDENT2_SUPPORT
   5107     /* Configure resilient hashing */
   5108     if (soc_feature(unit, soc_feature_lag_resilient_hash)) {
   5109         bcm_module_t del_mod;
   5110         bcm_port_t del_port;
   5111 
   5112         if (op == TRUNK_MEMBER_OP_SET) {
   5113             if ((stored_info->in_use) &&
   5114                 (add_info->psc == BCM_TRUNK_PSC_DYNAMIC_RESILIENT) &&
   5115                 (stored_info->psc == BCM_TRUNK_PSC_DYNAMIC_RESILIENT) &&
   5116                 (add_info->dynamic_size != 0) &&
   5117                 (add_info->dynamic_size == stored_info->dynamic_size)) {
   5118                 rv = bcm_td2_lag_rh_replace(unit, tid, add_info,
   5119                         num_uc_egr_ports, uc_egr_hwmod, uc_egr_hwport,
   5120                         MEMBER_INFO(unit, tid).num_ports,
   5121                         MEMBER_INFO(unit, tid).modport,
   5122                         MEMBER_INFO(unit, tid).member_flags);
   5123                 if (BCM_FAILURE(rv)) {
   5124                     _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(rv);
   5125                 }
   5126             } else {
   5127                 if (t_info->in_use) {
   5128                     rv = bcm_td2_lag_rh_free_resource(unit, tid);
   5129                     if (BCM_FAILURE(rv)) {
   5130                         _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(rv);
   5131                     }
   5132                 }
   5133                 if (add_info->psc == BCM_TRUNK_PSC_DYNAMIC_RESILIENT) {
   5134                     rv = bcm_td2_lag_rh_set(unit, tid, add_info,
   5135                             num_uc_egr_ports, uc_egr_hwmod, uc_egr_hwport);
   5136                     if (BCM_FAILURE(rv)) {
   5137                         _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(rv);
   5138                     }
   5139                 }
   5140             }
   5141         } else if (op == TRUNK_MEMBER_OP_ADD) {
   5142             if (add_info->psc == BCM_TRUNK_PSC_DYNAMIC_RESILIENT) {
   5143                 /* Add the new member if it's eligible for resilient hashing */
   5144                 if (!(member->flags & BCM_TRUNK_MEMBER_EGRESS_DISABLE) &&
   5145                     !(member->flags & BCM_TRUNK_MEMBER_UNICAST_EGRESS_DISABLE)) {
   5146                     rv = bcm_td2_lag_rh_add(unit, tid, add_info,
   5147                             num_uc_egr_ports, uc_egr_hwmod, uc_egr_hwport,
   5148                             member);
   5149                     if (BCM_FAILURE(rv)) {
   5150                         _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(rv);
   5151                     }
   5152                 }
   5153             }
   5154         } else if (op == TRUNK_MEMBER_OP_DELETE) {
   5155             if (add_info->psc == BCM_TRUNK_PSC_DYNAMIC_RESILIENT) {
   5156                 for (i = 0; i < MEMBER_INFO(unit, tid).num_ports; i++) {
   5157                     mod = MEMBER_INFO(unit, tid).modport[i] >> 8;
   5158                     port = MEMBER_INFO(unit, tid).modport[i] & 0xff;
   5159                     rv = _bcm_esw_trunk_gport_array_resolve(unit, FALSE, 1,
   5160                             &member->gport, &del_port, &del_mod);
   5161                     if (BCM_FAILURE(rv)) {
   5162                         _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(rv);
   5163                     }
   5164                     if (mod == del_mod && port == del_port) {
   5165                         break;
   5166                     }
   5167                 }
   5168                 if (i == MEMBER_INFO(unit, tid).num_ports) {
   5169                     /* The member to be deleted is not found. */
   5170                     _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(BCM_E_NOT_FOUND);
   5171                 }
   5172                 /* Delete the member if it was resilient hashing eligible */
   5173                 if (!(MEMBER_INFO(unit, tid).member_flags[i] &
   5174                             BCM_TRUNK_MEMBER_EGRESS_DISABLE) &&
   5175                     !(MEMBER_INFO(unit, tid).member_flags[i] &
   5176                         BCM_TRUNK_MEMBER_UNICAST_EGRESS_DISABLE)) {
   5177                     rv = bcm_td2_lag_rh_delete(unit, tid, add_info,
   5178                             num_uc_egr_ports, uc_egr_hwmod, uc_egr_hwport,
   5179                             member);
   5180                     if (BCM_FAILURE(rv)) {
   5181                         _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(rv);
   5182                     }
   5183                 }
   5184             }
   5185         } else {
   5186             _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(BCM_E_PARAM);
   5187         }
   5188     }
   5189 #endif /* BCM_TRIDENT2_SUPPORT */
   5190 
   5191     /* Update TRUNK_BITMAP table */
   5192     rv = READ_TRUNK_BITMAPm(unit, MEM_BLOCK_ANY, tid, &trunk_bitmap_entry);
   5193     if (BCM_FAILURE(rv)) {
   5194         _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(rv);
   5195     }
   5196     SOC_PBMP_CLEAR(old_trunk_pbmp);
   5197     soc_mem_pbmp_field_get(unit, TRUNK_BITMAPm, &trunk_bitmap_entry,
   5198             TRUNK_BITMAPf, &old_trunk_pbmp);
   5199     soc_mem_pbmp_field_set(unit, TRUNK_BITMAPm, &trunk_bitmap_entry,
   5200             TRUNK_BITMAPf, &new_trunk_pbmp);
   5201     rv = WRITE_TRUNK_BITMAPm(unit, MEM_BLOCK_ALL, tid, &trunk_bitmap_entry);
   5202     if (BCM_FAILURE(rv)) {
   5203         _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(rv);
   5204     }
   5205 
   5206     /* Update source trunk map configuration */
   5207     for (i = 0; i < add_info->num_ports; i++) {
   5208         mod = hwmod[i%add_info->num_ports];
   5209         port = hwport[i%add_info->num_ports];
   5210 
   5211         if (add_info->member_flags[i] & BCM_TRUNK_MEMBER_INGRESS_DISABLE) {
   5212             rv = _bcm_trident_trunk_set_port_property(unit, mod, port, -1);
   5213         } else {
   5214             rv = _bcm_trident_trunk_set_port_property(unit, mod, port, tid);
   5215         }
   5216         if (BCM_FAILURE(rv)) {
   5217             _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(rv);
   5218         }
   5219     }    
   5220 
   5221     /* Update the trunk block mask */
   5222     if (SOC_PBMP_NOT_NULL(new_trunk_pbmp) ||
   5223             SOC_PBMP_NOT_NULL(old_trunk_pbmp)) {
   5224         rv = _bcm_trident_trunk_block_mask(unit,
   5225                 TRUNK_BLOCK_MASK_TYPE_IPMC,
   5226                 old_trunk_pbmp,
   5227                 new_trunk_pbmp,
   5228                 ipmc_localport_array,
   5229                 ipmc_localport_count,
   5230                 ipmc_my_modid_bmap,
   5231                 ipmc_member_count,
   5232                 add_info->flags);
   5233         if (BCM_FAILURE(rv)) {
   5234             _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(rv);
   5235         }
   5236         rv = _bcm_trident_trunk_block_mask(unit,
   5237                 TRUNK_BLOCK_MASK_TYPE_L2MC,
   5238                 old_trunk_pbmp,
   5239                 new_trunk_pbmp,
   5240                 l2mc_localport_array,
   5241                 l2mc_localport_count,
   5242                 l2mc_my_modid_bmap,
   5243                 l2mc_member_count,
   5244                 add_info->flags);
   5245         if (BCM_FAILURE(rv)) {
   5246             _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(rv);
   5247         }
   5248         rv = _bcm_trident_trunk_block_mask(unit,
   5249                 TRUNK_BLOCK_MASK_TYPE_BCAST,
   5250                 old_trunk_pbmp,
   5251                 new_trunk_pbmp,
   5252                 bcast_localport_array,
   5253                 bcast_localport_count,
   5254                 bcast_my_modid_bmap,
   5255                 bcast_member_count,
   5256                 add_info->flags);
   5257         if (BCM_FAILURE(rv)) {
   5258             _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(rv);
   5259         }
   5260         rv = _bcm_trident_trunk_block_mask(unit,
   5261                 TRUNK_BLOCK_MASK_TYPE_DLF,
   5262                 old_trunk_pbmp,
   5263                 new_trunk_pbmp,
   5264                 dlf_localport_array,
   5265                 dlf_localport_count,
   5266                 dlf_my_modid_bmap,
   5267                 dlf_member_count,
   5268                 add_info->flags);
   5269         if (BCM_FAILURE(rv)) {
   5270             _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(rv);
   5271         }
   5272 
   5273 #if defined(BCM_TRIUMPH3_SUPPORT) && defined(INCLUDE_L3)
   5274         if (soc_feature(unit, soc_feature_axp)) {
   5275             rv = _bcm_tr3_wlan_trunk_block_mask_update(unit);
   5276             if (BCM_FAILURE(rv)) {
   5277                 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(rv);
   5278             }
   5279         }
   5280 #endif /* BCM_TRIUMPH3_SUPPORT && defined(INCLUDE_L3) */
   5281     }
   5282 
   5283     /* Harware trunk failover */
   5284     if (soc_feature(unit, soc_feature_port_lag_failover)) {
   5285         rv = _bcm_trident_trunk_failover_set(unit, tid, FALSE, add_info);
   5286         if (BCM_FAILURE(rv)) {
   5287             _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(rv);
   5288         }
   5289     }
   5290 
   5291     /* Software trunk failover */
   5292     rv = _bcm_trident_trunk_swfailover_fp_set(unit,
   5293                                            tid,
   5294                                            t_info->rtag,
   5295                                            num_egr_ports,
   5296                                            egr_hwmod,
   5297                                            egr_hwport,
   5298                                            egr_member_flags,
   5299                                            add_info->flags);
   5300     if (BCM_FAILURE(rv)) {
   5301         _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(rv);
   5302     }
   5303 
   5304     /* Figure out which members are leaving, staying or joining
   5305      * the trunk group
   5306      */
   5307     if (t_info->in_use) {
   5308         if (MEMBER_INFO(unit, tid).num_ports > 0) {
   5309             leaving_members = sal_alloc(sizeof(bcm_gport_t) *
   5310                     MEMBER_INFO(unit, tid).num_ports, "leaving members");
   5311             if (leaving_members == NULL) {
   5312                 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(BCM_E_MEMORY);
   5313             }
   5314             sal_memset(leaving_members, 0,
   5315                     sizeof(bcm_gport_t) * MEMBER_INFO(unit, tid).num_ports);
   5316 
   5317             staying_members = sal_alloc(sizeof(bcm_gport_t) *
   5318                     MEMBER_INFO(unit, tid).num_ports, "staying members");
   5319             if (staying_members == NULL) {
   5320                 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(BCM_E_MEMORY);
   5321             }
   5322             sal_memset(staying_members, 0,
   5323                     sizeof(bcm_gport_t) * MEMBER_INFO(unit, tid).num_ports);
   5324 
   5325             for (i = 0; i < MEMBER_INFO(unit, tid).num_ports; i++) {
   5326                 mod = MEMBER_INFO(unit, tid).modport[i] >> 8;
   5327                 port = MEMBER_INFO(unit, tid).modport[i] & 0xff;
   5328                 BCM_GPORT_MODPORT_SET(gport, mod, port);
   5329 
   5330                 /* Invalidate port only if it is not a part from new trunk group */
   5331                 remove_trunk_port = TRUE;
   5332                 for (j = 0; j < add_info->num_ports; j++) {
   5333                     if (mod == add_info->tm[j] && port == add_info->tp[j]) {
   5334                         remove_trunk_port = FALSE;
   5335                     }
   5336                 }
   5337                 if (remove_trunk_port) {
   5338                     /* Add port to array containing members leaving the trunk
   5339                      * group if it is different from previous leaving members
   5340                      */
   5341                     match_leaving_members = FALSE;
   5342                     for (k = 0; k < num_leaving_members; k++) {
   5343                         if (gport == leaving_members[k]) {
   5344                             match_leaving_members = TRUE;
   5345                             break;
   5346                         }
   5347                     }
   5348                     if (!match_leaving_members) {
   5349                         leaving_members[num_leaving_members++] = gport;
   5350                     }
   5351 
   5352                     rv = _bcm_trident_trunk_set_port_property(unit, mod, port, -1);
   5353                     if (BCM_FAILURE(rv)) {
   5354                         _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(rv);
   5355                     }
   5356                     if (soc_feature(unit, soc_feature_port_lag_failover)) {
   5357                         is_local = is_local_subport = 0;
   5358                         /* If deleted port is local, clear HW failover info */
   5359                         rv = _bcm_esw_modid_is_local(unit, mod, &is_local);
   5360                         if (BCM_FAILURE(rv)) {
   5361                             _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(rv);
   5362                         }
   5363 #if defined(BCM_KATANA2_SUPPORT)
   5364                         if (soc_feature(unit, soc_feature_linkphy_coe) ||
   5365                                 soc_feature(unit, soc_feature_subtag_coe)) {
   5366                             rv = _bcm_kt2_modport_is_local_coe_subport(unit,
   5367                                     mod, port, &is_local_subport);
   5368                             if (BCM_FAILURE(rv)) {
   5369                                 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(rv);
   5370                             }
   5371                         }
   5372 #endif
   5373                         if (!is_local && !is_local_subport) {
   5374                             continue;
   5375                         }
   5376 
   5377                         BCM_GPORT_MODPORT_SET(gport, mod, port);
   5378                         rv = bcm_esw_port_local_get(unit, gport, &loc_port);
   5379                         if (BCM_FAILURE(rv)) {
   5380                             _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(rv);
   5381                         }
   5382                         if (IS_HG_PORT(unit, loc_port)) {
   5383                             continue;
   5384                         }
   5385                         /* skip Cascaded Physical Ports*/
   5386                         if ((soc_feature(unit, soc_feature_linkphy_coe) &&
   5387                             IS_LP_PORT(unit, loc_port)) ||
   5388                             (soc_feature(unit, soc_feature_subtag_coe) &&
   5389                             IS_SUBTAG_PORT(unit, loc_port)) ||
   5390                             (soc_feature(unit, soc_feature_hgproxy_subtag_coe) &&
   5391                             IS_SUBTAG_PORT (unit, loc_port))) {
   5392                             continue;
   5393                         }
   5394 #if defined(BCM_HELIX5_SUPPORT)
   5395                         /* Skip q-ports in HX5 since trunk hardware failover is
   5396                          * not supported for PM4x10Q.
   5397                          */
   5398                         if (IS_QSGMII_PORT(unit, loc_port)) {
   5399                             continue;
   5400                         }
   5401 #endif /* BCM_HELIX5_SUPPORT */
   5402                         rv = _bcm_trident_trunk_hwfailover_set(unit, tid,
   5403                                 FALSE, port, mod, add_info->psc,
   5404                                 0, 0, NULL, NULL);
   5405                         if (BCM_FAILURE(rv)) {
   5406                             _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(rv);
   5407                         }
   5408                     }
   5409                 } else {
   5410                     /* Add port to array containing members staying in the trunk
   5411                      * group if it is different from previous staying members
   5412                      */
   5413                     match_staying_members = FALSE;
   5414                     for (k = 0; k < num_staying_members; k++) {
   5415                         if (gport == staying_members[k]) {
   5416                             match_staying_members = TRUE;
   5417                             break;
   5418                         }
   5419                     }
   5420                     if (!match_staying_members) {
   5421                         staying_members[num_staying_members++] = gport;
   5422                     }
   5423 
   5424                 }
   5425             }
   5426         }
   5427     }
   5428 
   5429     joining_members = sal_alloc(sizeof(bcm_gport_t) * add_info->num_ports,
   5430             "joining members");
   5431     if (joining_members == NULL) {
   5432         _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(BCM_E_MEMORY);
   5433     }
   5434     sal_memset(joining_members, 0, sizeof(bcm_gport_t) * add_info->num_ports);
   5435     for (i = 0; i < add_info->num_ports; i++) {
   5436         BCM_GPORT_MODPORT_SET(gport, hwmod[i], hwport[i]); 
   5437         match_staying_members = FALSE;
   5438         for (j = 0; j < num_staying_members; j++) {
   5439             if (gport == staying_members[j]) {
   5440                 match_staying_members = TRUE;
   5441                 break;
   5442             }
   5443         }
   5444         if (!match_staying_members) {
   5445             match_joining_members = FALSE;
   5446             for (j = 0; j < num_joining_members; j++) {
   5447                 if (gport == joining_members[j]) {
   5448                     match_joining_members = TRUE;
   5449                     break;
   5450                 }
   5451             }
   5452             if (!match_joining_members) {
   5453                 joining_members[num_joining_members++] = gport;
   5454             }
   5455         }
   5456     }
   5457  
   5458     /* Migrate trunk properties from old members to new members */
   5459     rv = _bcm_xgs3_trunk_property_migrate(unit,
   5460                 num_leaving_members, leaving_members,
   5461                 num_staying_members, staying_members,
   5462                 num_joining_members, joining_members);
   5463     if (BCM_FAILURE(rv)) {
   5464         _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(rv);
   5465     }
   5466 
   5467     /* Save new trunk member info */
   5468     if (MEMBER_INFO(unit, tid).modport) {
   5469         sal_free(MEMBER_INFO(unit, tid).modport);
   5470         MEMBER_INFO(unit, tid).modport = NULL;
   5471     }
   5472     if (MEMBER_INFO(unit, tid).member_flags) {
   5473         sal_free(MEMBER_INFO(unit, tid).member_flags);
   5474         MEMBER_INFO(unit, tid).member_flags = NULL;
   5475     }
   5476 
   5477     MEMBER_INFO(unit, tid).modport = sal_alloc(
   5478             sizeof(uint16) * add_info->num_ports, "member info modport");
   5479     if (NULL == MEMBER_INFO(unit, tid).modport) {
   5480         _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(BCM_E_MEMORY);
   5481     }
   5482 
   5483     MEMBER_INFO(unit, tid).member_flags = sal_alloc(
   5484             sizeof(uint32) * add_info->num_ports, "member info flags");
   5485     if (NULL == MEMBER_INFO(unit, tid).member_flags) {
   5486         sal_free(MEMBER_INFO(unit, tid).modport);
   5487         MEMBER_INFO(unit, tid).modport = NULL;
   5488         _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(BCM_E_MEMORY);
   5489     }
   5490 
   5491     for (i = 0; i < add_info->num_ports; i++) {
   5492         MEMBER_INFO(unit, tid).modport[i] = ((hwmod[i] & 0xff) << 8) |
   5493                                             (hwport[i] & 0xff);
   5494         MEMBER_INFO(unit, tid).member_flags[i] = add_info->member_flags[i];
   5495     }
   5496     MEMBER_INFO(unit, tid).num_ports = add_info->num_ports;
   5497 
   5498     /* Call Trill module to clear states for local leaving members, joining members  */
   5499 #ifdef INCLUDE_L3
   5500     if (soc_feature(unit, soc_feature_trill)
   5501         || soc_feature(unit, soc_feature_mpls)
   5502         || soc_feature(unit, soc_feature_vxlan)
   5503         || soc_feature(unit, soc_feature_l2gre)) {
   5504         bcm_port_t local_member;
   5505         bcm_port_t local_member_arr[SOC_MAX_NUM_PORTS];
   5506         int num_local_members;
   5507 
   5508         num_local_members = 0;
   5509         for (i = 0; i < num_leaving_members; i++) {
   5510             if (BCM_SUCCESS(bcm_esw_port_local_get(unit, leaving_members[i],
   5511                             &local_member))) {
   5512                 local_member_arr[num_local_members++] = local_member;
   5513             }
   5514         }
   5515 
   5516         /* Support remote trunk members */
   5517         if (num_leaving_members > 0) {
   5518 #ifdef BCM_TRIDENT2_SUPPORT
   5519             if (soc_feature(unit, soc_feature_vxlan)) {
   5520                 rv = _bcm_esw_vxlan_trunk_member_delete(unit, tid,
   5521                         num_leaving_members, leaving_members);
   5522                 if (BCM_FAILURE(rv)) {
   5523                     _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(rv);
   5524                 }
   5525             }
   5526 #endif
   5527 
   5528 #ifdef BCM_TRIUMPH3_SUPPORT
   5529             if (soc_feature(unit, soc_feature_l2gre)) {
   5530                 rv = _bcm_esw_l2gre_trunk_member_delete(unit, tid,
   5531                         num_leaving_members, leaving_members);
   5532                 if (BCM_FAILURE(rv)) {
   5533                     _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(rv);
   5534                 }
   5535             }
   5536 #endif
   5537         }
   5538 
   5539         if (num_local_members > 0) {
   5540             if (soc_feature(unit, soc_feature_trill)) {
   5541                 rv = _bcm_esw_trill_trunk_member_delete(unit, tid,
   5542                         num_local_members, local_member_arr);
   5543                 if (BCM_FAILURE(rv)) {
   5544                     _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(rv);
   5545                 }
   5546             }
   5547 #ifdef BCM_TRIUMPH_SUPPORT
   5548             if (soc_feature(unit, soc_feature_mpls)) {
   5549                 rv = _bcm_esw_mpls_trunk_member_delete(unit, tid,
   5550                         num_local_members, local_member_arr);
   5551                 if (BCM_FAILURE(rv)) {
   5552                     _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(rv);
   5553                 }
   5554             }
   5555 #endif
   5556         }
   5557 
   5558         num_local_members = 0;
   5559         for (i = 0; i < num_joining_members; i++) {
   5560             if (BCM_SUCCESS(bcm_esw_port_local_get(unit, joining_members[i],
   5561                             &local_member))) {
   5562                 local_member_arr[num_local_members++] = local_member;
   5563             }
   5564         }
   5565 
   5566         /* Support remote trunk members */
   5567         if (num_joining_members > 0) {
   5568 #ifdef BCM_TRIDENT2_SUPPORT
   5569             if (soc_feature(unit, soc_feature_vxlan)) {
   5570                 rv = _bcm_esw_vxlan_trunk_member_add(unit, tid,
   5571                         num_joining_members, joining_members);
   5572                 if (BCM_FAILURE(rv)) {
   5573                     _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(rv);
   5574                 } 
   5575             }
   5576 #endif
   5577 
   5578 #ifdef BCM_TRIUMPH3_SUPPORT
   5579             if (soc_feature(unit, soc_feature_l2gre)) {
   5580                 rv = _bcm_esw_l2gre_trunk_member_add(unit, tid,
   5581                         num_joining_members, joining_members);
   5582                 if (BCM_FAILURE(rv)) {
   5583                     _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(rv);
   5584                 } 
   5585             }
   5586 #endif 
   5587         }
   5588 
   5589         if (num_local_members > 0) {
   5590             if (soc_feature(unit, soc_feature_trill)) {
   5591                 rv = _bcm_esw_trill_trunk_member_add(unit, tid,
   5592                         num_local_members, local_member_arr);
   5593                 if (BCM_FAILURE(rv)) {
   5594                     _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(rv);
   5595                 }
   5596             }
   5597 #ifdef BCM_TRIUMPH_SUPPORT
   5598             if (soc_feature(unit, soc_feature_mpls)) {
   5599                 rv = _bcm_esw_mpls_trunk_member_add(unit, tid,
   5600                         num_local_members, local_member_arr);
   5601                 if (BCM_FAILURE(rv)) {
   5602                     _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(rv);
   5603                 }
   5604             }
   5605 #endif
   5606         }
   5607     }
   5608 #endif /* INCLUDE_L3 */
   5609 
   5610     _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(rv);
   5611 }
   5612 
   5613 /*
   5614  * Function:
   5615  *      bcm_trident_trunk_fp_destroy
   5616  * Purpose:
   5617  *      Remove front-panel trunk group.
   5618  * Parameters:
   5619  *      unit     - (IN) SOC unit number. 
   5620  *      tid      - (IN) Trunk group ID.
   5621  *      t_info   - (IN) Pointer to trunk info.
   5622  * Returns:
   5623  *      BCM_E_xxx
   5624  */
   5625 STATIC int
   5626 _bcm_trident_trunk_fp_destroy(int unit,
   5627         bcm_trunk_t tid,
   5628         trunk_private_t *t_info)
   5629 {
   5630     trunk_group_entry_t         tg_entry;
   5631     trunk_bitmap_entry_t        trunk_bitmap_entry;
   5632     trunk_member_entry_t        trunk_member_entry;
   5633     pbmp_t                      old_trunk_pbmp, new_trunk_pbmp;
   5634     int                         old_base_ptr, old_tg_size, old_rtag;
   5635     int                         old_num_entries;
   5636     bcm_module_t                mod;
   5637     bcm_port_t                  port;
   5638     bcm_gport_t                 gport;
   5639     int                         i, j;
   5640     int                         num_leaving_members = 0;
   5641     bcm_gport_t                 *leaving_members = NULL;
   5642     int                         match_leaving_members;
   5643     int                         rv = BCM_E_NONE;
   5644 
   5645     /* Clear dynamic load balancing */
   5646 #ifdef BCM_TRIUMPH3_SUPPORT
   5647     if (soc_feature(unit, soc_feature_lag_dlb)) {
   5648 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT)
   5649         if (soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) {
   5650             BCM_IF_ERROR_RETURN(bcm_th2_hgt_lag_dlb_free_resource(unit, tid, 0));
   5651         } else
   5652 #endif /* BCM_TOMAHAWK2_SUPPORT */
   5653         {
   5654             BCM_IF_ERROR_RETURN(bcm_tr3_lag_dlb_free_resource(unit, tid));
   5655         }
   5656     }
   5657 #endif /* BCM_TRIUMPH3_SUPPORT */
   5658 
   5659 #ifdef BCM_TRIDENT2_SUPPORT
   5660     /* Clear resilient hashing configuration */
   5661     if (soc_feature(unit, soc_feature_lag_resilient_hash)) {
   5662         BCM_IF_ERROR_RETURN(bcm_td2_lag_rh_free_resource(unit, tid));
   5663     }
   5664 #endif /* BCM_TRIDENT2_SUPPORT */
   5665 
   5666     /* Get old trunk bitmap */
   5667     SOC_IF_ERROR_RETURN
   5668         (READ_TRUNK_BITMAPm(unit, MEM_BLOCK_ANY, tid, &trunk_bitmap_entry));
   5669     SOC_PBMP_CLEAR(old_trunk_pbmp);
   5670     soc_mem_pbmp_field_get(unit, TRUNK_BITMAPm, &trunk_bitmap_entry,
   5671             TRUNK_BITMAPf, &old_trunk_pbmp);
   5672 
   5673     /* Get old trunk group entry */
   5674     SOC_IF_ERROR_RETURN
   5675         (READ_TRUNK_GROUPm(unit, MEM_BLOCK_ANY, tid, &tg_entry));
   5676     old_base_ptr = soc_TRUNK_GROUPm_field32_get(unit, &tg_entry, BASE_PTRf);
   5677     old_tg_size = 1 + soc_TRUNK_GROUPm_field32_get(unit, &tg_entry, TG_SIZEf);
   5678     old_rtag = soc_TRUNK_GROUPm_field32_get(unit, &tg_entry, RTAGf);
   5679 
   5680     /* Clear TRUNK_BITMAP table */
   5681     SOC_IF_ERROR_RETURN
   5682         (WRITE_TRUNK_BITMAPm(unit, MEM_BLOCK_ALL, tid,
   5683                              soc_mem_entry_null(unit, TRUNK_BITMAPm)));
   5684 
   5685     /* Clear TRUNK_GROUP table */
   5686     SOC_IF_ERROR_RETURN
   5687         (WRITE_TRUNK_GROUPm(unit, MEM_BLOCK_ALL, tid,
   5688                             soc_mem_entry_null(unit, TRUNK_GROUPm)));
   5689 
   5690     /* Clear TRUNK_MEMBER table */
   5691     if (old_rtag != 0) {
   5692         old_num_entries = old_tg_size;
   5693         if (old_rtag >= 1 && old_rtag <= 6) {
   5694 #ifdef BCM_KATANA_SUPPORT
   5695             if (SOC_IS_KATANAX(unit)) {
   5696                 old_num_entries = _BCM_KATANA_FP_TRUNK_RTAG1_6_MAX_PORTCNT;
   5697             } else
   5698 #endif
   5699             if (soc_feature(unit,
   5700                         soc_feature_rtag1_6_max_portcnt_less_than_rtag7)) { 
   5701                 old_num_entries = _BCM_TD_FP_TRUNK_RTAG1_6_MAX_PORTCNT;
   5702             }
   5703         } 
   5704 
   5705         _BCM_FP_TRUNK_MEMBER_USED_CLR_RANGE(unit, old_base_ptr, old_num_entries);
   5706 
   5707         for (i = 0; i < old_num_entries; i++) {
   5708             sal_memset(&trunk_member_entry, 0, sizeof(trunk_member_entry_t));
   5709             rv = WRITE_TRUNK_MEMBERm(unit, MEM_BLOCK_ALL, old_base_ptr + i,
   5710                     &trunk_member_entry); 
   5711             if (BCM_FAILURE(rv)) {
   5712                 return rv;
   5713             }
   5714         }
   5715     }
   5716 
   5717     /* Update source port to trunk mapping */
   5718 
   5719     if (MEMBER_INFO(unit, tid).num_ports > 0) {
   5720         leaving_members = sal_alloc(sizeof(bcm_gport_t) *
   5721                 MEMBER_INFO(unit, tid).num_ports, "leaving members");
   5722         if (leaving_members == NULL) {
   5723             return BCM_E_MEMORY;
   5724         }
   5725         sal_memset(leaving_members, 0,
   5726                 sizeof(bcm_gport_t) * MEMBER_INFO(unit, tid).num_ports);
   5727 
   5728         for (i = 0; i < MEMBER_INFO(unit, tid).num_ports; i++) {
   5729             mod = MEMBER_INFO(unit, tid).modport[i] >> 8;
   5730             port = MEMBER_INFO(unit, tid).modport[i] & 0xff;
   5731             BCM_GPORT_MODPORT_SET(gport, mod, port);
   5732 
   5733             match_leaving_members = FALSE;
   5734             for (j = 0; j < num_leaving_members; j++) {
   5735                 if (gport == leaving_members[j]) {
   5736                     match_leaving_members = TRUE;
   5737                     break;
   5738                 }
   5739             }
   5740             if (!match_leaving_members) {
   5741                 leaving_members[num_leaving_members++] = gport;
   5742             }
   5743 
   5744             rv = _bcm_trident_trunk_set_port_property(unit, mod, port, -1);
   5745             if (BCM_FAILURE(rv)) {
   5746                 sal_free(leaving_members);
   5747                 return rv;
   5748             }
   5749         }
   5750     }
   5751 
   5752     /*
   5753      * Remove ports from the block mask table
   5754      */
   5755     if (SOC_PBMP_NOT_NULL(old_trunk_pbmp)) {
   5756         SOC_PBMP_CLEAR(new_trunk_pbmp);
   5757         /* coverity[divide_by_zero] */
   5758         rv = _bcm_trident_trunk_block_mask(unit, TRUNK_BLOCK_MASK_TYPE_IPMC,
   5759                 old_trunk_pbmp, new_trunk_pbmp, NULL, 0,
   5760                 NULL, 0, t_info->flags);
   5761         if (BCM_FAILURE(rv)) {
   5762             sal_free(leaving_members);
   5763             return rv;
   5764         }
   5765         rv = _bcm_trident_trunk_block_mask(unit, TRUNK_BLOCK_MASK_TYPE_L2MC,
   5766                 old_trunk_pbmp, new_trunk_pbmp, NULL, 0,
   5767                 NULL, 0, t_info->flags);
   5768         if (BCM_FAILURE(rv)) {
   5769             sal_free(leaving_members);
   5770             return rv;
   5771         }
   5772         rv = _bcm_trident_trunk_block_mask(unit, TRUNK_BLOCK_MASK_TYPE_BCAST,
   5773                 old_trunk_pbmp, new_trunk_pbmp, NULL, 0,
   5774                 NULL, 0, t_info->flags);
   5775         if (BCM_FAILURE(rv)) {
   5776             sal_free(leaving_members);
   5777             return rv;
   5778         }
   5779         rv = _bcm_trident_trunk_block_mask(unit, TRUNK_BLOCK_MASK_TYPE_DLF,
   5780                 old_trunk_pbmp, new_trunk_pbmp, NULL, 0,
   5781                 NULL, 0, t_info->flags);
   5782         if (BCM_FAILURE(rv)) {
   5783             sal_free(leaving_members);
   5784             return rv;
   5785         }
   5786 
   5787 #if defined(BCM_TRIUMPH3_SUPPORT) && defined(INCLUDE_L3)
   5788         if (soc_feature(unit, soc_feature_axp)) {
   5789             rv = _bcm_tr3_wlan_trunk_block_mask_update(unit);
   5790             if (BCM_FAILURE(rv)) {
   5791                 sal_free(leaving_members);
   5792                 return rv;
   5793             }
   5794         }
   5795 #endif /* BCM_TRIUMPH3_SUPPORT && defined(INCLUDE_L3) */
   5796     }
   5797 
   5798     /*
   5799      * Remove ports from failover
   5800      */
   5801     if (soc_feature(unit, soc_feature_port_lag_failover)) {
   5802         rv = _bcm_trident_trunk_failover_set(unit, tid, FALSE, NULL);
   5803         if (BCM_FAILURE(rv)) {
   5804             sal_free(leaving_members);
   5805             return rv;
   5806         }
   5807     }
   5808 
   5809     rv = _bcm_trident_trunk_swfailover_fp_set(unit,
   5810                                               tid,
   5811                                               0,
   5812                                               0,
   5813                                               NULL,
   5814                                               NULL,
   5815                                               NULL,
   5816                                               0);
   5817     if (BCM_FAILURE(rv)) {
   5818         sal_free(leaving_members);
   5819         return rv;
   5820     }
   5821 
   5822     /* Clear trunk properties from members */
   5823     rv = _bcm_xgs3_trunk_property_migrate(unit,
   5824                 num_leaving_members, leaving_members,
   5825                 0, NULL, 0, NULL);
   5826     if (BCM_FAILURE(rv)) {
   5827         sal_free(leaving_members);
   5828         return rv;
   5829     }
   5830 
   5831     /* Clear trunk member info */
   5832     if (MEMBER_INFO(unit, tid).modport) {
   5833         sal_free(MEMBER_INFO(unit, tid).modport);
   5834         MEMBER_INFO(unit, tid).modport = NULL;
   5835     }
   5836     if (MEMBER_INFO(unit, tid).member_flags) {
   5837         sal_free(MEMBER_INFO(unit, tid).member_flags);
   5838         MEMBER_INFO(unit, tid).member_flags = NULL;
   5839     }
   5840     MEMBER_INFO(unit, tid).num_ports = 0;
   5841 
   5842     t_info->in_use = FALSE;
   5843 
   5844     sal_free(leaving_members);
   5845     return rv;
   5846 }
   5847 
   5848 /*
   5849  * Function:
   5850  *	bcm_trident_trunk_fp_get
   5851  * Purpose:
   5852  *      Return trunk information of given front panel trunk ID.
   5853  *      If t_data->num_ports = 0, return number of trunk members in
   5854  *      t_data->num_ports.
   5855  * Parameters:
   5856  *      unit   - (IN) StrataSwitch PCI device unit number (driver internal).
   5857  *      tid    - (IN) Trunk ID.
   5858  *      t_data - (OUT) Place to store returned trunk add info.
   5859  *      t_info - (IN) Trunk info.
   5860  * Returns:
   5861  *      BCM_E_NONE              Success.
   5862  *      BCM_E_XXX
   5863  */
   5864 STATIC int
   5865 _bcm_trident_trunk_fp_get(int unit,
   5866         bcm_trunk_t tid,
   5867         _esw_trunk_add_info_t *t_data,
   5868         trunk_private_t *t_info)
   5869 {
   5870     int i;
   5871     bcm_module_t mod;
   5872     bcm_port_t port;
   5873 
   5874     if (t_data->num_ports == 0) {
   5875         t_data->num_ports = MEMBER_INFO(unit, tid).num_ports;
   5876     } else {
   5877         if (MEMBER_INFO(unit, tid).num_ports <= t_data->num_ports) {
   5878             t_data->num_ports = MEMBER_INFO(unit, tid).num_ports;
   5879         } 
   5880 
   5881         for (i = 0; i < t_data->num_ports; i++) {
   5882             mod = MEMBER_INFO(unit, tid).modport[i] >> 8;
   5883             port = MEMBER_INFO(unit, tid).modport[i] & 0xff;
   5884             BCM_IF_ERROR_RETURN
   5885                 (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, mod, port,
   5886                                         &t_data->tm[i], &t_data->tp[i]));
   5887             t_data->member_flags[i] = MEMBER_INFO(unit, tid).member_flags[i];
   5888 
   5889             t_data->dynamic_scaling_factor[i] = 0;
   5890             t_data->dynamic_load_weight[i] = 0;
   5891             t_data->dynamic_queue_size_weight[i] = 0;
   5892             if ((t_data->psc == BCM_TRUNK_PSC_DYNAMIC) ||
   5893                 (t_data->psc == BCM_TRUNK_PSC_DYNAMIC_ASSIGNED) ||
   5894                 (t_data->psc == BCM_TRUNK_PSC_DYNAMIC_OPTIMAL)) {
   5895                 if (!(t_data->member_flags[i] &
   5896                       BCM_TRUNK_MEMBER_EGRESS_DISABLE) && 
   5897                     !(t_data->member_flags[i] &
   5898                       BCM_TRUNK_MEMBER_UNICAST_EGRESS_DISABLE)) { 
   5899 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT)
   5900                     if (soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) {
   5901                         BCM_IF_ERROR_RETURN(bcm_th2_hgt_lag_dlb_member_attr_get(unit,
   5902                                 port,
   5903                                 &t_data->dynamic_scaling_factor[i],
   5904                                 &t_data->dynamic_load_weight[i],
   5905                                 &t_data->dynamic_queue_size_weight[i]));
   5906                     } else
   5907 #endif /* BCM_TOMAHAWK2_SUPPORT */
   5908 #ifdef BCM_TRIUMPH3_SUPPORT
   5909                     if (soc_feature(unit, soc_feature_lag_dlb)) {
   5910                         BCM_IF_ERROR_RETURN(bcm_tr3_lag_dlb_member_attr_get(unit,
   5911                                 mod, port,
   5912                                 &t_data->dynamic_scaling_factor[i],
   5913                                 &t_data->dynamic_load_weight[i]));
   5914                     }
   5915 #endif /* BCM_TRIUMPH3_SUPPORT */
   5916                 }
   5917             } 
   5918         }
   5919     }
   5920 
   5921     return BCM_E_NONE;
   5922 }
   5923 
   5924 /* ----------------------------------------------------------------------------- 
   5925  *
   5926  * Routines for Higig trunking 
   5927  *
   5928  * ----------------------------------------------------------------------------- 
   5929  */
   5930 
   5931 static soc_field_t port_loading_threshold_fields[] = {
   5932     PORT_LOADING_THRESHOLD_1f,
   5933     PORT_LOADING_THRESHOLD_2f,
   5934     PORT_LOADING_THRESHOLD_3f,
   5935     PORT_LOADING_THRESHOLD_4f,
   5936     PORT_LOADING_THRESHOLD_5f,
   5937     PORT_LOADING_THRESHOLD_6f,
   5938     PORT_LOADING_THRESHOLD_7f  
   5939 };
   5940 
   5941 /*
   5942  * Function:
   5943  *      _bcm_trident_hg_dlb_sample_rate_thresholds_set
   5944  * Purpose:
   5945  *      Set Higig DLB port load sample period and thresholds.
   5946  * Parameters:
   5947  *      unit - (IN) SOC unit number.
   5948  *      sample_rate - (IN) Number of samplings per second.
   5949  *      min_th      - (IN) Minimum port load threshold, in mbps.
   5950  *      max_th      - (IN) Maximum port load threshold, in mbps.
   5951  * Returns:
   5952  *      BCM_E_xxx
   5953  */
   5954 STATIC int
   5955 _bcm_trident_hg_dlb_sample_rate_thresholds_set(int unit, int sample_rate,
   5956         int min_th, int max_th)
   5957 {
   5958     int num_time_units;
   5959     uint32 measure_control_reg;
   5960     int max_th_bytes;
   5961     int th_increment;
   5962     dlb_hgt_glb_quantize_thresholds_entry_t thresholds_entry;
   5963     int i;
   5964     int th_bytes[7];
   5965 
   5966     if (sample_rate <= 0 || min_th < 0 || max_th < 0) {
   5967         return BCM_E_PARAM;
   5968     }
   5969     
   5970     if (min_th > max_th) {
   5971         max_th = min_th;
   5972     }
   5973 
   5974 #ifdef BCM_TRIUMPH3_SUPPORT
   5975     if (SOC_IS_TRIUMPH3(unit) || SOC_IS_TD2_TT2(unit)) {
   5976         /* Compute sampling period in units of 1us:
   5977          *     number of 1us time units = 10^6 / sample_rate
   5978          */ 
   5979         num_time_units = 1000000 / sample_rate;
   5980         if (num_time_units < 1 || num_time_units > 255) {
   5981             /* Hardware limits the sampling period to 1 to 255 time units. */ 
   5982             return BCM_E_PARAM;
   5983         }
   5984     } else
   5985 #endif /* BCM_TRIUMPH3_SUPPORT */
   5986     {
   5987         /* Compute sampling period in units of 256ns:
   5988          *     number of 256ns time units = 10^9 / 256 / sample_rate
   5989          *                                = 3906250 / sample_rate
   5990          */ 
   5991         num_time_units = 3906250 / sample_rate;
   5992         if (num_time_units < 2 || num_time_units > 255) {
   5993             /* Hardware limits the sampling period to 2 to 255 time units. */ 
   5994             return BCM_E_PARAM;
   5995         }
   5996     }
   5997     SOC_IF_ERROR_RETURN
   5998         (READ_DLB_HGT_QUALITY_MEASURE_CONTROLr(unit, &measure_control_reg));
   5999     soc_reg_field_set(unit, DLB_HGT_QUALITY_MEASURE_CONTROLr,
   6000             &measure_control_reg, SAMPLING_PERIODf, num_time_units);
   6001     SOC_IF_ERROR_RETURN
   6002         (WRITE_DLB_HGT_QUALITY_MEASURE_CONTROLr(unit, measure_control_reg));
   6003     HG_DLB_INFO(unit)->hg_dlb_sample_rate = sample_rate;
   6004 
   6005 #ifdef BCM_TRIUMPH3_SUPPORT
   6006     if (SOC_IS_TRIUMPH3(unit) || SOC_IS_TD2_TT2(unit)) {
   6007         dlb_hgt_quantize_threshold_entry_t quantize_threshold_entry;
   6008         soc_mem_t quantize_threshold_m;
   6009 
   6010         /* Compute threshold in bytes per sampling period:
   6011          * bytes per 1us = (million bits per sec) * 10^6 / 8 * 10^(-6),
   6012          * bytes per sampling period = (bytes per 1us) * (number of 1us 
   6013          *                             time units in sampling period)
   6014          *                           = mbps * num_time_units / 8
   6015          */
   6016         max_th_bytes = max_th * num_time_units / 8;
   6017 
   6018         if (max_th_bytes > 0xffffff) {
   6019             /* Hardware limits port load threshold to 24-bits */
   6020             return BCM_E_PARAM;
   6021         }
   6022 
   6023         /* Use min threshold as LOADING_THRESHOLD 0, and max threshold as
   6024          * LOADING_THRESHOLD 6. LOADING_THRESHOLD 1 to 5 will be
   6025          * evenly spread out between min and max thresholds.
   6026          */
   6027         th_increment = (max_th - min_th) / 6;
   6028         quantize_threshold_m = soc_mem_is_valid(unit,
   6029                 DLB_HGT_PLA_QUANTIZE_THRESHOLDm) ?
   6030                 DLB_HGT_PLA_QUANTIZE_THRESHOLDm : DLB_HGT_QUANTIZE_THRESHOLDm;
   6031         for (i = 0; i < 7; i++) {
   6032             SOC_IF_ERROR_RETURN
   6033                 (soc_mem_read(unit, quantize_threshold_m, MEM_BLOCK_ANY, i,
   6034                               &quantize_threshold_entry));
   6035             th_bytes[i] = (min_th + i * th_increment) * num_time_units / 8;
   6036             soc_mem_field32_set(unit, quantize_threshold_m,
   6037                     &quantize_threshold_entry, LOADING_THRESHOLDf, th_bytes[i]);
   6038             SOC_IF_ERROR_RETURN
   6039                 (soc_mem_write(unit, quantize_threshold_m, MEM_BLOCK_ALL, i,
   6040                                &quantize_threshold_entry));
   6041         }
   6042     } else
   6043 #endif /* BCM_TRIUMPH3_SUPPORT */
   6044     {
   6045         /* Compute threshold in bytes per sampling period:
   6046          * bytes per 256ns = (million bits per sec) * 10^6 / 8 * 256 * 10^(-9),
   6047          * bytes per sampling period = (bytes per 256ns) * (number of 256ns
   6048          *                             time units in sampling period)
   6049          *                           = mbps * 256 * num_time_units / 8000
   6050          *
   6051          * Note: The portion of the formula, (mbps * 256 * num_time_units), may
   6052          *       overflow when mbps exceeds 33000 and num_time_units equals to
   6053          *       to its max value of 255. Hence, the formula will be rewritten
   6054          *       as ((mbps * 256) / 8000) * num_time_units.
   6055          */
   6056         max_th_bytes = ((max_th << 8) / 8000) * num_time_units;
   6057 
   6058         if (max_th_bytes > 0xffff) {
   6059             /* Hardware limits port load threshold to 16-bits */
   6060             return BCM_E_PARAM;
   6061         }
   6062 
   6063         /* Use min threshold as PORT_LOADING_THRESHOLD_1, and max threshold as
   6064          * PORT_LOADING_THRESHOLD_7. PORT_LOADING_THRESHOLD 2 to 6 will be
   6065          * evenly spread out between min and max thresholds.
   6066          */
   6067         th_increment = (max_th - min_th) / 6;
   6068         SOC_IF_ERROR_RETURN
   6069             (READ_DLB_HGT_GLB_QUANTIZE_THRESHOLDSm(unit, MEM_BLOCK_ANY, 0,
   6070                                                    &thresholds_entry));
   6071         for (i = 0; i < 7; i++) {
   6072             th_bytes[i] = (((min_th + i * th_increment) << 8) / 8000) *
   6073                 num_time_units;
   6074             soc_DLB_HGT_GLB_QUANTIZE_THRESHOLDSm_field32_set
   6075                 (unit, &thresholds_entry, port_loading_threshold_fields[i],
   6076                  th_bytes[i]);
   6077         }
   6078         SOC_IF_ERROR_RETURN
   6079             (WRITE_DLB_HGT_GLB_QUANTIZE_THRESHOLDSm(unit, MEM_BLOCK_ALL, 0,
   6080                                                     &thresholds_entry));
   6081     }
   6082 
   6083     HG_DLB_INFO(unit)->hg_dlb_tx_load_min_th = min_th;
   6084     HG_DLB_INFO(unit)->hg_dlb_tx_load_max_th = max_th;
   6085 
   6086     return BCM_E_NONE;
   6087 }
   6088 
   6089 /*
   6090  * Function:
   6091  *      _bcm_trident_hg_dlb_sample_rate_set
   6092  * Purpose:
   6093  *      Set Higig dynamic load balancing sample rate.
   6094  * Parameters:
   6095  *      unit - (IN) SOC unit number.
   6096  *      sample_rate - (IN) Number of samplings per second.
   6097  * Returns:
   6098  *      BCM_E_xxx
   6099  */
   6100 STATIC int
   6101 _bcm_trident_hg_dlb_sample_rate_set(int unit, int sample_rate)
   6102 {
   6103     BCM_IF_ERROR_RETURN(_bcm_trident_hg_dlb_sample_rate_thresholds_set(unit,
   6104                 sample_rate, HG_DLB_INFO(unit)->hg_dlb_tx_load_min_th,
   6105                 HG_DLB_INFO(unit)->hg_dlb_tx_load_max_th));
   6106     return BCM_E_NONE;
   6107 }
   6108 
   6109 /*
   6110  * Function:
   6111  *      _bcm_trident_hg_dlb_tx_load_min_th_set
   6112  * Purpose:
   6113  *      Set Higig DLB port load minimum threshold.
   6114  * Parameters:
   6115  *      unit - (IN) SOC unit number.
   6116  *      min_th - (IN) Minimum port loading threshold.
   6117  * Returns:
   6118  *      BCM_E_xxx
   6119  */
   6120 STATIC int
   6121 _bcm_trident_hg_dlb_tx_load_min_th_set(int unit, int min_th)
   6122 {
   6123     BCM_IF_ERROR_RETURN(_bcm_trident_hg_dlb_sample_rate_thresholds_set(unit,
   6124                 HG_DLB_INFO(unit)->hg_dlb_sample_rate, min_th,
   6125                 HG_DLB_INFO(unit)->hg_dlb_tx_load_max_th));
   6126     return BCM_E_NONE;
   6127 }
   6128 
   6129 /*
   6130  * Function:
   6131  *      _bcm_trident_hg_dlb_tx_load_max_th_set
   6132  * Purpose:
   6133  *      Set Higig DLB port load maximum threshold.
   6134  * Parameters:
   6135  *      unit - (IN) SOC unit number.
   6136  *      max_th - (IN) Maximum port loading threshold.
   6137  * Returns:
   6138  *      BCM_E_xxx
   6139  */
   6140 STATIC int
   6141 _bcm_trident_hg_dlb_tx_load_max_th_set(int unit, int max_th)
   6142 {
   6143     BCM_IF_ERROR_RETURN(_bcm_trident_hg_dlb_sample_rate_thresholds_set(unit,
   6144                 HG_DLB_INFO(unit)->hg_dlb_sample_rate,
   6145                 HG_DLB_INFO(unit)->hg_dlb_tx_load_min_th,
   6146                 max_th));
   6147     return BCM_E_NONE;
   6148 }
   6149 
   6150 static soc_field_t port_qsize_threshold_fields[] = {
   6151     PORT_QSIZE_THRESHOLD_1f,
   6152     PORT_QSIZE_THRESHOLD_2f,
   6153     PORT_QSIZE_THRESHOLD_3f,
   6154     PORT_QSIZE_THRESHOLD_4f,
   6155     PORT_QSIZE_THRESHOLD_5f,
   6156     PORT_QSIZE_THRESHOLD_6f,
   6157     PORT_QSIZE_THRESHOLD_7f 
   6158 };
   6159 
   6160 /*
   6161  * Function:
   6162  *      _bcm_trident_hg_dlb_qsize_thresholds_set
   6163  * Purpose:
   6164  *      Set Higig DLB queue size thresholds.
   6165  * Parameters:
   6166  *      unit - (IN) SOC unit number.
   6167  *      min_th - (IN) Minimum queue size threshold, in bytes.
   6168  *      max_th - (IN) Maximum queue size threshold, in bytes.
   6169  * Returns:
   6170  *      BCM_E_xxx
   6171  */
   6172 STATIC int
   6173 _bcm_trident_hg_dlb_qsize_thresholds_set(int unit, int min_th, int max_th)
   6174 {
   6175     int max_th_cells;
   6176     int th_increment;
   6177     dlb_hgt_glb_quantize_thresholds_entry_t thresholds_entry;
   6178     int i;
   6179     int th_cells[7];
   6180 
   6181     if (min_th < 0 || max_th < 0) {
   6182         return BCM_E_PARAM;
   6183     }
   6184 
   6185     if (min_th > max_th) {
   6186         max_th = min_th;
   6187     }
   6188 
   6189     /* Convert threshold to number of cells */
   6190     max_th_cells = max_th / 208;
   6191 
   6192     if (max_th_cells > 0xffff) {
   6193         /* Hardware limits queue size threshold to 16-bits */
   6194         return BCM_E_PARAM;
   6195     }
   6196 
   6197 #ifdef BCM_TRIUMPH3_SUPPORT
   6198     if (SOC_IS_TRIUMPH3(unit) || SOC_IS_TD2_TT2(unit)) {
   6199         dlb_hgt_quantize_threshold_entry_t quantize_threshold_entry;
   6200         soc_mem_t quantize_threshold_m;
   6201 
   6202         /* Use min threshold as QSIZE_THRESHOLD 0, and max threshold as
   6203          * QSIZE_THRESHOLD 6. QSIZE_THRESHOLD 1 to 5 will be
   6204          * evenly spread out between min and max thresholds.
   6205          */
   6206         th_increment = (max_th - min_th) / 6;
   6207         quantize_threshold_m = soc_mem_is_valid(unit,
   6208                 DLB_HGT_PLA_QUANTIZE_THRESHOLDm) ?
   6209                 DLB_HGT_PLA_QUANTIZE_THRESHOLDm : DLB_HGT_QUANTIZE_THRESHOLDm;
   6210         for (i = 0; i < 7; i++) {
   6211             SOC_IF_ERROR_RETURN
   6212                 (soc_mem_read(unit, quantize_threshold_m, MEM_BLOCK_ANY, i,
   6213                               &quantize_threshold_entry));
   6214             th_cells[i] = (min_th + i * th_increment) / 208;
   6215             soc_mem_field32_set(unit, quantize_threshold_m,
   6216                     &quantize_threshold_entry, QSIZE_THRESHOLDf, th_cells[i]);
   6217             SOC_IF_ERROR_RETURN
   6218                 (soc_mem_write(unit, quantize_threshold_m, MEM_BLOCK_ALL, i,
   6219                                &quantize_threshold_entry));
   6220         }
   6221     } else 
   6222 #endif /* BCM_TRIUMPH3_SUPPORT */
   6223     {
   6224         /* Use min threshold as PORT_QSIZE_THRESHOLD_1, and max threshold as
   6225          * PORT_QSIZE_THRESHOLD_7. PORT_QSIZE_THRESHOLD 2 to 6 will be
   6226          * evenly spread out between min and max thresholds.
   6227          */
   6228         th_increment = (max_th - min_th) / 6;
   6229         SOC_IF_ERROR_RETURN
   6230             (READ_DLB_HGT_GLB_QUANTIZE_THRESHOLDSm(unit, MEM_BLOCK_ANY, 0,
   6231                                                    &thresholds_entry));
   6232         for (i = 0; i < 7; i++) {
   6233             th_cells[i] = (min_th + i * th_increment) >> 7;
   6234             soc_DLB_HGT_GLB_QUANTIZE_THRESHOLDSm_field32_set
   6235                 (unit, &thresholds_entry, port_qsize_threshold_fields[i],
   6236                  th_cells[i]);
   6237         }
   6238         SOC_IF_ERROR_RETURN
   6239             (WRITE_DLB_HGT_GLB_QUANTIZE_THRESHOLDSm(unit, MEM_BLOCK_ALL, 0,
   6240                                                     &thresholds_entry));
   6241     }
   6242     HG_DLB_INFO(unit)->hg_dlb_qsize_min_th = min_th;
   6243     HG_DLB_INFO(unit)->hg_dlb_qsize_max_th = max_th;
   6244 
   6245     return BCM_E_NONE;
   6246 }
   6247 
   6248 /*
   6249  * Function:
   6250  *      _bcm_trident_hg_dlb_qsize_min_th_set
   6251  * Purpose:
   6252  *      Set Higig DLB queue size minimum threshold.
   6253  * Parameters:
   6254  *      unit - (IN) SOC unit number.
   6255  *      min_th - (IN) Minimum queue size threshold, in bytes.
   6256  * Returns:
   6257  *      BCM_E_xxx
   6258  */
   6259 STATIC int
   6260 _bcm_trident_hg_dlb_qsize_min_th_set(int unit, int min_th)
   6261 {
   6262     BCM_IF_ERROR_RETURN(_bcm_trident_hg_dlb_qsize_thresholds_set(unit,
   6263                 min_th, HG_DLB_INFO(unit)->hg_dlb_qsize_max_th));
   6264 
   6265     return BCM_E_NONE;
   6266 }
   6267 
   6268 /*
   6269  * Function:
   6270  *      _bcm_trident_hg_dlb_qsize_max_th_set
   6271  * Purpose:
   6272  *      Set Higig DLB queue size maximum threshold.
   6273  * Parameters:
   6274  *      unit - (IN) SOC unit number.
   6275  *      max_th - (IN) Maximum queue size threshold, in bytes.
   6276  * Returns:
   6277  *      BCM_E_xxx
   6278  */
   6279 STATIC int
   6280 _bcm_trident_hg_dlb_qsize_max_th_set(int unit, int max_th)
   6281 {
   6282     BCM_IF_ERROR_RETURN(_bcm_trident_hg_dlb_qsize_thresholds_set(unit,
   6283                 HG_DLB_INFO(unit)->hg_dlb_qsize_min_th, max_th));
   6284 
   6285     return BCM_E_NONE;
   6286 }
   6287 
   6288 /*
   6289  * Function:
   6290  *      _bcm_trident_hg_dlb_tx_load_weight_set
   6291  * Purpose:
   6292  *      Set Higig DLB port load weight.
   6293  * Parameters:
   6294  *      unit - (IN) SOC unit number.
   6295  *      weight - (IN) Port load weight.
   6296  * Returns:
   6297  *      BCM_E_xxx
   6298  */
   6299 STATIC int
   6300 _bcm_trident_hg_dlb_tx_load_weight_set(int unit, int weight)
   6301 {
   6302     uint32 measure_control_reg;
   6303     soc_field_t load_weight_f;
   6304 
   6305     if (weight < 0 || 
   6306         weight > 0xf) {
   6307         /* Hardware limits port load weight to 4 bits */
   6308         return BCM_E_PARAM;
   6309     }
   6310 
   6311     SOC_IF_ERROR_RETURN
   6312         (READ_DLB_HGT_QUALITY_MEASURE_CONTROLr(unit, &measure_control_reg));
   6313     if (SOC_REG_FIELD_VALID(unit, DLB_HGT_QUALITY_MEASURE_CONTROLr,
   6314                 PORT_LOADING_WEIGHTf)) {
   6315         load_weight_f = PORT_LOADING_WEIGHTf;
   6316     } else {
   6317         load_weight_f = WEIGHT_LOADINGf;
   6318     }
   6319     soc_reg_field_set(unit, DLB_HGT_QUALITY_MEASURE_CONTROLr,
   6320         &measure_control_reg, load_weight_f, weight);
   6321     SOC_IF_ERROR_RETURN
   6322         (WRITE_DLB_HGT_QUALITY_MEASURE_CONTROLr(unit, measure_control_reg));
   6323     return BCM_E_NONE;
   6324 }
   6325 
   6326 /*
   6327  * Function:
   6328  *      _bcm_trident_hg_dlb_tx_load_weight_get
   6329  * Purpose:
   6330  *      Get Higig DLB port load weight.
   6331  * Parameters:
   6332  *      unit - (IN) SOC unit number.
   6333  *      weight - (OUT) Port load weight.
   6334  * Returns:
   6335  *      BCM_E_xxx
   6336  */
   6337 STATIC int
   6338 _bcm_trident_hg_dlb_tx_load_weight_get(int unit, int *weight)
   6339 {
   6340     uint32 measure_control_reg;
   6341     soc_field_t load_weight_f;
   6342 
   6343     SOC_IF_ERROR_RETURN
   6344         (READ_DLB_HGT_QUALITY_MEASURE_CONTROLr(unit, &measure_control_reg));
   6345     if (SOC_REG_FIELD_VALID(unit, DLB_HGT_QUALITY_MEASURE_CONTROLr,
   6346                 PORT_LOADING_WEIGHTf)) {
   6347         load_weight_f = PORT_LOADING_WEIGHTf;
   6348     } else {
   6349         load_weight_f = WEIGHT_LOADINGf;
   6350     }
   6351     *weight = soc_reg_field_get(unit, DLB_HGT_QUALITY_MEASURE_CONTROLr,
   6352         measure_control_reg, load_weight_f);
   6353 
   6354     return BCM_E_NONE;
   6355 }
   6356 
   6357 /*
   6358  * Function:
   6359  *      _bcm_trident_hg_dlb_qsize_weight_set
   6360  * Purpose:
   6361  *      Set Higig DLB queue size weight.
   6362  * Parameters:
   6363  *      unit - (IN) SOC unit number.
   6364  *      weight - (IN) Queue size weight.
   6365  * Returns:
   6366  *      BCM_E_xxx
   6367  */
   6368 STATIC int
   6369 _bcm_trident_hg_dlb_qsize_weight_set(int unit, int weight)
   6370 {
   6371     uint32 measure_control_reg;
   6372     soc_field_t qsize_weight_f;
   6373 
   6374     if (weight < 0 || 
   6375         weight > 0xf) {
   6376         /* Hardware limits queue size weight to 4 bits */
   6377         return BCM_E_PARAM;
   6378     }
   6379 
   6380     SOC_IF_ERROR_RETURN
   6381         (READ_DLB_HGT_QUALITY_MEASURE_CONTROLr(unit, &measure_control_reg));
   6382     if (SOC_REG_FIELD_VALID(unit, DLB_HGT_QUALITY_MEASURE_CONTROLr,
   6383                 PORT_QSIZE_WEIGHTf)) {
   6384         qsize_weight_f = PORT_QSIZE_WEIGHTf;
   6385     } else {
   6386         qsize_weight_f = WEIGHT_QSIZEf;
   6387     }
   6388     soc_reg_field_set(unit, DLB_HGT_QUALITY_MEASURE_CONTROLr,
   6389         &measure_control_reg, qsize_weight_f, weight);
   6390     SOC_IF_ERROR_RETURN
   6391         (WRITE_DLB_HGT_QUALITY_MEASURE_CONTROLr(unit, measure_control_reg));
   6392     return BCM_E_NONE;
   6393 }
   6394 
   6395 /*
   6396  * Function:
   6397  *      _bcm_trident_hg_dlb_qsize_weight_get
   6398  * Purpose:
   6399  *      Get Higig DLB queue size weight.
   6400  * Parameters:
   6401  *      unit - (IN) SOC unit number.
   6402  *      weight - (OUT) Queue size weight.
   6403  * Returns:
   6404  *      BCM_E_xxx
   6405  */
   6406 STATIC int
   6407 _bcm_trident_hg_dlb_qsize_weight_get(int unit, int *weight)
   6408 {
   6409     uint32 measure_control_reg;
   6410     soc_field_t qsize_weight_f;
   6411 
   6412     SOC_IF_ERROR_RETURN
   6413         (READ_DLB_HGT_QUALITY_MEASURE_CONTROLr(unit, &measure_control_reg));
   6414     if (SOC_REG_FIELD_VALID(unit, DLB_HGT_QUALITY_MEASURE_CONTROLr,
   6415                 PORT_QSIZE_WEIGHTf)) {
   6416         qsize_weight_f = PORT_QSIZE_WEIGHTf;
   6417     } else {
   6418         qsize_weight_f = WEIGHT_QSIZEf;
   6419     }
   6420     *weight = soc_reg_field_get(unit, DLB_HGT_QUALITY_MEASURE_CONTROLr,
   6421         measure_control_reg, qsize_weight_f);
   6422 
   6423     return BCM_E_NONE;
   6424 }
   6425 
   6426 /*
   6427  * Function:
   6428  *      _bcm_trident_hg_dlb_tx_load_cap_set
   6429  * Purpose:
   6430  *      Set Higig DLB port load cap control.
   6431  * Parameters:
   6432  *      unit - (IN) SOC unit number.
   6433  *      cap - (IN) Port load cap control.
   6434  * Returns:
   6435  *      BCM_E_xxx
   6436  */
   6437 STATIC int
   6438 _bcm_trident_hg_dlb_tx_load_cap_set(int unit, int cap)
   6439 {
   6440     uint32 measure_control_reg;
   6441     soc_field_t cap_load_f;
   6442 
   6443     if (cap < 0 || 
   6444         cap > 1) {
   6445         /* Hardware limits port load cap control to 1 bit */
   6446         return BCM_E_PARAM;
   6447     }
   6448 
   6449     SOC_IF_ERROR_RETURN
   6450         (READ_DLB_HGT_QUALITY_MEASURE_CONTROLr(unit, &measure_control_reg));
   6451     if (SOC_REG_FIELD_VALID(unit, DLB_HGT_QUALITY_MEASURE_CONTROLr,
   6452                 CAP_LOADING_AVERAGEf)) {
   6453         cap_load_f = CAP_LOADING_AVERAGEf; 
   6454     } else {
   6455         cap_load_f = CAP_LOADING_AVGf;
   6456     }
   6457     soc_reg_field_set(unit, DLB_HGT_QUALITY_MEASURE_CONTROLr,
   6458         &measure_control_reg, cap_load_f, cap);
   6459     SOC_IF_ERROR_RETURN
   6460         (WRITE_DLB_HGT_QUALITY_MEASURE_CONTROLr(unit, measure_control_reg));
   6461     return BCM_E_NONE;
   6462 }
   6463 
   6464 /*
   6465  * Function:
   6466  *      _bcm_trident_hg_dlb_tx_load_cap_get
   6467  * Purpose:
   6468  *      Get Higig DLB port load cap control.
   6469  * Parameters:
   6470  *      unit - (IN) SOC unit number.
   6471  *      cap - (OUT) Cap control.
   6472  * Returns:
   6473  *      BCM_E_xxx
   6474  */
   6475 STATIC int
   6476 _bcm_trident_hg_dlb_tx_load_cap_get(int unit, int *cap)
   6477 {
   6478     uint32 measure_control_reg;
   6479     soc_field_t cap_load_f;
   6480 
   6481     SOC_IF_ERROR_RETURN
   6482         (READ_DLB_HGT_QUALITY_MEASURE_CONTROLr(unit, &measure_control_reg));
   6483     if (SOC_REG_FIELD_VALID(unit, DLB_HGT_QUALITY_MEASURE_CONTROLr,
   6484                 CAP_LOADING_AVERAGEf)) {
   6485         cap_load_f = CAP_LOADING_AVERAGEf; 
   6486     } else {
   6487         cap_load_f = CAP_LOADING_AVGf;
   6488     }
   6489     *cap= soc_reg_field_get(unit, DLB_HGT_QUALITY_MEASURE_CONTROLr,
   6490         measure_control_reg, cap_load_f);
   6491 
   6492     return BCM_E_NONE;
   6493 }
   6494 
   6495 /*
   6496  * Function:
   6497  *      _bcm_trident_hg_dlb_qsize_cap_set
   6498  * Purpose:
   6499  *      Set Higig DLB queue size cap control.
   6500  * Parameters:
   6501  *      unit - (IN) SOC unit number.
   6502  *      cap - (IN) Queue size cap control.
   6503  * Returns:
   6504  *      BCM_E_xxx
   6505  */
   6506 STATIC int
   6507 _bcm_trident_hg_dlb_qsize_cap_set(int unit, int cap)
   6508 {
   6509     uint32 measure_control_reg;
   6510     soc_field_t cap_qsize_f;
   6511 
   6512     if (cap < 0 || 
   6513         cap > 1) {
   6514         /* Hardware limits queue size cap control to 1 bit */
   6515         return BCM_E_PARAM;
   6516     }
   6517 
   6518     SOC_IF_ERROR_RETURN
   6519         (READ_DLB_HGT_QUALITY_MEASURE_CONTROLr(unit, &measure_control_reg));
   6520     if (SOC_REG_FIELD_VALID(unit, DLB_HGT_QUALITY_MEASURE_CONTROLr,
   6521                 CAP_QSIZE_AVERAGEf)) {
   6522         cap_qsize_f = CAP_QSIZE_AVERAGEf; 
   6523     } else {
   6524         cap_qsize_f = CAP_QSIZE_AVGf; 
   6525     }
   6526     soc_reg_field_set(unit, DLB_HGT_QUALITY_MEASURE_CONTROLr,
   6527         &measure_control_reg, cap_qsize_f, cap);
   6528     SOC_IF_ERROR_RETURN
   6529         (WRITE_DLB_HGT_QUALITY_MEASURE_CONTROLr(unit, measure_control_reg));
   6530 
   6531     return BCM_E_NONE;
   6532 }
   6533 
   6534 /*
   6535  * Function:
   6536  *      _bcm_trident_hg_dlb_qsize_cap_get
   6537  * Purpose:
   6538  *      Get Higig DLB queue size cap control.
   6539  * Parameters:
   6540  *      unit - (IN) SOC unit number.
   6541  *      cap - (OUT) Cap control.
   6542  * Returns:
   6543  *      BCM_E_xxx
   6544  */
   6545 STATIC int
   6546 _bcm_trident_hg_dlb_qsize_cap_get(int unit, int *cap)
   6547 {
   6548     uint32 measure_control_reg;
   6549     soc_field_t cap_qsize_f;
   6550 
   6551     SOC_IF_ERROR_RETURN
   6552         (READ_DLB_HGT_QUALITY_MEASURE_CONTROLr(unit, &measure_control_reg));
   6553     if (SOC_REG_FIELD_VALID(unit, DLB_HGT_QUALITY_MEASURE_CONTROLr,
   6554                 CAP_QSIZE_AVERAGEf)) {
   6555         cap_qsize_f = CAP_QSIZE_AVERAGEf; 
   6556     } else {
   6557         cap_qsize_f = CAP_QSIZE_AVGf; 
   6558     }
   6559     *cap= soc_reg_field_get(unit, DLB_HGT_QUALITY_MEASURE_CONTROLr,
   6560         measure_control_reg, cap_qsize_f);
   6561 
   6562     return BCM_E_NONE;
   6563 }
   6564 
   6565 /*
   6566  * Function:
   6567  *      _bcm_trident_hg_dlb_config_set
   6568  * Purpose:
   6569  *      Set per-chip Higig dynamic load balancing configuration parameters.
   6570  * Parameters:
   6571  *      unit - (IN) SOC unit number.
   6572  *      type - (IN) Configuration parameter type.
   6573  *      arg  - (IN) Configuration paramter value.
   6574  * Returns:
   6575  *      BCM_E_xxx
   6576  */
   6577 int
   6578 _bcm_trident_hg_dlb_config_set(int unit, bcm_switch_control_t type, int arg)
   6579 {
   6580     switch (type) {
   6581         case bcmSwitchFabricTrunkDynamicSampleRate:
   6582             return _bcm_trident_hg_dlb_sample_rate_set(unit, arg);
   6583 
   6584         case bcmSwitchFabricTrunkDynamicEgressBytesExponent:
   6585             return _bcm_trident_hg_dlb_tx_load_weight_set(unit, arg);
   6586 
   6587         case bcmSwitchFabricTrunkDynamicQueuedBytesExponent:
   6588             return _bcm_trident_hg_dlb_qsize_weight_set(unit, arg);
   6589 
   6590         case bcmSwitchFabricTrunkDynamicEgressBytesDecreaseReset:
   6591             return _bcm_trident_hg_dlb_tx_load_cap_set(unit, arg);
   6592 
   6593         case bcmSwitchFabricTrunkDynamicQueuedBytesDecreaseReset:
   6594             return _bcm_trident_hg_dlb_qsize_cap_set(unit, arg);
   6595 
   6596         case bcmSwitchFabricTrunkDynamicEgressBytesMinThreshold:
   6597             return _bcm_trident_hg_dlb_tx_load_min_th_set(unit, arg);
   6598 
   6599         case bcmSwitchFabricTrunkDynamicEgressBytesMaxThreshold:
   6600             return _bcm_trident_hg_dlb_tx_load_max_th_set(unit, arg);
   6601 
   6602         case bcmSwitchFabricTrunkDynamicQueuedBytesMinThreshold:
   6603             return _bcm_trident_hg_dlb_qsize_min_th_set(unit, arg);
   6604 
   6605         case bcmSwitchFabricTrunkDynamicQueuedBytesMaxThreshold:
   6606             return _bcm_trident_hg_dlb_qsize_max_th_set(unit, arg);
   6607 
   6608         default:
   6609             return BCM_E_PARAM;
   6610     }
   6611 }
   6612 
   6613 /*
   6614  * Function:
   6615  *      _bcm_trident_hg_dlb_config_get
   6616  * Purpose:
   6617  *      Get per-chip Higig dynamic load balancing configuration parameters.
   6618  * Parameters:
   6619  *      unit - (IN) SOC unit number.
   6620  *      type - (IN) Configuration parameter type.
   6621  *      arg  - (OUT) Configuration paramter value.
   6622  * Returns:
   6623  *      BCM_E_xxx
   6624  */
   6625 int
   6626 _bcm_trident_hg_dlb_config_get(int unit, bcm_switch_control_t type, int *arg)
   6627 {
   6628     switch (type) {
   6629         case bcmSwitchFabricTrunkDynamicSampleRate:
   6630             *arg = HG_DLB_INFO(unit)->hg_dlb_sample_rate;
   6631             break;
   6632 
   6633         case bcmSwitchFabricTrunkDynamicEgressBytesExponent:
   6634             return _bcm_trident_hg_dlb_tx_load_weight_get(unit, arg);
   6635 
   6636         case bcmSwitchFabricTrunkDynamicQueuedBytesExponent:
   6637             return _bcm_trident_hg_dlb_qsize_weight_get(unit, arg);
   6638 
   6639         case bcmSwitchFabricTrunkDynamicEgressBytesDecreaseReset:
   6640             return _bcm_trident_hg_dlb_tx_load_cap_get(unit, arg);
   6641 
   6642         case bcmSwitchFabricTrunkDynamicQueuedBytesDecreaseReset:
   6643             return _bcm_trident_hg_dlb_qsize_cap_get(unit, arg);
   6644 
   6645         case bcmSwitchFabricTrunkDynamicEgressBytesMinThreshold:
   6646             *arg = HG_DLB_INFO(unit)->hg_dlb_tx_load_min_th;
   6647             break;
   6648 
   6649         case bcmSwitchFabricTrunkDynamicEgressBytesMaxThreshold:
   6650             *arg = HG_DLB_INFO(unit)->hg_dlb_tx_load_max_th;
   6651             break;
   6652 
   6653         case bcmSwitchFabricTrunkDynamicQueuedBytesMinThreshold:
   6654             *arg = HG_DLB_INFO(unit)->hg_dlb_qsize_min_th;
   6655             break;
   6656 
   6657         case bcmSwitchFabricTrunkDynamicQueuedBytesMaxThreshold:
   6658             *arg = HG_DLB_INFO(unit)->hg_dlb_qsize_max_th;
   6659             break;
   6660 
   6661         default:
   6662             return BCM_E_PARAM;
   6663     }
   6664 
   6665     return BCM_E_NONE;
   6666 }
   6667 
   6668 /*
   6669  * Function:
   6670  *      _bcm_trident_hg_dlb_quality_assign
   6671  * Purpose:
   6672  *      Assign quality based on port loading and queue size.
   6673  * Parameters:
   6674  *      unit - (IN)SOC unit number. 
   6675  *      tx_load_percent - (IN) Percent weight of port loading in determing
   6676  *                             port quality. The remaining percentage is
   6677  *                             the weight of queue size.
   6678  *      entry_arr - (IN) Array of 64 quality map table entries.
   6679  * Returns:
   6680  *      BCM_X_XXX
   6681  */
   6682 STATIC int 
   6683 _bcm_trident_hg_dlb_quality_assign(int unit, int tx_load_percent,
   6684         uint32 *entry_arr)
   6685 {
   6686     int quantized_tx_load;
   6687     int quantized_qsize;
   6688     int quality;
   6689     int entry_index;
   6690 
   6691     if (entry_arr == NULL) {
   6692         return BCM_E_PARAM;
   6693     }
   6694 
   6695     for (quantized_tx_load = 0; quantized_tx_load < 8; quantized_tx_load++) {
   6696         for (quantized_qsize = 0; quantized_qsize < 8; quantized_qsize++) {
   6697             quality = (quantized_tx_load * tx_load_percent +
   6698                     quantized_qsize * (100 - tx_load_percent)) / 100;
   6699             entry_index = (quantized_tx_load << 3) + quantized_qsize;
   6700             if (soc_mem_is_valid(unit, DLB_HGT_PORT_QUALITY_MAPPINGm)) {
   6701                 soc_DLB_HGT_PORT_QUALITY_MAPPINGm_field32_set(unit,
   6702                         &entry_arr[entry_index], ASSIGNED_QUALITYf, quality);
   6703             } else if (soc_mem_field_valid(unit, DLB_HGT_QUALITY_MAPPINGm,
   6704                         ASSIGNED_QUALITYf)) {
   6705                 soc_DLB_HGT_QUALITY_MAPPINGm_field32_set(unit,
   6706                         &entry_arr[entry_index], ASSIGNED_QUALITYf, quality);
   6707             } else {
   6708                 soc_DLB_HGT_QUALITY_MAPPINGm_field32_set(unit,
   6709                         &entry_arr[entry_index], QUALITYf, quality);
   6710             }
   6711         }
   6712     }
   6713 
   6714     return BCM_E_NONE;
   6715 }
   6716 
   6717 #ifdef BCM_TRIUMPH3_SUPPORT
   6718 /*
   6719  * Function:
   6720  *      _bcm_tr3_hg_dlb_member_quality_map_set
   6721  * Purpose:
   6722  *      Set per-member Higig DLB quality mapping table.
   6723  * Parameters:
   6724  *      unit - (IN) SOC unit number.
   6725  *      member_id - (IN) Member ID.
   6726  *      tx_load_percent - (IN) Percent weight of port loading in determing
   6727  *                             port quality. The remaining percentage is
   6728  *                             the weight of queue size.
   6729  * Returns:
   6730  *      BCM_E_xxx
   6731  */
   6732 STATIC int
   6733 _bcm_tr3_hg_dlb_member_quality_map_set(int unit, int member_id,
   6734         int tx_load_percent)
   6735 {
   6736     soc_profile_mem_t *profile;
   6737     soc_mem_t mem;
   6738     int entry_bytes;
   6739     int entries_per_profile;
   6740     int alloc_size;
   6741     uint32 *entry_arr;
   6742     int rv = BCM_E_NONE;
   6743     void *entries;
   6744     uint32 base_index;
   6745     uint32 old_base_index = 0;
   6746     dlb_hgt_quality_control_entry_t quality_control_entry;
   6747     soc_field_t profile_ptr_f;
   6748 
   6749     profile = _trident_hg_dlb_bk[unit]->hg_dlb_quality_map_profile;
   6750 
   6751     entries_per_profile = 64;
   6752     entry_bytes = sizeof(dlb_hgt_quality_mapping_entry_t);
   6753     alloc_size = entries_per_profile * entry_bytes;
   6754     entry_arr = sal_alloc(alloc_size, "HG DLB Quality Map entries");
   6755     if (entry_arr == NULL) {
   6756         return BCM_E_MEMORY;
   6757     }
   6758     sal_memset(entry_arr, 0, alloc_size);
   6759 
   6760     /* Assign quality in the entry array */
   6761     rv = _bcm_trident_hg_dlb_quality_assign(unit, tx_load_percent, entry_arr);
   6762     if (BCM_FAILURE(rv)) {
   6763         sal_free(entry_arr);
   6764         return rv;
   6765     }
   6766 
   6767     mem = DLB_HGT_QUALITY_MAPPINGm;
   6768     soc_mem_lock(unit, mem);
   6769 
   6770     /* Add profile */
   6771     entries = entry_arr;
   6772     rv = soc_profile_mem_add(unit, profile, &entries, entries_per_profile,
   6773             &base_index);
   6774     sal_free(entry_arr);
   6775     if (SOC_FAILURE(rv)) {
   6776         soc_mem_unlock(unit, mem);
   6777         return rv;
   6778     }
   6779 
   6780     /* Update member profile pointer */
   6781     rv = READ_DLB_HGT_QUALITY_CONTROLm(unit, MEM_BLOCK_ANY, member_id,
   6782             &quality_control_entry);
   6783     if (SOC_FAILURE(rv)) {
   6784         soc_mem_unlock(unit, mem);
   6785         return rv;
   6786     }
   6787     profile_ptr_f = soc_mem_field_valid(unit, DLB_HGT_QUALITY_CONTROLm,
   6788             PROFILE_PTRf) ? PROFILE_PTRf : QMT_PROFILE_PTRf;
   6789     old_base_index = entries_per_profile * soc_mem_field32_get(unit,
   6790             DLB_HGT_QUALITY_CONTROLm, &quality_control_entry, profile_ptr_f);
   6791     soc_DLB_HGT_QUALITY_CONTROLm_field32_set(unit, &quality_control_entry, 
   6792             profile_ptr_f, base_index / entries_per_profile);
   6793     rv = WRITE_DLB_HGT_QUALITY_CONTROLm(unit, MEM_BLOCK_ALL, member_id,
   6794             &quality_control_entry);
   6795     if (SOC_FAILURE(rv)) {
   6796         soc_mem_unlock(unit, mem);
   6797         return rv;
   6798     }
   6799 
   6800     /* Delete old profile */
   6801     rv = soc_profile_mem_delete(unit, profile, old_base_index);
   6802     soc_mem_unlock(unit, mem);
   6803 
   6804     HG_DLB_INFO(unit)->hg_dlb_load_weight[base_index/entries_per_profile] =
   6805         tx_load_percent;
   6806 
   6807     return rv;
   6808 }
   6809 #endif /* BCM_TRIUMPH3_SUPPORT */
   6810 
   6811 /*
   6812  * Function:
   6813  *      _bcm_trident_hg_dlb_quality_map_set
   6814  * Purpose:
   6815  *      Set per-port Higig DLB quality mapping table.
   6816  * Parameters:
   6817  *      unit - (IN) SOC unit number.
   6818  *      port - (IN) Port number.
   6819  *      tx_load_percent - (IN) Percent weight of port loading in determing
   6820  *                             port quality. The remaining percentage is
   6821  *                             the weight of queue size.
   6822  * Returns:
   6823  *      BCM_E_xxx
   6824  */
   6825 STATIC int
   6826 _bcm_trident_hg_dlb_quality_map_set(int unit, bcm_port_t port,
   6827         int tx_load_percent)
   6828 {
   6829     soc_profile_mem_t *profile;
   6830     int entries_per_profile;
   6831     int alloc_size;
   6832     uint32 *entry_arr;
   6833     int rv;
   6834     void *entries;
   6835     uint32 base_index;
   6836     uint32 old_base_index;
   6837     uint32 quantize_control_reg;
   6838     soc_mem_t mem;
   6839 
   6840     profile = _trident_hg_dlb_bk[unit]->hg_dlb_quality_map_profile;
   6841 
   6842     entries_per_profile = 64;
   6843     alloc_size = entries_per_profile *
   6844         sizeof(dlb_hgt_port_quality_mapping_entry_t);
   6845     entry_arr = sal_alloc(alloc_size, "HG DLB Quality Map entries");
   6846     if (entry_arr == NULL) {
   6847         return BCM_E_MEMORY;
   6848     }
   6849     sal_memset(entry_arr, 0, alloc_size);
   6850 
   6851     /* Assign quality in the entry array */
   6852     rv = _bcm_trident_hg_dlb_quality_assign(unit, tx_load_percent, entry_arr);
   6853     if (BCM_FAILURE(rv)) {
   6854         sal_free(entry_arr);
   6855         return rv;
   6856     }
   6857 
   6858     mem = DLB_HGT_PORT_QUALITY_MAPPINGm;
   6859     soc_mem_lock(unit, mem);
   6860     entries = entry_arr;
   6861     rv = soc_profile_mem_add(unit, profile, &entries, entries_per_profile,
   6862             &base_index);
   6863     sal_free(entry_arr);
   6864     if (SOC_FAILURE(rv)) {
   6865         soc_mem_unlock(unit, mem);
   6866         return rv;
   6867     }
   6868 
   6869     rv = READ_DLB_HGT_QUANTIZE_CONTROLr(unit, port, &quantize_control_reg);
   6870     if (SOC_FAILURE(rv)) {
   6871         soc_mem_unlock(unit, mem);
   6872         return rv;
   6873     }
   6874     old_base_index = entries_per_profile * soc_reg_field_get(unit,
   6875             DLB_HGT_QUANTIZE_CONTROLr, quantize_control_reg,
   6876             PORT_QUALITY_MAPPING_PROFILE_PTRf);
   6877     soc_reg_field_set(unit, DLB_HGT_QUANTIZE_CONTROLr,
   6878             &quantize_control_reg, PORT_QUALITY_MAPPING_PROFILE_PTRf,
   6879             base_index / entries_per_profile);
   6880     rv = WRITE_DLB_HGT_QUANTIZE_CONTROLr(unit, port, quantize_control_reg);
   6881     if (SOC_FAILURE(rv)) {
   6882         soc_mem_unlock(unit, mem);
   6883         return rv;
   6884     }
   6885 
   6886     rv = soc_profile_mem_delete(unit, profile, old_base_index);
   6887 
   6888     soc_mem_unlock(unit, mem);
   6889 
   6890     HG_DLB_INFO(unit)->hg_dlb_load_weight[base_index/entries_per_profile] =
   6891         tx_load_percent;
   6892 
   6893     return rv;
   6894 }
   6895 
   6896 /*
   6897  * Function:
   6898  *      _bcm_trident_hg_dlb_id_alloc
   6899  * Purpose:
   6900  *      Get a free Higig DLB ID and mark it used.
   6901  * Parameters:
   6902  *      unit - (IN) SOC unit number.
   6903  *      hgtid - (IN) Higig trunk ID.
   6904  *      dlb_id - (OUT) Allocated DLB ID.
   6905  * Returns:
   6906  *      BCM_E_xxx
   6907  */
   6908 STATIC int
   6909 _bcm_trident_hg_dlb_id_alloc(int unit, int hgtid, int *dlb_id)
   6910 {
   6911     int i;
   6912 
   6913 #ifdef BCM_TRIDENT2_SUPPORT
   6914     if (soc_feature(unit, soc_feature_hg_dlb_id_equal_hg_tid)) {
   6915         if (_BCM_HG_DLB_ID_USED_GET(unit, hgtid)) {
   6916             return BCM_E_EXISTS;
   6917         }
   6918         _BCM_HG_DLB_ID_USED_SET(unit, hgtid);
   6919         *dlb_id = hgtid;
   6920         return BCM_E_NONE;
   6921     } else
   6922 #endif /* BCM_TRIDENT2_SUPPORT */
   6923     {
   6924         for (i = 0; i < soc_mem_index_count(unit, DLB_HGT_GROUP_CONTROLm); i++) {
   6925             if (!_BCM_HG_DLB_ID_USED_GET(unit, i)) {
   6926                 _BCM_HG_DLB_ID_USED_SET(unit, i);
   6927                 *dlb_id = i;
   6928                 return BCM_E_NONE;
   6929             }
   6930         }
   6931     }
   6932 
   6933     return BCM_E_RESOURCE;
   6934 }
   6935 
   6936 /*
   6937  * Function:
   6938  *      _bcm_trident_hg_dlb_id_free
   6939  * Purpose:
   6940  *      Free a Higig DLB ID.
   6941  * Parameters:
   6942  *      unit - (IN) SOC unit number.
   6943  *      dlb_id - (IN) DLB ID to be freed.
   6944  * Returns:
   6945  *      BCM_E_xxx
   6946  */
   6947 STATIC int
   6948 _bcm_trident_hg_dlb_id_free(int unit, int dlb_id)
   6949 {
   6950     if (dlb_id < 0 || dlb_id > soc_mem_index_max(unit, DLB_HGT_GROUP_CONTROLm)) {
   6951         return BCM_E_PARAM;
   6952     }
   6953 
   6954     _BCM_HG_DLB_ID_USED_CLR(unit, dlb_id);
   6955 
   6956     return BCM_E_NONE;
   6957 }
   6958 
   6959 #ifdef BCM_TRIUMPH3_SUPPORT
   6960 /*
   6961  * Function:
   6962  *      _bcm_tr3_hg_dlb_member_id_alloc
   6963  * Purpose:
   6964  *      Get a free Higig DLB Member ID and mark it used.
   6965  * Parameters:
   6966  *      unit - (IN) SOC unit number.
   6967  *      member_id - (OUT) Allocated Member ID.
   6968  * Returns:
   6969  *      BCM_E_xxx
   6970  */
   6971 STATIC int
   6972 _bcm_tr3_hg_dlb_member_id_alloc(int unit, int *member_id)
   6973 {
   6974     int i;
   6975 
   6976     for (i = 0; i < soc_mem_index_count(unit, DLB_HGT_MEMBER_ATTRIBUTEm); i++) {
   6977         if (!_BCM_HG_DLB_MEMBER_ID_USED_GET(unit, i)) {
   6978             _BCM_HG_DLB_MEMBER_ID_USED_SET(unit, i);
   6979             *member_id = i;
   6980             return BCM_E_NONE;
   6981         }
   6982     }
   6983 
   6984     return BCM_E_RESOURCE;
   6985 }
   6986 
   6987 /*
   6988  * Function:
   6989  *      _bcm_tr3_hg_dlb_member_id_free
   6990  * Purpose:
   6991  *      Free a Higig DLB Member ID.
   6992  * Parameters:
   6993  *      unit - (IN) SOC unit number.
   6994  *      member_id - (IN) Member ID to be freed.
   6995  * Returns:
   6996  *      BCM_E_xxx
   6997  */
   6998 STATIC int
   6999 _bcm_tr3_hg_dlb_member_id_free(int unit, int member_id)
   7000 {
   7001     if (member_id < 0 || member_id > soc_mem_index_max(unit,
   7002                 DLB_HGT_MEMBER_ATTRIBUTEm)) {
   7003         return BCM_E_PARAM;
   7004     }
   7005 
   7006     _BCM_HG_DLB_MEMBER_ID_USED_CLR(unit, member_id);
   7007 
   7008     return BCM_E_NONE;
   7009 }
   7010 
   7011 /*
   7012  * Function:
   7013  *      _bcm_tr3_hg_dlb_member_array_alloc
   7014  * Purpose:
   7015  *      Allocate member IDs for each Higig trunk member.
   7016  * Parameters:
   7017  *      unit  - (IN) SOC unit number. 
   7018  *      add_info - (IN) Pointer to trunk add info structure.
   7019  *      member_id_array - (OUT) Array of member IDs.
   7020  * Returns:
   7021  *      BCM_E_xxx
   7022  */
   7023 STATIC int
   7024 _bcm_tr3_hg_dlb_member_array_alloc(int unit,
   7025         _esw_trunk_add_info_t *add_info,
   7026         int *member_id_array)
   7027 {
   7028     int i;
   7029     dlb_hgt_port_member_map_entry_t port_member_map_entry;
   7030     port_tab_entry_t ptab;
   7031     dlb_hgt_member_attribute_entry_t member_attr_entry;
   7032     dlb_hgt_quality_control_entry_t quality_control_entry;
   7033     soc_field_t enable_credit_collect_f;
   7034     int hw_mask;
   7035 
   7036     for (i = 0; i < add_info->num_ports; i++) {
   7037         SOC_IF_ERROR_RETURN(READ_DLB_HGT_PORT_MEMBER_MAPm(unit, MEM_BLOCK_ANY,
   7038                     add_info->tp[i], &port_member_map_entry));
   7039         if (soc_DLB_HGT_PORT_MEMBER_MAPm_field32_get(unit,
   7040                     &port_member_map_entry, VALIDf)) {
   7041             member_id_array[i] =
   7042                 soc_DLB_HGT_PORT_MEMBER_MAPm_field32_get(unit,
   7043                         &port_member_map_entry, MEMBER_IDf);
   7044         } else {
   7045             BCM_IF_ERROR_RETURN(_bcm_tr3_hg_dlb_member_id_alloc(unit,
   7046                         &member_id_array[i]));
   7047 
   7048             /* Set member map entry */ 
   7049             soc_DLB_HGT_PORT_MEMBER_MAPm_field32_set(unit,
   7050                     &port_member_map_entry, VALIDf, 1);
   7051             soc_DLB_HGT_PORT_MEMBER_MAPm_field32_set(unit,
   7052                     &port_member_map_entry, MEMBER_IDf, member_id_array[i]);
   7053             if (soc_mem_field_valid(unit, DLB_HGT_PORT_MEMBER_MAPm, EMBEDDED_HGf)) {
   7054                 SOC_IF_ERROR_RETURN
   7055                     (READ_PORT_TABm(unit, MEM_BLOCK_ANY, add_info->tp[i], &ptab));
   7056                 if (soc_PORT_TABm_field32_get(unit, &ptab, PORT_TYPEf) == 3) {
   7057                     /* Port is an embedded Higig port */
   7058                     soc_DLB_HGT_PORT_MEMBER_MAPm_field32_set(unit,
   7059                             &port_member_map_entry, EMBEDDED_HGf, 1);
   7060                 } else {
   7061                     soc_DLB_HGT_PORT_MEMBER_MAPm_field32_set(unit,
   7062                             &port_member_map_entry, EMBEDDED_HGf, 0);
   7063                 }
   7064             }
   7065             SOC_IF_ERROR_RETURN(WRITE_DLB_HGT_PORT_MEMBER_MAPm(unit,
   7066                         MEM_BLOCK_ALL, add_info->tp[i],
   7067                         &port_member_map_entry));
   7068 
   7069             /* Set member attribute entry */
   7070             SOC_IF_ERROR_RETURN(READ_DLB_HGT_MEMBER_ATTRIBUTEm(unit,
   7071                         MEM_BLOCK_ANY, member_id_array[i],
   7072                         &member_attr_entry));
   7073             soc_DLB_HGT_MEMBER_ATTRIBUTEm_field32_set(unit, &member_attr_entry,
   7074                     PORT_NUMf, add_info->tp[i]);
   7075             SOC_IF_ERROR_RETURN(WRITE_DLB_HGT_MEMBER_ATTRIBUTEm(unit,
   7076                         MEM_BLOCK_ALL, member_id_array[i],
   7077                         &member_attr_entry));
   7078 
   7079             /* Set member quality mapping profile */
   7080             BCM_IF_ERROR_RETURN(_bcm_tr3_hg_dlb_member_quality_map_set(unit,
   7081                         member_id_array[i], add_info->dynamic_load_weight[i]));
   7082 
   7083             /* Enable member quality control */
   7084             SOC_IF_ERROR_RETURN(READ_DLB_HGT_QUALITY_CONTROLm(unit,
   7085                         MEM_BLOCK_ANY, member_id_array[i],
   7086                         &quality_control_entry));
   7087             soc_DLB_HGT_QUALITY_CONTROLm_field32_set(unit,
   7088                     &quality_control_entry, ENABLE_AVG_CALCf, 1);
   7089             soc_DLB_HGT_QUALITY_CONTROLm_field32_set(unit,
   7090                     &quality_control_entry, ENABLE_QUALITY_UPDATEf, 1);
   7091             enable_credit_collect_f = soc_mem_field_valid(unit,
   7092                     DLB_HGT_QUALITY_CONTROLm, ENABLE_CREDIT_COLLECTIONf) ?
   7093                 ENABLE_CREDIT_COLLECTIONf : ENB_CREDIT_COLLECTIONf;
   7094             soc_DLB_HGT_QUALITY_CONTROLm_field32_set(unit,
   7095                     &quality_control_entry, enable_credit_collect_f, 1);
   7096             hw_mask = (1 << soc_mem_field_length(unit, DLB_HGT_QUALITY_CONTROLm,
   7097                                           LOADING_SCALING_FACTORf)) - 1;
   7098             soc_DLB_HGT_QUALITY_CONTROLm_field32_set(unit,
   7099                     &quality_control_entry, LOADING_SCALING_FACTORf,
   7100                     add_info->dynamic_scaling_factor[i] & hw_mask);
   7101             hw_mask = (1 << soc_mem_field_length(unit, DLB_HGT_QUALITY_CONTROLm,
   7102                                           QSIZE_SCALING_FACTORf)) - 1;
   7103             soc_DLB_HGT_QUALITY_CONTROLm_field32_set(unit,
   7104                     &quality_control_entry, QSIZE_SCALING_FACTORf, 
   7105                     add_info->dynamic_scaling_factor[i] & hw_mask);
   7106             SOC_IF_ERROR_RETURN(WRITE_DLB_HGT_QUALITY_CONTROLm(unit,
   7107                         MEM_BLOCK_ALL, member_id_array[i],
   7108                         &quality_control_entry));
   7109         }
   7110     }
   7111 
   7112     return BCM_E_NONE;
   7113 }
   7114 
   7115 /*
   7116  * Function:
   7117  *      _bcm_tr3_hg_dlb_member_free_resource
   7118  * Purpose:
   7119  *      Clear state and free resources associated with a Higig DLB member.
   7120  * Parameters:
   7121  *      unit  - (IN) SOC unit number. 
   7122  *      member_id - (IN) Member ID.
   7123  * Returns:
   7124  *      BCM_E_xxx
   7125  */
   7126 STATIC int
   7127 _bcm_tr3_hg_dlb_member_free_resource(int unit, int member_id)
   7128 {
   7129     dlb_hgt_quality_control_entry_t quality_control_entry;
   7130     soc_field_t enable_credit_collect_f;
   7131     dlb_hgt_member_attribute_entry_t member_attribute_entry;
   7132     int port_num;
   7133 
   7134     /* Disable member quality control */
   7135     SOC_IF_ERROR_RETURN(READ_DLB_HGT_QUALITY_CONTROLm(unit, MEM_BLOCK_ANY,
   7136                 member_id, &quality_control_entry));
   7137     soc_DLB_HGT_QUALITY_CONTROLm_field32_set(unit,
   7138             &quality_control_entry, ENABLE_AVG_CALCf, 0);
   7139     soc_DLB_HGT_QUALITY_CONTROLm_field32_set(unit,
   7140             &quality_control_entry, ENABLE_QUALITY_UPDATEf, 0);
   7141     enable_credit_collect_f = soc_mem_field_valid(unit,
   7142             DLB_HGT_QUALITY_CONTROLm, ENABLE_CREDIT_COLLECTIONf) ?
   7143         ENABLE_CREDIT_COLLECTIONf : ENB_CREDIT_COLLECTIONf;
   7144     soc_DLB_HGT_QUALITY_CONTROLm_field32_set(unit,
   7145             &quality_control_entry, enable_credit_collect_f, 0);
   7146     soc_DLB_HGT_QUALITY_CONTROLm_field32_set(unit, &quality_control_entry,
   7147             LOADING_SCALING_FACTORf, 0);
   7148     soc_DLB_HGT_QUALITY_CONTROLm_field32_set(unit, &quality_control_entry,
   7149             QSIZE_SCALING_FACTORf, 0);
   7150     SOC_IF_ERROR_RETURN(WRITE_DLB_HGT_QUALITY_CONTROLm(unit, MEM_BLOCK_ALL,
   7151                 member_id, &quality_control_entry));
   7152 
   7153     /* Revert member quality mapping profile to default */
   7154     BCM_IF_ERROR_RETURN
   7155         (_bcm_tr3_hg_dlb_member_quality_map_set(unit, member_id, 100));
   7156 
   7157     /* Clear member attribute entry */
   7158     SOC_IF_ERROR_RETURN(READ_DLB_HGT_MEMBER_ATTRIBUTEm(unit, MEM_BLOCK_ANY,
   7159                 member_id, &member_attribute_entry));
   7160     port_num = soc_DLB_HGT_MEMBER_ATTRIBUTEm_field32_get(unit,
   7161             &member_attribute_entry, PORT_NUMf);
   7162     SOC_IF_ERROR_RETURN(WRITE_DLB_HGT_MEMBER_ATTRIBUTEm(unit, MEM_BLOCK_ALL,
   7163                 member_id, soc_mem_entry_null(unit, DLB_HGT_MEMBER_ATTRIBUTEm)));
   7164 
   7165     /* Clear member map entry */
   7166     SOC_IF_ERROR_RETURN(WRITE_DLB_HGT_PORT_MEMBER_MAPm(unit, MEM_BLOCK_ALL,
   7167                 port_num, soc_mem_entry_null(unit, DLB_HGT_PORT_MEMBER_MAPm)));
   7168 
   7169     /* Free member ID */
   7170     BCM_IF_ERROR_RETURN(_bcm_tr3_hg_dlb_member_id_free(unit, member_id));
   7171 
   7172     return BCM_E_NONE;
   7173 }
   7174 
   7175 /*
   7176  * Function:
   7177  *      _bcm_tr3_hg_dlb_member_attr_get
   7178  * Purpose:
   7179  *      Get attributes of a Higig DLB member.
   7180  * Parameters:
   7181  *      unit - (IN) SOC unit number. 
   7182  *      port - (IN) Port number of the member.
   7183  *      scaling_factor - (OUT) Member's scaling factor.
   7184  *      load_weight    - (OUT) Member's load weight.
   7185  * Returns:
   7186  *      BCM_E_xxx
   7187  */
   7188 STATIC int
   7189 _bcm_tr3_hg_dlb_member_attr_get(int unit, bcm_port_t port,
   7190         int *scaling_factor, int *load_weight)
   7191 {
   7192     dlb_hgt_port_member_map_entry_t port_member_map_entry;
   7193     int member_id;
   7194     dlb_hgt_quality_control_entry_t quality_control_entry;
   7195     soc_field_t profile_ptr_f;
   7196     int profile_ptr = 0;
   7197 
   7198     /* Find member ID of the given module and port */
   7199     SOC_IF_ERROR_RETURN(READ_DLB_HGT_PORT_MEMBER_MAPm(unit, MEM_BLOCK_ANY,
   7200                 port, &port_member_map_entry));
   7201     if (!soc_DLB_HGT_PORT_MEMBER_MAPm_field32_get(unit, &port_member_map_entry,
   7202                 VALIDf)) {
   7203         return BCM_E_NOT_FOUND;
   7204     }
   7205     member_id = soc_DLB_HGT_PORT_MEMBER_MAPm_field32_get(unit,
   7206             &port_member_map_entry, MEMBER_IDf);
   7207 
   7208     /* Get member's scaling factor and load weight */
   7209     SOC_IF_ERROR_RETURN(READ_DLB_HGT_QUALITY_CONTROLm(unit, MEM_BLOCK_ANY,
   7210                 member_id, &quality_control_entry));
   7211     *scaling_factor = soc_DLB_HGT_QUALITY_CONTROLm_field32_get(unit,
   7212             &quality_control_entry, LOADING_SCALING_FACTORf);
   7213     profile_ptr_f = soc_mem_field_valid(unit, DLB_HGT_QUALITY_CONTROLm,
   7214             PROFILE_PTRf) ? PROFILE_PTRf : QMT_PROFILE_PTRf;
   7215     profile_ptr = soc_DLB_HGT_QUALITY_CONTROLm_field32_get(unit,
   7216             &quality_control_entry, profile_ptr_f);
   7217     *load_weight = HG_DLB_INFO(unit)->hg_dlb_load_weight[profile_ptr];
   7218 
   7219     return BCM_E_NONE;
   7220 }
   7221 
   7222 #endif /* BCM_TRIUMPH3_SUPPORT */
   7223 
   7224 /*
   7225  * Function:
   7226  *      _bcm_trident_hg_dlb_dynamic_size_encode
   7227  * Purpose:
   7228  *      Encode Higig trunk dynamic load balancing flow set size.
   7229  * Parameters:
   7230  *      dynamic_size - (IN) Number of flow sets.
   7231  *      encoded_value - (OUT) Encoded value.
   7232  * Returns:
   7233  *      BCM_E_xxx
   7234  */
   7235 STATIC int
   7236 _bcm_trident_hg_dlb_dynamic_size_encode(int dynamic_size,
   7237         int *encoded_value)
   7238 {   
   7239     switch (dynamic_size) {
   7240         case 512:
   7241             *encoded_value = 1;
   7242             break;
   7243         case 1024:
   7244             *encoded_value = 2;
   7245             break;
   7246         case 2048:
   7247             *encoded_value = 3;
   7248             break;
   7249         case 4096:
   7250             *encoded_value = 4;
   7251             break;
   7252         case 8192:
   7253             *encoded_value = 5;
   7254             break;
   7255         case 16384:
   7256             *encoded_value = 6;
   7257             break;
   7258         case 32768:
   7259             *encoded_value = 7;
   7260             break;
   7261         default:
   7262             return BCM_E_PARAM;
   7263     }
   7264 
   7265     return BCM_E_NONE;
   7266 }
   7267 
   7268 /*
   7269  * Function:
   7270  *      _bcm_trident_hg_dlb_dynamic_size_decode
   7271  * Purpose:
   7272  *      Decode Higig trunk dynamic load balancing flow set size.
   7273  * Parameters:
   7274  *      encoded_value - (IN) Encoded value.
   7275  *      dynamic_size - (OUT) Number of flow sets.
   7276  * Returns:
   7277  *      BCM_E_xxx
   7278  */
   7279 STATIC int
   7280 _bcm_trident_hg_dlb_dynamic_size_decode(int encoded_value,
   7281         int *dynamic_size)
   7282 {   
   7283     switch (encoded_value) {
   7284         case 1:
   7285             *dynamic_size = 512;
   7286             break;
   7287         case 2:
   7288             *dynamic_size = 1024;
   7289             break;
   7290         case 3:
   7291             *dynamic_size = 2048;
   7292             break;
   7293         case 4:
   7294             *dynamic_size = 4096;
   7295             break;
   7296         case 5:
   7297             *dynamic_size = 8192;
   7298             break;
   7299         case 6:
   7300             *dynamic_size = 16384;
   7301             break;
   7302         case 7:
   7303             *dynamic_size = 32768;
   7304             break;
   7305         default:
   7306             return BCM_E_INTERNAL;
   7307     }
   7308 
   7309     return BCM_E_NONE;
   7310 }
   7311 
   7312 /*
   7313  * Function:
   7314  *      _bcm_trident_hg_dlb_free_resource
   7315  * Purpose:
   7316  *      Free resources for a Higig dynamic load balancing group.
   7317  * Parameters:
   7318  *      unit  - (IN) SOC unit number. 
   7319  *      hgtid - (IN) Higig group ID.
   7320  * Returns:
   7321  *      BCM_E_xxx
   7322  */
   7323 STATIC int
   7324 _bcm_trident_hg_dlb_free_resource(int unit, int hgtid)
   7325 {
   7326     int rv = BCM_E_NONE;
   7327     hgt_dlb_control_entry_t hgt_dlb_control_entry;
   7328     int dlb_enable, dlb_id;
   7329     dlb_hgt_group_control_entry_t dlb_hgt_group_control_entry;
   7330     int entry_base_ptr;
   7331     int flow_set_size;
   7332     int num_entries;
   7333     int block_base_ptr;
   7334     int num_blocks;
   7335 
   7336 #ifdef BCM_TRIDENT2_SUPPORT
   7337     if (soc_feature(unit, soc_feature_hg_dlb_id_equal_hg_tid)) {
   7338         SOC_IF_ERROR_RETURN(READ_DLB_HGT_GROUP_CONTROLm(unit, MEM_BLOCK_ANY,
   7339                     hgtid, &dlb_hgt_group_control_entry));
   7340         dlb_enable = soc_DLB_HGT_GROUP_CONTROLm_field32_get(unit,
   7341                 &dlb_hgt_group_control_entry, GROUP_ENABLEf);
   7342         dlb_id = hgtid;
   7343     } else
   7344 #endif /* BCM_TRIDENT2_SUPPORT */
   7345     {
   7346         SOC_IF_ERROR_RETURN(READ_HGT_DLB_CONTROLm(unit, MEM_BLOCK_ANY, hgtid,
   7347                     &hgt_dlb_control_entry));
   7348         dlb_enable = soc_HGT_DLB_CONTROLm_field32_get(unit,
   7349                 &hgt_dlb_control_entry, GROUP_ENABLEf);
   7350         dlb_id = soc_HGT_DLB_CONTROLm_field32_get(unit,
   7351                 &hgt_dlb_control_entry, DLB_IDf);
   7352     }
   7353     if (!dlb_enable) {
   7354         return BCM_E_NONE;
   7355     }
   7356 
   7357     /* Clear ENHANCED_HASHING_ENABLE in HG_TRUNK_GROUP */
   7358 #ifdef BCM_TRIDENT2_SUPPORT
   7359     if (soc_mem_field_valid(unit, HG_TRUNK_GROUPm, ENHANCED_HASHING_ENABLEf)) {
   7360         hg_trunk_group_entry_t hg_trunk_group_entry;
   7361 
   7362         SOC_IF_ERROR_RETURN(READ_HG_TRUNK_GROUPm(unit, MEM_BLOCK_ANY, hgtid,
   7363                     &hg_trunk_group_entry));
   7364         soc_HG_TRUNK_GROUPm_field32_set(unit, &hg_trunk_group_entry,
   7365                 ENHANCED_HASHING_ENABLEf, 0);
   7366         SOC_IF_ERROR_RETURN(WRITE_HG_TRUNK_GROUPm(unit, MEM_BLOCK_ALL, hgtid,
   7367                     &hg_trunk_group_entry));
   7368     }
   7369 #endif /* BCM_TRIDENT2_SUPPORT */
   7370 
   7371     /* Clear HGT_DLB_CONTROL entry */
   7372     if (soc_mem_is_valid(unit, HGT_DLB_CONTROLm)) {
   7373         SOC_IF_ERROR_RETURN(WRITE_HGT_DLB_CONTROLm(unit, MEM_BLOCK_ALL, hgtid,
   7374                     soc_mem_entry_null(unit, HGT_DLB_CONTROLm)));
   7375     }
   7376 
   7377     /* Clear DLB_HGT_GROUP_CONTROL entry */
   7378     SOC_IF_ERROR_RETURN(READ_DLB_HGT_GROUP_CONTROLm(unit, MEM_BLOCK_ANY, dlb_id,
   7379                 &dlb_hgt_group_control_entry));
   7380     entry_base_ptr = soc_DLB_HGT_GROUP_CONTROLm_field32_get(unit,
   7381             &dlb_hgt_group_control_entry, FLOW_SET_BASEf);
   7382     flow_set_size = soc_DLB_HGT_GROUP_CONTROLm_field32_get(unit,
   7383             &dlb_hgt_group_control_entry, FLOW_SET_SIZEf);
   7384     SOC_IF_ERROR_RETURN(WRITE_DLB_HGT_GROUP_CONTROLm(unit, MEM_BLOCK_ALL,
   7385                 dlb_id, soc_mem_entry_null(unit, DLB_HGT_GROUP_CONTROLm)));
   7386 
   7387     if (SOC_MEM_IS_VALID(unit, DLB_HGT_GROUP_CONTROL_Xm)) {
   7388         SOC_IF_ERROR_RETURN(
   7389             WRITE_DLB_HGT_GROUP_CONTROL_Xm(
   7390                 unit, MEM_BLOCK_ALL, dlb_id,
   7391                 soc_mem_entry_null(unit, DLB_HGT_GROUP_CONTROL_Xm)));
   7392     }
   7393 
   7394     if (SOC_MEM_IS_VALID(unit, DLB_HGT_GROUP_CONTROL_Ym)) {
   7395         SOC_IF_ERROR_RETURN(
   7396             WRITE_DLB_HGT_GROUP_CONTROL_Ym(
   7397                 unit, MEM_BLOCK_ALL, dlb_id,
   7398                 soc_mem_entry_null(unit, DLB_HGT_GROUP_CONTROL_Ym)));
   7399     }
   7400 
   7401     /* Free flow set table resources */
   7402     BCM_IF_ERROR_RETURN
   7403         (_bcm_trident_hg_dlb_dynamic_size_decode(flow_set_size, &num_entries));
   7404     block_base_ptr = entry_base_ptr >> 9;
   7405     num_blocks = num_entries >> 9; 
   7406     _BCM_HG_DLB_FLOWSET_BLOCK_USED_CLR_RANGE(unit, block_base_ptr, num_blocks);
   7407 
   7408 #ifdef BCM_TRIUMPH3_SUPPORT
   7409     if (soc_feature(unit, soc_feature_hg_dlb_member_id)) {
   7410         dlb_hgt_group_membership_entry_t dlb_hgt_group_membership_entry;
   7411         int member_bitmap_width, alloc_size;
   7412         int i;
   7413         SHR_BITDCL *member_bitmap = NULL;
   7414         SHR_BITDCL *status_bitmap = NULL;
   7415         SHR_BITDCL *override_bitmap = NULL;
   7416         dlb_hgt_member_sw_state_entry_t dlb_hgt_member_sw_state_entry;
   7417 
   7418         /* Get membership and clear each member's state */
   7419         SOC_IF_ERROR_RETURN(READ_DLB_HGT_GROUP_MEMBERSHIPm(unit, MEM_BLOCK_ANY,
   7420                     dlb_id, &dlb_hgt_group_membership_entry));
   7421         member_bitmap_width = soc_mem_field_length(unit,
   7422             DLB_HGT_GROUP_MEMBERSHIPm, MEMBER_BITMAPf);
   7423         alloc_size = SHR_BITALLOCSIZE(member_bitmap_width);
   7424         member_bitmap = sal_alloc(alloc_size, "DLB HGT member bitmap"); 
   7425         if (NULL == member_bitmap) {
   7426             return BCM_E_MEMORY;
   7427         }
   7428         soc_DLB_HGT_GROUP_MEMBERSHIPm_field_get(unit,
   7429             &dlb_hgt_group_membership_entry, MEMBER_BITMAPf, member_bitmap);
   7430         for (i = 0; i < member_bitmap_width; i++) {
   7431             if (SHR_BITGET(member_bitmap, i)) {
   7432                 rv = _bcm_tr3_hg_dlb_member_free_resource(unit, i);
   7433                 if (BCM_FAILURE(rv)) {
   7434                     sal_free(member_bitmap);
   7435                     return rv;
   7436                 }
   7437             }
   7438         }
   7439 
   7440         /* Clear member software state */
   7441         rv = READ_DLB_HGT_MEMBER_SW_STATEm(unit, MEM_BLOCK_ANY, 0,
   7442                 &dlb_hgt_member_sw_state_entry);
   7443         if (BCM_FAILURE(rv)) {
   7444             sal_free(member_bitmap);
   7445             return rv;
   7446         }
   7447 
   7448         status_bitmap = sal_alloc(alloc_size, "DLB HGT member status bitmap"); 
   7449         if (NULL == status_bitmap) {
   7450             sal_free(member_bitmap);
   7451             return BCM_E_MEMORY;
   7452         }
   7453         soc_DLB_HGT_MEMBER_SW_STATEm_field_get(unit,
   7454                 &dlb_hgt_member_sw_state_entry, MEMBER_BITMAPf, status_bitmap);
   7455         SHR_BITREMOVE_RANGE(status_bitmap, member_bitmap, 0, member_bitmap_width,
   7456                 status_bitmap);
   7457         soc_DLB_HGT_MEMBER_SW_STATEm_field_set(unit,
   7458                 &dlb_hgt_member_sw_state_entry, MEMBER_BITMAPf, status_bitmap);
   7459 
   7460         override_bitmap = sal_alloc(alloc_size, "DLB HGT member override bitmap"); 
   7461         if (NULL == override_bitmap) {
   7462             sal_free(member_bitmap);
   7463             sal_free(status_bitmap);
   7464             return BCM_E_MEMORY;
   7465         }
   7466         soc_DLB_HGT_MEMBER_SW_STATEm_field_get(unit,
   7467                 &dlb_hgt_member_sw_state_entry, OVERRIDE_MEMBER_BITMAPf, override_bitmap);
   7468         SHR_BITREMOVE_RANGE(override_bitmap, member_bitmap, 0, member_bitmap_width,
   7469                 override_bitmap);
   7470         soc_DLB_HGT_MEMBER_SW_STATEm_field_set(unit,
   7471                 &dlb_hgt_member_sw_state_entry, OVERRIDE_MEMBER_BITMAPf, override_bitmap);
   7472 
   7473         rv = WRITE_DLB_HGT_MEMBER_SW_STATEm(unit, MEM_BLOCK_ALL, 0,
   7474                     &dlb_hgt_member_sw_state_entry);
   7475         sal_free(member_bitmap);
   7476         sal_free(status_bitmap);
   7477         sal_free(override_bitmap);
   7478         if (BCM_FAILURE(rv)) {
   7479             return rv;
   7480         }
   7481 
   7482         /* Clear group membership */
   7483         SOC_IF_ERROR_RETURN(WRITE_DLB_HGT_GROUP_MEMBERSHIPm(unit,
   7484                     MEM_BLOCK_ALL, dlb_id, soc_mem_entry_null(unit,
   7485                         DLB_HGT_GROUP_MEMBERSHIPm)));
   7486     } else
   7487 #endif /* BCM_TRIUMPH3_SUPPORT */
   7488     {
   7489         dlb_hgt_group_membership_entry_t dlb_hgt_group_membership_entry;
   7490         bcm_pbmp_t port_map, negated_port_map;
   7491         bcm_port_t port;
   7492         uint32 quantize_control;
   7493         uint32 measure_update_control;
   7494         dlb_hgt_link_control_entry_t dlb_hgt_link_control_entry;
   7495         bcm_pbmp_t sw_port_state, override_port_map;
   7496 
   7497         SOC_IF_ERROR_RETURN(READ_DLB_HGT_GROUP_MEMBERSHIPm(unit, MEM_BLOCK_ANY,
   7498                     dlb_id, &dlb_hgt_group_membership_entry));
   7499         soc_mem_pbmp_field_get(unit, DLB_HGT_GROUP_MEMBERSHIPm,
   7500                 &dlb_hgt_group_membership_entry, PORT_MAPf, &port_map);
   7501         BCM_PBMP_ITER(port_map, port) {
   7502             /* Disable quality measure update */
   7503             SOC_IF_ERROR_RETURN
   7504                 (READ_DLB_HGT_PORT_QUALITY_MEASURE_UPDATE_CONTROLr(unit,
   7505                     port, &measure_update_control));
   7506             soc_reg_field_set(unit, DLB_HGT_PORT_QUALITY_MEASURE_UPDATE_CONTROLr,
   7507                     &measure_update_control, ENABLE_MEASURE_COLLECTIONf, 0);
   7508             soc_reg_field_set(unit, DLB_HGT_PORT_QUALITY_MEASURE_UPDATE_CONTROLr,
   7509                     &measure_update_control, ENABLE_MEASURE_AVERAGE_CALCULATIONf, 0);
   7510             soc_reg_field_set(unit, DLB_HGT_PORT_QUALITY_MEASURE_UPDATE_CONTROLr,
   7511                     &measure_update_control, ENABLE_PORT_QUALITY_UPDATEf, 0);
   7512             SOC_IF_ERROR_RETURN
   7513                 (WRITE_DLB_HGT_PORT_QUALITY_MEASURE_UPDATE_CONTROLr(unit,
   7514                     port, measure_update_control));
   7515 
   7516             /* Revert member quality mapping profile to default */
   7517             BCM_IF_ERROR_RETURN
   7518                 (_bcm_trident_hg_dlb_quality_map_set(unit, port, 100));
   7519 
   7520             /* Clear threshold scaling factors */
   7521             SOC_IF_ERROR_RETURN(READ_DLB_HGT_QUANTIZE_CONTROLr(unit, port,
   7522                         &quantize_control));
   7523             soc_reg_field_set(unit, DLB_HGT_QUANTIZE_CONTROLr,
   7524                     &quantize_control, PORT_LOADING_THRESHOLD_SCALING_FACTORf, 0);
   7525             soc_reg_field_set(unit, DLB_HGT_QUANTIZE_CONTROLr,
   7526                     &quantize_control, PORT_QSIZE_THRESHOLD_SCALING_FACTORf, 0);
   7527             SOC_IF_ERROR_RETURN(WRITE_DLB_HGT_QUANTIZE_CONTROLr(unit, port,
   7528                         quantize_control));
   7529         }
   7530 
   7531         /* Clear member software state */
   7532         SOC_IF_ERROR_RETURN(READ_DLB_HGT_LINK_CONTROLm(unit, MEM_BLOCK_ANY,
   7533                     0, &dlb_hgt_link_control_entry));
   7534 
   7535         soc_mem_pbmp_field_get(unit, DLB_HGT_LINK_CONTROLm,
   7536                 &dlb_hgt_link_control_entry, SW_PORT_STATEf, &sw_port_state);
   7537         BCM_PBMP_NEGATE(negated_port_map, port_map);
   7538         BCM_PBMP_AND(sw_port_state, negated_port_map);
   7539         soc_mem_pbmp_field_set(unit, DLB_HGT_LINK_CONTROLm,
   7540                 &dlb_hgt_link_control_entry, SW_PORT_STATEf, &sw_port_state);
   7541 
   7542         soc_mem_pbmp_field_get(unit, DLB_HGT_LINK_CONTROLm,
   7543                 &dlb_hgt_link_control_entry, SW_OVERRIDE_PORT_MAPf,
   7544                 &override_port_map);
   7545         BCM_PBMP_AND(override_port_map, negated_port_map);
   7546         soc_mem_pbmp_field_set(unit, DLB_HGT_LINK_CONTROLm,
   7547                 &dlb_hgt_link_control_entry, SW_OVERRIDE_PORT_MAPf,
   7548                 &override_port_map);
   7549 
   7550         SOC_IF_ERROR_RETURN(WRITE_DLB_HGT_LINK_CONTROLm(unit, MEM_BLOCK_ALL,
   7551                     0, &dlb_hgt_link_control_entry));
   7552 
   7553         /* Clear group membership */
   7554         SOC_IF_ERROR_RETURN(WRITE_DLB_HGT_GROUP_MEMBERSHIPm(unit,
   7555                     MEM_BLOCK_ALL, dlb_id, soc_mem_entry_null(unit,
   7556                         DLB_HGT_GROUP_MEMBERSHIPm)));
   7557     }
   7558 
   7559     /* Free DLB ID */
   7560     BCM_IF_ERROR_RETURN(_bcm_trident_hg_dlb_id_free(unit, dlb_id));
   7561 
   7562     return rv;
   7563 }
   7564 
   7565 /*
   7566  * Function:
   7567  *      _bcm_trident_hg_dlb_set
   7568  * Purpose:
   7569  *      Configure a Higig dynamic load balancing group.
   7570  * Parameters:
   7571  *      unit  - (IN) SOC unit number. 
   7572  *      hgtid - (IN) Higig trunk group ID.
   7573  *      add_info - (IN) Pointer to trunk add info structure.
   7574  * Returns:
   7575  *      BCM_E_xxx
   7576  */
   7577 STATIC int
   7578 _bcm_trident_hg_dlb_set(int unit,
   7579         int hgtid,
   7580         _esw_trunk_add_info_t *add_info)
   7581 {
   7582     int dlb_enable;
   7583     int dlb_id;
   7584     int num_blocks;
   7585     int total_blocks;
   7586     int max_block_base_ptr;
   7587     int block_base_ptr;
   7588     SHR_BITDCL occupied;
   7589     int entry_base_ptr;
   7590     int num_entries_per_block;
   7591     int alloc_size;
   7592     uint32 *block_ptr = NULL;
   7593     int i, k, m;
   7594     int index_min, index_max;
   7595     int rv = BCM_E_NONE;
   7596     dlb_hgt_group_control_entry_t dlb_hgt_group_control_entry;
   7597     int flow_set_size;
   7598     int dlb_mode;
   7599     hgt_dlb_control_entry_t hgt_dlb_control_entry;
   7600     int *member_id_array = NULL;
   7601     soc_mem_t flowset_mem[3] = {INVALIDm, INVALIDm, INVALIDm};
   7602     int flowset_entry_size;
   7603     SHR_BITDCL *member_bitmap = NULL;
   7604     SHR_BITDCL *override_bitmap = NULL;
   7605 
   7606     dlb_enable = (add_info->psc == BCM_TRUNK_PSC_DYNAMIC) ||
   7607         (add_info->psc == BCM_TRUNK_PSC_DYNAMIC_ASSIGNED) ||
   7608         (add_info->psc == BCM_TRUNK_PSC_DYNAMIC_OPTIMAL);
   7609     if (!dlb_enable) {
   7610         return BCM_E_NONE;
   7611     }
   7612 
   7613     /* Allocate a free DLB ID */
   7614     BCM_IF_ERROR_RETURN(_bcm_trident_hg_dlb_id_alloc(unit, hgtid, &dlb_id));
   7615 
   7616 #ifdef BCM_TRIUMPH3_SUPPORT
   7617     if (soc_feature(unit, soc_feature_hg_dlb_member_id)) {
   7618         int member_bitmap_width;
   7619         dlb_hgt_group_membership_entry_t dlb_hgt_group_membership_entry;
   7620         dlb_hgt_member_sw_state_entry_t dlb_hgt_member_sw_state_entry;
   7621 
   7622         /* Allocate member IDs */
   7623         member_id_array = sal_alloc(sizeof(int) * add_info->num_ports,
   7624                 "Higig DLB Member IDs");
   7625         if (NULL == member_id_array) {
   7626             rv = BCM_E_MEMORY;
   7627             goto error;
   7628         }
   7629         rv = _bcm_tr3_hg_dlb_member_array_alloc(unit, add_info,
   7630                 member_id_array);
   7631         if (BCM_FAILURE(rv)) {
   7632             goto error;
   7633         }
   7634 
   7635         /* Set group membership */
   7636         member_bitmap_width = soc_mem_field_length(unit,
   7637                 DLB_HGT_GROUP_MEMBERSHIPm, MEMBER_BITMAPf);
   7638         alloc_size = SHR_BITALLOCSIZE(member_bitmap_width);
   7639         member_bitmap = sal_alloc(alloc_size, "DLB HGT member bitmap"); 
   7640         if (NULL == member_bitmap) {
   7641             rv = BCM_E_MEMORY;
   7642             goto error;
   7643         }
   7644         sal_memset(member_bitmap, 0, alloc_size);
   7645         for (i = 0; i < add_info->num_ports; i++) {
   7646             SHR_BITSET(member_bitmap, member_id_array[i]);
   7647         }
   7648         sal_memset(&dlb_hgt_group_membership_entry, 0,
   7649                 sizeof(dlb_hgt_group_membership_entry_t));
   7650         soc_DLB_HGT_GROUP_MEMBERSHIPm_field_set(unit,
   7651                 &dlb_hgt_group_membership_entry, MEMBER_BITMAPf, member_bitmap);
   7652         rv = WRITE_DLB_HGT_GROUP_MEMBERSHIPm(unit, MEM_BLOCK_ALL, dlb_id,
   7653                 &dlb_hgt_group_membership_entry);
   7654         if (BCM_FAILURE(rv)) {
   7655             goto error;
   7656         }
   7657 
   7658         /* Disable member state software override */
   7659         rv = READ_DLB_HGT_MEMBER_SW_STATEm(unit, MEM_BLOCK_ANY,
   7660                 0, &dlb_hgt_member_sw_state_entry);
   7661         if (BCM_FAILURE(rv)) {
   7662             goto error;
   7663         }
   7664         override_bitmap = sal_alloc(alloc_size, "DLB HGT member override bitmap"); 
   7665         if (NULL == override_bitmap) {
   7666             rv = BCM_E_MEMORY;
   7667             goto error;
   7668         }
   7669         soc_DLB_HGT_MEMBER_SW_STATEm_field_get(unit,
   7670             &dlb_hgt_member_sw_state_entry, OVERRIDE_MEMBER_BITMAPf,
   7671             override_bitmap);
   7672         SHR_BITREMOVE_RANGE(override_bitmap, member_bitmap, 0, member_bitmap_width,
   7673                 override_bitmap);
   7674         soc_DLB_HGT_MEMBER_SW_STATEm_field_set(unit,
   7675             &dlb_hgt_member_sw_state_entry, OVERRIDE_MEMBER_BITMAPf,
   7676             override_bitmap);
   7677         rv = WRITE_DLB_HGT_MEMBER_SW_STATEm(unit, MEM_BLOCK_ALL,
   7678                 0, &dlb_hgt_member_sw_state_entry);
   7679         if (BCM_FAILURE(rv)) {
   7680             goto error;
   7681         }
   7682     } else
   7683 #endif /* BCM_TRIUMPH3_SUPPORT */
   7684     {
   7685         uint32 quantize_control;
   7686         uint32 measure_update_control;
   7687         dlb_hgt_group_membership_entry_t dlb_hgt_group_membership_entry;
   7688         bcm_pbmp_t port_map, negated_port_map, override_port_map;
   7689         dlb_hgt_link_control_entry_t dlb_hgt_link_control_entry;
   7690 
   7691         BCM_PBMP_CLEAR(port_map);
   7692         for (i = 0; i < add_info->num_ports; i++) {
   7693             /* Set port quality mapping profile */
   7694             rv = _bcm_trident_hg_dlb_quality_map_set(unit,
   7695                     add_info->tp[i], add_info->dynamic_load_weight[i]);
   7696             if (BCM_FAILURE(rv)) {
   7697                 goto error;
   7698             }
   7699 
   7700             /* Set port threshold scaling factors */
   7701             rv = READ_DLB_HGT_QUANTIZE_CONTROLr(unit, add_info->tp[i],
   7702                     &quantize_control);
   7703             if (BCM_FAILURE(rv)) {
   7704                 goto error;
   7705             }
   7706             soc_reg_field_set(unit, DLB_HGT_QUANTIZE_CONTROLr,
   7707                     &quantize_control, PORT_LOADING_THRESHOLD_SCALING_FACTORf,
   7708                     add_info->dynamic_scaling_factor[i]);
   7709             soc_reg_field_set(unit, DLB_HGT_QUANTIZE_CONTROLr,
   7710                     &quantize_control, PORT_QSIZE_THRESHOLD_SCALING_FACTORf,
   7711                     add_info->dynamic_scaling_factor[i]);
   7712             rv = WRITE_DLB_HGT_QUANTIZE_CONTROLr(unit, add_info->tp[i],
   7713                     quantize_control);
   7714             if (BCM_FAILURE(rv)) {
   7715                 goto error;
   7716             }
   7717 
   7718             /* Enable quality measure update */
   7719             rv = READ_DLB_HGT_PORT_QUALITY_MEASURE_UPDATE_CONTROLr(unit,
   7720                     add_info->tp[i], &measure_update_control);
   7721             if (BCM_FAILURE(rv)) {
   7722                 goto error;
   7723             }
   7724             soc_reg_field_set(unit, DLB_HGT_PORT_QUALITY_MEASURE_UPDATE_CONTROLr,
   7725                     &measure_update_control, ENABLE_MEASURE_COLLECTIONf, 1);
   7726             soc_reg_field_set(unit, DLB_HGT_PORT_QUALITY_MEASURE_UPDATE_CONTROLr,
   7727                     &measure_update_control, ENABLE_MEASURE_AVERAGE_CALCULATIONf, 1);
   7728             soc_reg_field_set(unit, DLB_HGT_PORT_QUALITY_MEASURE_UPDATE_CONTROLr,
   7729                     &measure_update_control, ENABLE_PORT_QUALITY_UPDATEf, 1);
   7730             rv = WRITE_DLB_HGT_PORT_QUALITY_MEASURE_UPDATE_CONTROLr(unit,
   7731                     add_info->tp[i], measure_update_control);
   7732             if (BCM_FAILURE(rv)) {
   7733                 goto error;
   7734             }
   7735 
   7736             /* Set group port bitmap */
   7737             BCM_PBMP_PORT_ADD(port_map, add_info->tp[i]);
   7738         }
   7739 
   7740         /* Set group membership */
   7741         sal_memset(&dlb_hgt_group_membership_entry, 0,
   7742                 sizeof(dlb_hgt_group_membership_entry_t));
   7743         soc_mem_pbmp_field_set(unit, DLB_HGT_GROUP_MEMBERSHIPm,
   7744                 &dlb_hgt_group_membership_entry, PORT_MAPf, &port_map);
   7745         rv = WRITE_DLB_HGT_GROUP_MEMBERSHIPm(unit, MEM_BLOCK_ALL, dlb_id,
   7746                 &dlb_hgt_group_membership_entry);
   7747         if (BCM_FAILURE(rv)) {
   7748             goto error;
   7749         }
   7750 
   7751         /* Disable member state software override */
   7752         rv = READ_DLB_HGT_LINK_CONTROLm(unit, MEM_BLOCK_ANY, 0,
   7753                     &dlb_hgt_link_control_entry);
   7754         if (BCM_FAILURE(rv)) {
   7755             goto error;
   7756         }
   7757         soc_mem_pbmp_field_get(unit, DLB_HGT_LINK_CONTROLm,
   7758                 &dlb_hgt_link_control_entry, SW_OVERRIDE_PORT_MAPf,
   7759                 &override_port_map);
   7760         BCM_PBMP_NEGATE(negated_port_map, port_map);
   7761         BCM_PBMP_AND(override_port_map, negated_port_map);
   7762         soc_mem_pbmp_field_set(unit, DLB_HGT_LINK_CONTROLm,
   7763                 &dlb_hgt_link_control_entry, SW_OVERRIDE_PORT_MAPf,
   7764                 &override_port_map);
   7765         rv = WRITE_DLB_HGT_LINK_CONTROLm(unit, MEM_BLOCK_ALL, 0,
   7766                     &dlb_hgt_link_control_entry);
   7767         if (BCM_FAILURE(rv)) {
   7768             goto error;
   7769         }
   7770     }
   7771 
   7772     /* Find a contiguous region of flow set table that's large
   7773      * enough to hold the requested number of flow sets.
   7774      * The flow set table is allocated in 512-entry blocks.
   7775      */
   7776     m = 0;
   7777 #ifdef BCM_TRIUMPH3_SUPPORT
   7778     if (soc_feature(unit, soc_feature_hg_dlb_member_id)) {
   7779         flowset_mem[m++] = DLB_HGT_FLOWSETm;
   7780         if (soc_mem_is_valid(unit, DLB_HGT_FLOWSET_Xm)
   7781             && soc_mem_is_valid(unit, DLB_HGT_FLOWSET_Ym)) {
   7782             flowset_mem[m++] = DLB_HGT_FLOWSET_Xm;
   7783             flowset_mem[m] = DLB_HGT_FLOWSET_Ym;
   7784         } else {
   7785             flowset_mem[m] = flowset_mem[0];
   7786         }
   7787         flowset_entry_size = sizeof(dlb_hgt_flowset_entry_t);
   7788     } else 
   7789 #endif /* BCM_TRIUMPH3_SUPPORT */
   7790     {
   7791         flowset_mem[m++] = DLB_HGT_FLOWSET_PORTm;
   7792         if (soc_mem_is_valid(unit, DLB_HGT_FLOWSET_PORT_Xm)
   7793             && soc_mem_is_valid(unit, DLB_HGT_FLOWSET_PORT_Ym)) {
   7794             flowset_mem[m++] = DLB_HGT_FLOWSET_PORT_Xm;
   7795             flowset_mem[m] = DLB_HGT_FLOWSET_PORT_Ym;
   7796         } else {
   7797             flowset_mem[m] = flowset_mem[0];
   7798         }
   7799         flowset_entry_size = sizeof(dlb_hgt_flowset_port_entry_t);
   7800     }
   7801     num_blocks = add_info->dynamic_size >> 9;
   7802     total_blocks = soc_mem_index_count(unit, flowset_mem[0]) >> 9;
   7803     max_block_base_ptr = total_blocks - num_blocks;
   7804     for (block_base_ptr = 0;
   7805          block_base_ptr <= max_block_base_ptr;
   7806          block_base_ptr++) {
   7807         /* Check if the contiguous region of flow set table from
   7808          * block_base_ptr to (block_base_ptr + num_blocks - 1) is free. 
   7809          */
   7810         _BCM_HG_DLB_FLOWSET_BLOCK_TEST_RANGE(unit, block_base_ptr, num_blocks,
   7811                 occupied); 
   7812         if (!occupied) {
   7813             break;
   7814         }
   7815     }
   7816     if (block_base_ptr > max_block_base_ptr) {
   7817         /* A contiguous region of the desired size could not be found in
   7818          * flow set table.
   7819          */
   7820         rv = BCM_E_RESOURCE;
   7821         goto error;
   7822     }
   7823 
   7824     /* Configure flow set table */
   7825     entry_base_ptr = block_base_ptr << 9;
   7826     num_entries_per_block = 512;
   7827     alloc_size = num_entries_per_block * flowset_entry_size;
   7828     block_ptr = soc_cm_salloc(unit, alloc_size,
   7829             "Block of DLB_HGT_FLOWSET entries");
   7830     if (NULL == block_ptr) {
   7831         rv = BCM_E_MEMORY;
   7832         goto error;
   7833     }
   7834     sal_memset(block_ptr, 0, alloc_size);
   7835     for (i = 0; i < num_blocks; i++) {
   7836         for (k = 0; k < num_entries_per_block; k++) {
   7837 #ifdef BCM_TRIUMPH3_SUPPORT
   7838             if (soc_feature(unit, soc_feature_hg_dlb_member_id)) {
   7839                 dlb_hgt_flowset_entry_t *flowset_entry;
   7840 
   7841                 flowset_entry = soc_mem_table_idx_to_pointer(unit,
   7842                         DLB_HGT_FLOWSETm, dlb_hgt_flowset_entry_t *,
   7843                         block_ptr, k);
   7844                 soc_DLB_HGT_FLOWSETm_field32_set(unit, flowset_entry, VALIDf, 1);
   7845                 soc_DLB_HGT_FLOWSETm_field32_set(unit, flowset_entry, MEMBER_IDf,
   7846                         member_id_array[(i * num_entries_per_block + k)
   7847                         % add_info->num_ports]);
   7848             } else
   7849 #endif /* BCM_TRIUMPH3_SUPPORT */
   7850             {
   7851                 dlb_hgt_flowset_port_entry_t *flowset_port_entry;
   7852 
   7853                 flowset_port_entry = soc_mem_table_idx_to_pointer(unit,
   7854                         DLB_HGT_FLOWSET_PORTm, dlb_hgt_flowset_port_entry_t *,
   7855                         block_ptr, k);
   7856                 soc_DLB_HGT_FLOWSET_PORTm_field32_set(unit, flowset_port_entry,
   7857                         VALIDf, 1);
   7858                 soc_DLB_HGT_FLOWSET_PORTm_field32_set(unit, flowset_port_entry,
   7859                         PORT_NUMf, add_info->tp[(i * num_entries_per_block + k)
   7860                         % add_info->num_ports]);
   7861             }
   7862         }
   7863         index_min = entry_base_ptr + i * num_entries_per_block;
   7864         index_max = index_min + num_entries_per_block - 1;
   7865         for (m = 1; m < 3; m++) {
   7866             if (flowset_mem[m] == INVALIDm) {
   7867                 continue;
   7868             }
   7869             rv = soc_mem_write_range(unit, flowset_mem[m], MEM_BLOCK_ALL,
   7870                     index_min, index_max, block_ptr);
   7871             if (SOC_FAILURE(rv)) {
   7872                 goto error;
   7873             }
   7874         }
   7875     }
   7876     _BCM_HG_DLB_FLOWSET_BLOCK_USED_SET_RANGE(unit, block_base_ptr, num_blocks);
   7877 
   7878     /* Update Higig DLB group control table */
   7879     sal_memset(&dlb_hgt_group_control_entry, 0,
   7880             sizeof(dlb_hgt_group_control_entry_t));
   7881 #ifdef BCM_TRIDENT2_SUPPORT
   7882     if (soc_mem_field_valid(unit, DLB_HGT_GROUP_CONTROLm, GROUP_ENABLEf)) {
   7883         soc_DLB_HGT_GROUP_CONTROLm_field32_set(unit, &dlb_hgt_group_control_entry,
   7884                 GROUP_ENABLEf, 1);
   7885     }
   7886 #endif /* BCM_TRIDENT2_SUPPORT */
   7887     soc_DLB_HGT_GROUP_CONTROLm_field32_set(unit, &dlb_hgt_group_control_entry,
   7888             ENABLE_OPTIMAL_CANDIDATE_UPDATEf, 1);
   7889     soc_DLB_HGT_GROUP_CONTROLm_field32_set(unit, &dlb_hgt_group_control_entry,
   7890             FLOW_SET_BASEf, entry_base_ptr);
   7891 
   7892     rv = _bcm_trident_hg_dlb_dynamic_size_encode(add_info->dynamic_size,
   7893                                                  &flow_set_size);
   7894     if (SOC_FAILURE(rv)) {
   7895         goto error;
   7896     }
   7897     soc_DLB_HGT_GROUP_CONTROLm_field32_set(unit, &dlb_hgt_group_control_entry,
   7898             FLOW_SET_SIZEf, flow_set_size);
   7899 
   7900     switch (add_info->psc) {
   7901         case BCM_TRUNK_PSC_DYNAMIC:
   7902             dlb_mode = 0;
   7903             break;
   7904         case BCM_TRUNK_PSC_DYNAMIC_ASSIGNED:
   7905             dlb_mode = 1;
   7906             break;
   7907         case BCM_TRUNK_PSC_DYNAMIC_OPTIMAL:
   7908             dlb_mode = 2;
   7909             break;
   7910         default:
   7911             rv = BCM_E_PARAM;
   7912             goto error;
   7913     }
   7914 #ifdef BCM_TRIUMPH3_SUPPORT
   7915     if (soc_mem_field_valid(unit, DLB_HGT_GROUP_CONTROLm,
   7916                 MEMBER_ASSIGNMENT_MODEf)) {
   7917         soc_DLB_HGT_GROUP_CONTROLm_field32_set(unit,
   7918                 &dlb_hgt_group_control_entry,
   7919                 MEMBER_ASSIGNMENT_MODEf, dlb_mode);
   7920     } else
   7921 #endif /* BCM_TRIUMPH3_SUPPORT */
   7922     {
   7923         soc_DLB_HGT_GROUP_CONTROLm_field32_set(unit,
   7924                 &dlb_hgt_group_control_entry,
   7925                 PORT_ASSIGNMENT_MODEf, dlb_mode);
   7926     }
   7927 
   7928     soc_DLB_HGT_GROUP_CONTROLm_field32_set(unit, &dlb_hgt_group_control_entry,
   7929             INACTIVITY_DURATIONf, add_info->dynamic_age);
   7930 
   7931     rv = WRITE_DLB_HGT_GROUP_CONTROLm(unit, MEM_BLOCK_ALL, dlb_id,
   7932                                       &dlb_hgt_group_control_entry);
   7933     if (SOC_FAILURE(rv)) {
   7934         goto error;
   7935     }
   7936 
   7937     if (SOC_MEM_IS_VALID(unit, DLB_HGT_GROUP_CONTROL_Xm)) {
   7938         rv = WRITE_DLB_HGT_GROUP_CONTROL_Xm(unit, MEM_BLOCK_ALL, dlb_id,
   7939                                             &dlb_hgt_group_control_entry);
   7940         if (SOC_FAILURE(rv)) {
   7941             goto error;
   7942         }
   7943     }
   7944     if (SOC_MEM_IS_VALID(unit, DLB_HGT_GROUP_CONTROL_Ym)) {
   7945         rv = WRITE_DLB_HGT_GROUP_CONTROL_Ym(unit, MEM_BLOCK_ALL, dlb_id,
   7946                                             &dlb_hgt_group_control_entry);
   7947         if (SOC_FAILURE(rv)) {
   7948             goto error;
   7949         }
   7950     }
   7951 
   7952     /* Update Higig DLB control table */
   7953     if (soc_mem_is_valid(unit, HGT_DLB_CONTROLm)) {
   7954         sal_memset(&hgt_dlb_control_entry, 0, sizeof(hgt_dlb_control_entry_t));
   7955         soc_HGT_DLB_CONTROLm_field32_set
   7956             (unit, &hgt_dlb_control_entry, DLB_IDf, dlb_id);
   7957         soc_HGT_DLB_CONTROLm_field32_set
   7958             (unit, &hgt_dlb_control_entry, GROUP_ENABLEf, 1);
   7959         rv = WRITE_HGT_DLB_CONTROLm(unit, MEM_BLOCK_ALL, hgtid,
   7960                 &hgt_dlb_control_entry);
   7961         if (SOC_FAILURE(rv)) {
   7962             goto error;
   7963         }
   7964     }
   7965     
   7966     /* Update HG_TRUNK_GROUP */
   7967 #ifdef BCM_TRIDENT2_SUPPORT
   7968     if (soc_mem_field_valid(unit, HG_TRUNK_GROUPm, ENHANCED_HASHING_ENABLEf)) {
   7969         hg_trunk_group_entry_t hg_trunk_group_entry;
   7970 
   7971         rv = READ_HG_TRUNK_GROUPm(unit, MEM_BLOCK_ANY, hgtid,
   7972                 &hg_trunk_group_entry);
   7973         if (SOC_FAILURE(rv)) {
   7974             goto error;
   7975         }
   7976         soc_HG_TRUNK_GROUPm_field32_set(unit, &hg_trunk_group_entry,
   7977                 ENHANCED_HASHING_ENABLEf, 1);
   7978         rv = WRITE_HG_TRUNK_GROUPm(unit, MEM_BLOCK_ALL, hgtid,
   7979                 &hg_trunk_group_entry);
   7980         if (SOC_FAILURE(rv)) {
   7981             goto error;
   7982         }
   7983     }
   7984 #endif /* BCM_TRIDENT2_SUPPORT */
   7985 
   7986 error:
   7987     if (NULL != member_id_array) {
   7988         sal_free(member_id_array);
   7989     }
   7990     if (NULL != member_bitmap) {
   7991         sal_free(member_bitmap);
   7992     }
   7993     if (NULL != override_bitmap) {
   7994         sal_free(override_bitmap);
   7995     }
   7996     if (NULL != block_ptr) { 
   7997         soc_cm_sfree(unit, block_ptr);
   7998     }
   7999     return rv;
   8000 }
   8001 
   8002 /*
   8003  * Function:
   8004  *      _bcm_trident_hg_slb_free_resource
   8005  * Purpose:
   8006  *      Free resources for a Higig static load balancing group.
   8007  * Parameters:
   8008  *      unit  - (IN) SOC unit number. 
   8009  *      hgtid - (IN) Higig trunk group ID.
   8010  * Returns:
   8011  *      BCM_E_xxx
   8012  */
   8013 STATIC int
   8014 _bcm_trident_hg_slb_free_resource(int unit, int hgtid)
   8015 {
   8016     hg_trunk_group_entry_t hg_trunk_group_entry;
   8017     int base_ptr;
   8018     int tg_size;
   8019     int rtag;
   8020     int num_entries;
   8021 
   8022     SOC_IF_ERROR_RETURN
   8023         (READ_HG_TRUNK_GROUPm(unit, MEM_BLOCK_ANY, hgtid,
   8024                               &hg_trunk_group_entry));
   8025     base_ptr = soc_HG_TRUNK_GROUPm_field32_get(unit,
   8026             &hg_trunk_group_entry, BASE_PTRf);
   8027     tg_size = 1 + soc_HG_TRUNK_GROUPm_field32_get(unit,
   8028             &hg_trunk_group_entry, TG_SIZEf);
   8029     rtag = soc_HG_TRUNK_GROUPm_field32_get(unit,
   8030             &hg_trunk_group_entry, RTAGf);
   8031 
   8032     num_entries = tg_size;
   8033     if (rtag >= 1 && rtag <= 6) {
   8034 #ifdef BCM_KATANA_SUPPORT
   8035         if (SOC_IS_KATANAX(unit)) {
   8036             num_entries = _BCM_KATANA_FABRIC_TRUNK_RTAG1_6_MAX_PORTCNT;
   8037         } else
   8038 #endif
   8039         if (soc_feature(unit,
   8040                     soc_feature_rtag1_6_max_portcnt_less_than_rtag7)) { 
   8041             num_entries = _BCM_TD_FABRIC_TRUNK_RTAG1_6_MAX_PORTCNT;
   8042         }
   8043     }
   8044 
   8045     _BCM_HG_TRUNK_MEMBER_USED_CLR_RANGE(unit, base_ptr, num_entries);
   8046 
   8047     return BCM_E_NONE;
   8048 }
   8049 
   8050 /*
   8051  * Function:
   8052  *      _bcm_trident_hg_slb_set
   8053  * Purpose:
   8054  *      Configure a Higig static load balancing group.
   8055  * Parameters:
   8056  *      unit  - (IN) SOC unit number. 
   8057  *      hgtid - (IN) Higig trunk group ID.
   8058  *      add_info - (IN) Pointer to trunk add info structure.
   8059  *      t_info   - (IN) Pointer to trunk info.
   8060  *      trunk_flag   - (IN) 0: hg trunk; 1: cascaded trunk.
   8061  * Returns:
   8062  *      BCM_E_xxx
   8063  */
   8064 STATIC int
   8065 _bcm_trident_hg_slb_set(int unit,
   8066         int hgtid,
   8067         _esw_trunk_add_info_t *add_info,
   8068         trunk_private_t *t_info,
   8069         int trunk_flag)
   8070 {
   8071     int num_entries;
   8072     int max_base_ptr=0;
   8073     int base_ptr;
   8074     SHR_BITDCL occupied;
   8075     int i;
   8076     hg_trunk_member_entry_t hg_trunk_member_entry;
   8077     hg_trunk_group_entry_t  hg_trunk_group_entry;
   8078 #ifdef BCM_TOMAHAWK_SUPPORT
   8079     random_rrlb_hg_trunk_member_entry_t random_rrlb_hg_trunk_member_entry;
   8080     hg_trunk_mode_entry_t  hg_trunk_mode_entry;
   8081     hg_trunk_rr_cnt_entry_t rrlb_cnt_entry;
   8082     uint16 seed=0;
   8083     soc_reg_t reg;
   8084     uint32 rval;
   8085     int pipe;
   8086 #endif
   8087 
   8088     /* Find a contiguous region of HG_TRUNK_MEMBER table that's large
   8089      * enough to hold all of the Higig trunk group's member ports.
   8090      */
   8091 
   8092     num_entries = add_info->num_ports;
   8093 
   8094     /* If RTAG is 1-6, Trident A0 and Katana ignore the TG_SIZE field and assume 
   8095      * the Higig trunk group occupies FABRIC_TRUNK_RTAG1_6_MAX_PORTCNT
   8096      * contiguous entries in HG_TRUNK_MEMBER table.
   8097      */
   8098     if (t_info->rtag >= 1 && t_info->rtag <= 6) {
   8099 #ifdef BCM_KATANA_SUPPORT
   8100         if(SOC_IS_KATANAX(unit)) {
   8101             num_entries = _BCM_KATANA_FABRIC_TRUNK_RTAG1_6_MAX_PORTCNT;
   8102         } else
   8103 #endif
   8104         if (soc_feature(unit,
   8105                     soc_feature_rtag1_6_max_portcnt_less_than_rtag7)) { 
   8106             num_entries = _BCM_TD_FABRIC_TRUNK_RTAG1_6_MAX_PORTCNT;
   8107         }
   8108     } 
   8109 
   8110 #ifdef BCM_TOMAHAWK_SUPPORT
   8111     if (soc_feature(unit, soc_feature_round_robin_load_balance)) {
   8112         if (t_info->psc == BCM_TRUNK_PSC_ROUND_ROBIN) {
   8113             base_ptr = 0;
   8114             max_base_ptr = soc_mem_index_count(unit, RANDOM_RRLB_HG_TRUNK_MEMBERm) - num_entries;
   8115         } else {
   8116             base_ptr = soc_mem_index_count(unit, RANDOM_RRLB_HG_TRUNK_MEMBERm);
   8117             max_base_ptr = soc_mem_index_count(unit, HG_TRUNK_MEMBERm) - num_entries;
   8118         }
   8119     } else 
   8120 #endif
   8121     {
   8122         base_ptr = 0;
   8123         max_base_ptr = soc_mem_index_count(unit, HG_TRUNK_MEMBERm) - num_entries;
   8124     }
   8125 
   8126     for (; base_ptr <= max_base_ptr; base_ptr++) {
   8127         /* Check if the contiguous region of HG_TRUNK_MEMBERm table from
   8128          * index base_ptr to (base_ptr + num_entries - 1) is free. 
   8129          */
   8130         _BCM_HG_TRUNK_MEMBER_TEST_RANGE(unit, base_ptr, num_entries, occupied); 
   8131         if (!occupied) {
   8132             break;
   8133         }
   8134     }
   8135 
   8136 #ifdef BCM_TOMAHAWK_SUPPORT
   8137     if (soc_feature(unit, soc_feature_round_robin_load_balance) &&
   8138         t_info->psc != BCM_TRUNK_PSC_ROUND_ROBIN) {
   8139         if (base_ptr > max_base_ptr) {
   8140             /* start from zero, try again. */
   8141             for (base_ptr = 0; base_ptr <= max_base_ptr; base_ptr++) {
   8142                 _BCM_HG_TRUNK_MEMBER_TEST_RANGE(unit, base_ptr, num_entries, occupied);
   8143                 if (!occupied) {
   8144                     break;
   8145                 }
   8146             }
   8147         }
   8148     }
   8149 #endif
   8150 
   8151     if (base_ptr > max_base_ptr) {
   8152         /* A contiguous region of the desired size could not be found in
   8153          * HG_TRUNK_MEMBER table.
   8154          */
   8155         return BCM_E_RESOURCE;
   8156     }
   8157 
   8158     for (i = 0; i < num_entries; i++) {
   8159         sal_memset(&hg_trunk_member_entry, 0, sizeof(hg_trunk_member_entry_t));
   8160 #if defined(BCM_KATANA2_SUPPORT)
   8161         if (SOC_IS_KATANA2(unit)) {
   8162             soc_HG_TRUNK_MEMBERm_field32_set(unit, &hg_trunk_member_entry,
   8163                     PHYSICAL_PORTf, add_info->tp[i % add_info->num_ports]);
   8164             soc_HG_TRUNK_MEMBERm_field32_set(unit, &hg_trunk_member_entry,
   8165                     PP_PORTf, add_info->tp[i % add_info->num_ports]);
   8166         } else 
   8167 #endif /*  (defined(BCM_KATANA2_SUPPORT)  */
   8168         {
   8169 
   8170 #ifdef BCM_TOMAHAWK_SUPPORT
   8171            if (t_info->psc == BCM_TRUNK_PSC_ROUND_ROBIN) {
   8172                if (soc_feature(unit, soc_feature_round_robin_load_balance)) {
   8173                    sal_memset(&random_rrlb_hg_trunk_member_entry, 0, sizeof(random_rrlb_hg_trunk_member_entry_t));
   8174                    soc_RANDOM_RRLB_HG_TRUNK_MEMBERm_field32_set(unit, &random_rrlb_hg_trunk_member_entry,
   8175                     PORT_NUMf, add_info->tp[i % add_info->num_ports]);
   8176                    SOC_IF_ERROR_RETURN
   8177                      (WRITE_RANDOM_RRLB_HG_TRUNK_MEMBERm(unit, MEM_BLOCK_ALL, base_ptr + i,
   8178                                     &random_rrlb_hg_trunk_member_entry)); 
   8179                }
   8180            } else if ((t_info->psc == BCM_TRUNK_PSC_RANDOMIZED)) {
   8181                if (soc_feature(unit, soc_feature_randomized_load_balance)) {
   8182                    /* Configure HG Rand LB Seed */
   8183                    seed = (sal_rand()) % 0xFFFF;
   8184                    rval = 0;
   8185                    for (pipe = 0; pipe < NUM_PIPE(unit); pipe++) {
   8186                       reg = SOC_REG_UNIQUE_ACC(unit, HG_TRUNK_RAND_LB_SEEDr)[pipe];
   8187                       soc_reg_field_set(unit, reg, &rval, SEEDf, seed);
   8188                       SOC_IF_ERROR_RETURN
   8189                          (soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval));
   8190                    }
   8191                }
   8192            }
   8193 #endif
   8194 
   8195            soc_HG_TRUNK_MEMBERm_field32_set(unit, &hg_trunk_member_entry,
   8196                     PORT_NUMf, add_info->tp[i % add_info->num_ports]);
   8197         }
   8198 
   8199         SOC_IF_ERROR_RETURN
   8200                  (WRITE_HG_TRUNK_MEMBERm(unit, MEM_BLOCK_ALL, base_ptr + i,
   8201                                     &hg_trunk_member_entry)); 
   8202     }
   8203 
   8204     /* Set hg_trunk_member_bitmap */
   8205     _BCM_HG_TRUNK_MEMBER_USED_SET_RANGE(unit, base_ptr, num_entries);
   8206 
   8207     /* Update Higig trunk base_ptr, tg_size, and rtag */
   8208     SOC_IF_ERROR_RETURN(READ_HG_TRUNK_GROUPm(unit, MEM_BLOCK_ANY, hgtid,
   8209             &hg_trunk_group_entry));
   8210     soc_HG_TRUNK_GROUPm_field32_set
   8211         (unit, &hg_trunk_group_entry, BASE_PTRf, base_ptr);
   8212     soc_HG_TRUNK_GROUPm_field32_set
   8213         (unit, &hg_trunk_group_entry, TG_SIZEf, add_info->num_ports-1);
   8214     soc_HG_TRUNK_GROUPm_field32_set
   8215         (unit, &hg_trunk_group_entry, RTAGf, t_info->rtag);
   8216 #if defined(BCM_HGPROXY_COE_SUPPORT)
   8217     if (soc_mem_field_valid(unit, HG_TRUNK_GROUPm, ENTRY_TYPEf) &&
   8218         (trunk_flag == 1)) {
   8219         /*cascaded trunk*/
   8220         soc_HG_TRUNK_GROUPm_field32_set
   8221             (unit, &hg_trunk_group_entry, ENTRY_TYPEf, 1);
   8222     }
   8223 #endif
   8224     SOC_IF_ERROR_RETURN
   8225         (WRITE_HG_TRUNK_GROUPm(unit, MEM_BLOCK_ALL, hgtid, &hg_trunk_group_entry));
   8226 
   8227 #ifdef BCM_TOMAHAWK_SUPPORT
   8228     if (t_info->psc == BCM_TRUNK_PSC_ROUND_ROBIN) {
   8229         if (soc_feature(unit, soc_feature_round_robin_load_balance)) {
   8230             soc_HG_TRUNK_MODEm_field32_set(unit, &hg_trunk_mode_entry, HG_TRUNK_LB_MODEf, 0x3);
   8231             SOC_IF_ERROR_RETURN
   8232               (WRITE_HG_TRUNK_MODEm(unit, MEM_BLOCK_ALL, hgtid, &hg_trunk_mode_entry));
   8233 
   8234             BCM_IF_ERROR_RETURN(READ_HG_TRUNK_RR_CNTm(unit, MEM_BLOCK_ANY,
   8235                    hgtid, &rrlb_cnt_entry));
   8236             soc_HG_TRUNK_RR_CNTm_field32_set(unit, &rrlb_cnt_entry,
   8237                            RR_CNTf, 0);
   8238             BCM_IF_ERROR_RETURN(WRITE_HG_TRUNK_RR_CNTm(unit, MEM_BLOCK_ALL,
   8239                            hgtid, &rrlb_cnt_entry));
   8240 
   8241         }
   8242     } else if ((t_info->psc == BCM_TRUNK_PSC_RANDOMIZED)) {
   8243          if (soc_feature(unit, soc_feature_randomized_load_balance)) {
   8244            soc_HG_TRUNK_MODEm_field32_set(unit, &hg_trunk_mode_entry, HG_TRUNK_LB_MODEf, 0x2);
   8245            seed = (sal_rand()) % 0xF;
   8246            soc_HG_TRUNK_MODEm_field32_set(unit, &hg_trunk_mode_entry, OFFSET_RANDOM_LBf, seed);
   8247            SOC_IF_ERROR_RETURN
   8248               (WRITE_HG_TRUNK_MODEm(unit, MEM_BLOCK_ALL, hgtid, &hg_trunk_mode_entry));
   8249          }
   8250     } else if ((t_info->psc != BCM_TRUNK_PSC_DYNAMIC) &&
   8251                (t_info->psc != BCM_TRUNK_PSC_DYNAMIC_ASSIGNED) &&
   8252                (t_info->psc != BCM_TRUNK_PSC_DYNAMIC_OPTIMAL) &&
   8253                (t_info->psc != BCM_TRUNK_PSC_DYNAMIC_RESILIENT)) {
   8254         if (soc_mem_field_valid(unit, HG_TRUNK_MODEm, HG_TRUNK_LB_MODEf)) {
   8255             soc_HG_TRUNK_MODEm_field32_set(unit, &hg_trunk_mode_entry, HG_TRUNK_LB_MODEf, 0x0);
   8256             SOC_IF_ERROR_RETURN
   8257               (WRITE_HG_TRUNK_MODEm(unit, MEM_BLOCK_ALL, hgtid, &hg_trunk_mode_entry));
   8258         }
   8259     }
   8260 #endif
   8261 
   8262     return BCM_E_NONE;
   8263 }
   8264 
   8265 /*
   8266  * Function:
   8267  *      bcm_trident_trunk_fabric_port_set
   8268  * Purpose:
   8269  *      Update port table for Higig trunks.
   8270  * Parameters:
   8271  *      unit      - (IN) SOC unit number. 
   8272  *      hgtid     - (IN) Higig trunk group ID.
   8273  *      old_ports - (IN) Higig trunk group's old port bitmap.
   8274  *      new_ports - (IN) Higig trunk group's new port bitmap.
   8275  * Returns:
   8276  *      BCM_E_xxx
   8277  */
   8278 STATIC int
   8279 _bcm_trident_trunk_fabric_port_set(int unit,
   8280         bcm_trunk_t hgtid,
   8281         pbmp_t old_ports,
   8282         pbmp_t new_ports)
   8283 {
   8284     bcm_port_t		port;
   8285     bcm_pbmp_t      pbm;
   8286     int			ctid;
   8287 
   8288     BCM_PBMP_ASSIGN(pbm, PBMP_HG_ALL(unit));
   8289     BCM_PBMP_OR(pbm, PBMP_ST_ALL(unit));
   8290     PBMP_ITER(pbm, port) {
   8291         if (BCM_PBMP_MEMBER(new_ports, port)) {
   8292             ctid = hgtid;
   8293         } else if (BCM_PBMP_MEMBER(old_ports, port)) {
   8294             ctid = -1;
   8295             if (soc_feature(unit, soc_feature_hg_trunk_failover)) {
   8296                 /* Clear HW failover info for deleted port */
   8297                 BCM_IF_ERROR_RETURN
   8298                     (_bcm_trident_trunk_hwfailover_set(unit, hgtid, TRUE,
   8299                                                        port, -1,
   8300                                                        BCM_TRUNK_PSC_DEFAULT,
   8301                                                        0, 0, NULL, NULL));
   8302             }
   8303         } else {
   8304             continue;
   8305         }
   8306         BCM_IF_ERROR_RETURN
   8307             (_bcm_esw_port_config_set(unit, port,
   8308                                       _bcmPortHigigTrunkId, ctid));
   8309     }
   8310     if (soc_feature(unit, soc_feature_linkphy_coe) &&
   8311         BCM_PBMP_NOT_NULL(PBMP_LP_ALL(unit))) {
   8312         PBMP_LP_ITER(unit, port) {
   8313             if (BCM_PBMP_MEMBER(old_ports, port)) {
   8314                 if (soc_feature(unit, soc_feature_hg_trunk_failover)) {
   8315                     /* Clear HW failover info for deleted port */
   8316                     BCM_IF_ERROR_RETURN
   8317                         (_bcm_trident_trunk_hwfailover_set(unit, hgtid, TRUE,
   8318                                                        port, -1,
   8319                                                        BCM_TRUNK_PSC_DEFAULT,
   8320                                                        0, 0, NULL, NULL));
   8321                 }
   8322             }
   8323             BCM_IF_ERROR_RETURN
   8324                 (_bcm_esw_port_config_set(unit, port,
   8325                                       _bcmPortHigigTrunkId, -1));
   8326         }
   8327     }
   8328     if ((soc_feature(unit, soc_feature_subtag_coe) || 
   8329          soc_feature(unit, soc_feature_hgproxy_subtag_coe)) &&
   8330         BCM_PBMP_NOT_NULL(PBMP_SUBTAG_ALL(unit))) {
   8331         PBMP_SUBTAG_ITER(unit, port) {
   8332             if (BCM_PBMP_MEMBER(old_ports, port)) {
   8333                 if (soc_feature(unit, soc_feature_hg_trunk_failover)) {
   8334                     /* Clear HW failover info for deleted port */
   8335                     BCM_IF_ERROR_RETURN
   8336                         (_bcm_trident_trunk_hwfailover_set(unit, hgtid, TRUE,
   8337                                                        port, -1,
   8338                                                        BCM_TRUNK_PSC_DEFAULT,
   8339                                                        0, 0, NULL, NULL));
   8340                 }
   8341             }
   8342             BCM_IF_ERROR_RETURN
   8343                 (_bcm_esw_port_config_set(unit, port,
   8344                                       _bcmPortHigigTrunkId, -1));
   8345         }
   8346     }
   8347     return BCM_E_NONE;
   8348 }
   8349 
   8350 /*
   8351  * Function:
   8352  *      bcm_trident_trunk_fabric_modify
   8353  * Purpose:
   8354  *      Set, add or delete trunk members.
   8355  * Parameters:
   8356  *      unit     - (IN) SOC unit number. 
   8357  *      hgtid    - (IN) Higig trunk group ID.
   8358  *      add_info - (IN) Pointer to trunk add info structure.
   8359  *      t_info   - (IN) Pointer to trunk info.
   8360  *      op       - (IN) Type of operation: TRUNK_MEMBER_OP_SET, ADD or DELETE.
   8361  *      member   - (IN) Member to add or delete.
   8362  * Returns:
   8363  *      BCM_E_xxx
   8364  */
   8365 STATIC int
   8366 _bcm_trident_trunk_fabric_modify(int unit,
   8367         bcm_trunk_t hgtid,
   8368         _esw_trunk_add_info_t *add_info,
   8369         trunk_private_t *t_info,
   8370         trunk_private_t *stored_info,
   8371         int op,
   8372         bcm_trunk_member_t *member)
   8373 {
   8374     bcm_trunk_chip_info_t chip_info;
   8375     int          i, local_id;
   8376     bcm_gport_t  gport;
   8377     bcm_trunk_t  trunk, tid;
   8378     pbmp_t       old_trunk_pbmp, new_trunk_pbmp;
   8379     hg_trunk_bitmap_entry_t hg_trunk_bitmap_entry;
   8380     int          auto_include_disable = 0;
   8381     int          rv = BCM_E_NONE;
   8382     int          trunk_flag = 0; /*hg trunk or cascaded trunk*/
   8383 #if defined(BCM_HGPROXY_COE_SUPPORT)
   8384     bcm_port_t local_port;
   8385 #endif
   8386 
   8387     BCM_IF_ERROR_RETURN(bcm_esw_trunk_chip_info_get(unit, &chip_info));
   8388 
   8389     if (add_info->num_ports > chip_info.trunk_fabric_ports_max ||
   8390             add_info->num_ports < 1) {
   8391         return BCM_E_PARAM;
   8392     }
   8393  
   8394     /* On Trident, the max number of trunk members for RTAG 1-6 is smaller
   8395      * than for RTAG 7.
   8396      */
   8397     if (soc_feature(unit, soc_feature_rtag1_6_max_portcnt_less_than_rtag7)) { 
   8398         if (t_info->rtag >= 1 && t_info->rtag <= 6) {
   8399             if (add_info->num_ports > _BCM_TD_FABRIC_TRUNK_RTAG1_6_MAX_PORTCNT) {
   8400                 return BCM_E_PARAM;
   8401             }
   8402         }
   8403     }
   8404 
   8405     tid = hgtid + chip_info.trunk_group_count;
   8406 
   8407     SOC_PBMP_CLEAR(new_trunk_pbmp);
   8408     for (i = 0; i < add_info->num_ports; i++) {
   8409         /* if given modid is -1 devport was used */
   8410         if (BCM_MODID_INVALID != add_info->tm[i]) {
   8411             BCM_GPORT_MODPORT_SET(gport, add_info->tm[i], add_info->tp[i]);
   8412 
   8413             BCM_IF_ERROR_RETURN
   8414                 (_bcm_esw_gport_resolve(unit, gport, &add_info->tm[i],
   8415                                         &add_info->tp[i], &trunk, &local_id));
   8416 #if defined(BCM_HGPROXY_COE_SUPPORT)
   8417             BCM_IF_ERROR_RETURN
   8418                 (bcm_esw_port_local_get(unit, gport, &local_port));
   8419             /*Cascaded port*/
   8420             if (IS_SUBTAG_PORT(unit, local_port) &&
   8421                 soc_feature(unit, soc_feature_hgproxy_subtag_coe)) {
   8422                 /*cascaded trunk*/
   8423                 trunk_flag = 1;
   8424             }
   8425 #endif
   8426         }
   8427 
   8428         if (!SOC_PORT_VALID(unit, add_info->tp[i])) {
   8429             return BCM_E_PORT;
   8430         }
   8431         if (!(IS_ST_PORT(unit, add_info->tp[i]) ||
   8432               (trunk_flag == 1))) {
   8433             return BCM_E_PARAM;
   8434         }
   8435         SOC_PBMP_PORT_ADD(new_trunk_pbmp, add_info->tp[i]);
   8436     }
   8437 
   8438     /* Configure static load balancing */
   8439     if (t_info->in_use) {
   8440         BCM_IF_ERROR_RETURN(_bcm_trident_hg_slb_free_resource(unit, hgtid));
   8441     }
   8442     BCM_IF_ERROR_RETURN(_bcm_trident_hg_slb_set(unit, hgtid, add_info,
   8443                     t_info, trunk_flag));
   8444 
   8445     /* Configure dynamic load balancing, if enabled */
   8446     if (soc_feature(unit, soc_feature_hg_dlb) &&
   8447         !soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) {
   8448         if (t_info->in_use) {
   8449             BCM_IF_ERROR_RETURN(_bcm_trident_hg_dlb_free_resource(unit, hgtid));
   8450         } 
   8451         BCM_IF_ERROR_RETURN(_bcm_trident_hg_dlb_set(unit, hgtid, add_info));
   8452     }
   8453 
   8454 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT)
   8455     /* Configure dynamic load balancing */
   8456     if (soc_feature(unit, soc_feature_hg_dlb) &&
   8457         soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) {
   8458         if (t_info->in_use) {
   8459             BCM_IF_ERROR_RETURN(bcm_th2_hgt_lag_dlb_free_resource(unit, hgtid, 1));
   8460         }
   8461         BCM_IF_ERROR_RETURN(bcm_th2_hgt_lag_dlb_set(unit, hgtid, 1, add_info,
   8462             add_info->num_ports, add_info->tm, add_info->tp,
   8463             add_info->dynamic_scaling_factor, add_info->dynamic_load_weight,
   8464             add_info->dynamic_queue_size_weight));
   8465     }
   8466 #endif /* BCM_TOMAHAWK2_SUPPORT */
   8467 
   8468 #ifdef BCM_TRIDENT2_SUPPORT
   8469     /* Configure resilient hashing, if enabled */
   8470     if (soc_feature(unit, soc_feature_hg_resilient_hash)) {
   8471         if (op == TRUNK_MEMBER_OP_SET) {
   8472             if ((stored_info->in_use) &&
   8473                 (add_info->psc == BCM_TRUNK_PSC_DYNAMIC_RESILIENT) &&
   8474                 (stored_info->psc == BCM_TRUNK_PSC_DYNAMIC_RESILIENT) &&
   8475                 (add_info->dynamic_size != 0) &&
   8476                 (add_info->dynamic_size == stored_info->dynamic_size)) {
   8477                 BCM_IF_ERROR_RETURN(bcm_td2_hg_rh_replace(unit, hgtid, add_info,
   8478                     MEMBER_INFO(unit, tid).num_ports,
   8479                     MEMBER_INFO(unit, tid).modport,
   8480                     MEMBER_INFO(unit, tid).member_flags));
   8481             } else {
   8482                 if (t_info->in_use) {
   8483                     BCM_IF_ERROR_RETURN(bcm_td2_hg_rh_free_resource(unit, hgtid));
   8484                 }
   8485                 if (add_info->psc == BCM_TRUNK_PSC_DYNAMIC_RESILIENT) {
   8486                     BCM_IF_ERROR_RETURN(bcm_td2_hg_rh_set(unit, hgtid, add_info));
   8487                 }
   8488             }
   8489         } else if (op == TRUNK_MEMBER_OP_ADD) {
   8490             if (add_info->psc == BCM_TRUNK_PSC_DYNAMIC_RESILIENT) {
   8491                 BCM_IF_ERROR_RETURN(bcm_td2_hg_rh_add(unit, hgtid, add_info,
   8492                             member));
   8493             }
   8494         } else if (op == TRUNK_MEMBER_OP_DELETE) {
   8495             if (add_info->psc == BCM_TRUNK_PSC_DYNAMIC_RESILIENT) {
   8496                 BCM_IF_ERROR_RETURN(bcm_td2_hg_rh_delete(unit, hgtid, add_info,
   8497                             member));
   8498             }
   8499         } else {
   8500             return BCM_E_PARAM;
   8501         }
   8502     }
   8503 #endif /* BCM_TRIDENT2_SUPPORT */
   8504 
   8505     /* Update Higig trunk bitmap */
   8506 
   8507     SOC_IF_ERROR_RETURN
   8508         (READ_HG_TRUNK_BITMAPm(unit, MEM_BLOCK_ANY, hgtid, &hg_trunk_bitmap_entry));
   8509     SOC_PBMP_CLEAR(old_trunk_pbmp);
   8510     soc_mem_pbmp_field_get(unit, HG_TRUNK_BITMAPm, &hg_trunk_bitmap_entry,
   8511             HIGIG_TRUNK_BITMAPf, &old_trunk_pbmp);
   8512 
   8513     soc_mem_pbmp_field_set(unit, HG_TRUNK_BITMAPm, &hg_trunk_bitmap_entry,
   8514             HIGIG_TRUNK_BITMAPf, &new_trunk_pbmp);
   8515     SOC_IF_ERROR_RETURN
   8516         (WRITE_HG_TRUNK_BITMAPm(unit, MEM_BLOCK_ALL, hgtid, &hg_trunk_bitmap_entry));
   8517 
   8518     BCM_IF_ERROR_RETURN
   8519         (_bcm_trident_trunk_fabric_port_set(unit,
   8520                                             hgtid,
   8521                                             old_trunk_pbmp,
   8522                                             new_trunk_pbmp));
   8523 
   8524     if (soc_feature(unit, soc_feature_hg_trunk_failover)) {
   8525         BCM_IF_ERROR_RETURN
   8526             (_bcm_trident_trunk_failover_set(unit, hgtid, TRUE, add_info));
   8527     }
   8528 
   8529     BCM_IF_ERROR_RETURN
   8530         (_bcm_trident_trunk_swfailover_fabric_set(unit,
   8531                                                   hgtid,
   8532                                                   t_info->rtag,
   8533                                                   new_trunk_pbmp));
   8534 
   8535     if (MEMBER_INFO(unit, tid).modport) {
   8536         sal_free(MEMBER_INFO(unit, tid).modport);
   8537         MEMBER_INFO(unit, tid).modport = NULL;
   8538     }
   8539     if (MEMBER_INFO(unit, tid).member_flags) {
   8540         sal_free(MEMBER_INFO(unit, tid).member_flags);
   8541         MEMBER_INFO(unit, tid).member_flags = NULL;
   8542     }
   8543 
   8544     MEMBER_INFO(unit, tid).modport = sal_alloc(
   8545             sizeof(uint16) * add_info->num_ports, "member info modport");
   8546     if (NULL == MEMBER_INFO(unit, tid).modport) {
   8547         return BCM_E_MEMORY;
   8548     }
   8549 
   8550     MEMBER_INFO(unit, tid).member_flags = sal_alloc(
   8551             sizeof(uint32) * add_info->num_ports, "member info flags");
   8552     if (NULL == MEMBER_INFO(unit, tid).member_flags) {
   8553         sal_free(MEMBER_INFO(unit, tid).modport);
   8554         MEMBER_INFO(unit, tid).modport = NULL;
   8555         return BCM_E_MEMORY;
   8556     }
   8557 
   8558     for (i = 0; i < add_info->num_ports; i++) {
   8559         /* Save new trunk member info */
   8560         MEMBER_INFO(unit, tid).modport[i] = add_info->tp[i];
   8561         MEMBER_INFO(unit, tid).member_flags[i] = add_info->member_flags[i];
   8562     }
   8563     MEMBER_INFO(unit, tid).num_ports = add_info->num_ports;
   8564 
   8565     /* On Trident, changing Higig trunk membership requires
   8566      * updating the modport map table.
   8567      */ 
   8568     rv = bcm_esw_switch_control_get(unit,
   8569             bcmSwitchFabricTrunkAutoIncludeDisable, &auto_include_disable);
   8570     if (BCM_FAILURE(rv)) {
   8571         if (BCM_E_UNAVAIL == rv) {
   8572             auto_include_disable = 0;
   8573         } else {
   8574             return rv;
   8575         }
   8576     }
   8577     if (!auto_include_disable) {
   8578         BCM_IF_ERROR_RETURN(bcm_td_stk_modport_map_update(unit));
   8579     }
   8580 
   8581     return BCM_E_NONE;
   8582 }
   8583 
   8584 /*
   8585  * Function:
   8586  *      bcm_trident_trunk_fabric_destroy
   8587  * Purpose:
   8588  *      Remove fabric trunk group.
   8589  * Parameters:
   8590  *      unit     - (IN) SOC unit number. 
   8591  *      hgtid    - (IN) Higig trunk group ID.
   8592  *      t_info   - (IN) Pointer to trunk info.
   8593  * Returns:
   8594  *      BCM_E_xxx
   8595  */
   8596 STATIC int
   8597 _bcm_trident_trunk_fabric_destroy(int unit,
   8598         bcm_trunk_t hgtid,
   8599         trunk_private_t *t_info)
   8600 {
   8601     bcm_trunk_chip_info_t chip_info;
   8602     pbmp_t old_trunk_pbmp, new_trunk_pbmp;
   8603     hg_trunk_bitmap_entry_t hg_trunk_bitmap_entry;
   8604     bcm_trunk_t tid;
   8605     int auto_include_disable = 0;
   8606     int rv = BCM_E_NONE;
   8607 
   8608     BCM_IF_ERROR_RETURN(bcm_esw_trunk_chip_info_get(unit, &chip_info));
   8609     tid = hgtid + chip_info.trunk_group_count;
   8610 
   8611     /* Clear DLB configuration */
   8612     if (soc_feature(unit, soc_feature_hg_dlb) &&
   8613         !soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) {
   8614         BCM_IF_ERROR_RETURN(_bcm_trident_hg_dlb_free_resource(unit, hgtid));
   8615     }
   8616 
   8617 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT)
   8618     if (soc_feature(unit, soc_feature_hg_dlb) &&
   8619         soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) {
   8620         BCM_IF_ERROR_RETURN(bcm_th2_hgt_lag_dlb_free_resource(unit, hgtid, 1));
   8621     }
   8622 #endif /* BCM_TOMAHAWK2_SUPPORT */
   8623 
   8624 #ifdef BCM_TRIDENT2_SUPPORT
   8625     /* Clear resilient hashing configuration */
   8626     if (soc_feature(unit, soc_feature_hg_resilient_hash)) {
   8627         BCM_IF_ERROR_RETURN(bcm_td2_hg_rh_free_resource(unit, hgtid));
   8628     }
   8629 #endif /* BCM_TRIDENT2_SUPPORT */
   8630 
   8631     BCM_IF_ERROR_RETURN(_bcm_trident_hg_slb_free_resource(unit, hgtid));
   8632 
   8633     if (MEMBER_INFO(unit, tid).modport) {
   8634         sal_free(MEMBER_INFO(unit, tid).modport);
   8635         MEMBER_INFO(unit, tid).modport = NULL;
   8636     }
   8637     if (MEMBER_INFO(unit, tid).member_flags) {
   8638         sal_free(MEMBER_INFO(unit, tid).member_flags);
   8639         MEMBER_INFO(unit, tid).member_flags = NULL;
   8640     }
   8641     MEMBER_INFO(unit, tid).num_ports = 0;
   8642 
   8643     /* Get old Higig trunk bitmap */
   8644     SOC_IF_ERROR_RETURN
   8645         (READ_HG_TRUNK_BITMAPm(unit, MEM_BLOCK_ANY, hgtid, &hg_trunk_bitmap_entry));
   8646     SOC_PBMP_CLEAR(old_trunk_pbmp);
   8647     soc_mem_pbmp_field_get(unit, HG_TRUNK_BITMAPm, &hg_trunk_bitmap_entry,
   8648             HIGIG_TRUNK_BITMAPf, &old_trunk_pbmp);
   8649 
   8650     /* Clear Higig trunk bitmap */
   8651     SOC_IF_ERROR_RETURN
   8652         (WRITE_HG_TRUNK_BITMAPm(unit, MEM_BLOCK_ALL, hgtid,
   8653                                 soc_mem_entry_null(unit, HG_TRUNK_BITMAPm)));
   8654 
   8655     /* Clear Higig trunk group table */
   8656     SOC_IF_ERROR_RETURN
   8657         (WRITE_HG_TRUNK_GROUPm(unit, MEM_BLOCK_ALL, hgtid,
   8658                                soc_mem_entry_null(unit, HG_TRUNK_GROUPm)));
   8659 
   8660     SOC_PBMP_CLEAR(new_trunk_pbmp);
   8661 
   8662     BCM_IF_ERROR_RETURN
   8663         (_bcm_trident_trunk_fabric_port_set(unit,
   8664                                             hgtid,
   8665                                             old_trunk_pbmp,
   8666                                             new_trunk_pbmp));
   8667 
   8668     if (soc_feature(unit, soc_feature_hg_trunk_failover)) {
   8669         BCM_IF_ERROR_RETURN
   8670             (_bcm_trident_trunk_failover_set(unit, hgtid, TRUE, NULL));
   8671     }
   8672 
   8673     BCM_IF_ERROR_RETURN
   8674         (_bcm_trident_trunk_swfailover_fabric_set(unit,
   8675                                                   hgtid,
   8676                                                   0,
   8677                                                   new_trunk_pbmp));
   8678 
   8679     /* On Trident, changing Higig trunk membership requires
   8680      * updating the modport map table.
   8681      */ 
   8682     rv = bcm_esw_switch_control_get(unit,
   8683             bcmSwitchFabricTrunkAutoIncludeDisable, &auto_include_disable);
   8684     if (BCM_FAILURE(rv)) {
   8685         if (BCM_E_UNAVAIL == rv) {
   8686             auto_include_disable = 0;
   8687         } else {
   8688             return rv;
   8689         }
   8690     }
   8691     if (!auto_include_disable) {
   8692         BCM_IF_ERROR_RETURN(bcm_td_stk_modport_map_update(unit));
   8693     }
   8694 
   8695     t_info->in_use = FALSE;
   8696     return BCM_E_NONE;
   8697 }
   8698 
   8699 /*
   8700  * Function:
   8701  *	bcm_trident_trunk_fabric_get
   8702  * Purpose:
   8703  *      Return a fabric trunk information of given fabric trunk ID.
   8704  *      If t_data->num_ports = 0, return number of trunk members in
   8705  *      t_data->num_ports.
   8706  * Parameters:
   8707  *      unit   - (IN) StrataSwitch PCI device unit number (driver internal).
   8708  *      tid    - (IN) Trunk ID.
   8709  *      t_data - (OUT) Place to store returned trunk add info.
   8710  *      t_info - (IN) Trunk info.
   8711  * Returns:
   8712  *      BCM_E_NONE              Success.
   8713  *      BCM_E_XXX
   8714  */
   8715 STATIC int
   8716 _bcm_trident_trunk_fabric_get(int unit,
   8717         bcm_trunk_t hgtid,
   8718         _esw_trunk_add_info_t *t_data,
   8719         trunk_private_t *t_info)
   8720 {
   8721     bcm_trunk_chip_info_t chip_info;
   8722     bcm_trunk_t tid;
   8723     bcm_module_t modid;
   8724     bcm_port_t port;
   8725     int i;
   8726     uint32 quantize_control_reg;
   8727     int profile_ptr;
   8728 
   8729     BCM_IF_ERROR_RETURN(bcm_esw_trunk_chip_info_get(unit, &chip_info));
   8730     tid = hgtid + chip_info.trunk_group_count;
   8731 
   8732     if (t_data->num_ports == 0) {
   8733         t_data->num_ports = MEMBER_INFO(unit, tid).num_ports;
   8734     } else {
   8735         if (MEMBER_INFO(unit, tid).num_ports <= t_data->num_ports) {
   8736             t_data->num_ports = MEMBER_INFO(unit, tid).num_ports;
   8737         } 
   8738 
   8739         if (BCM_FAILURE(bcm_esw_stk_my_modid_get(unit, &modid))) {
   8740             modid = 0;
   8741         }
   8742 
   8743         for (i = 0; i < t_data->num_ports; i++) {
   8744             port = MEMBER_INFO(unit, tid).modport[i] & 0xff;
   8745             BCM_IF_ERROR_RETURN(_bcm_esw_stk_modmap_map(unit,
   8746                         BCM_STK_MODMAP_GET, modid, port,
   8747                         &t_data->tm[i], &t_data->tp[i]));
   8748 
   8749             /* Get per trunk member DLB attributes */
   8750             t_data->dynamic_scaling_factor[i] = 0;
   8751             t_data->dynamic_load_weight[i] = 0;
   8752             t_data->dynamic_queue_size_weight[i] = 0;
   8753             if ((t_data->psc == BCM_TRUNK_PSC_DYNAMIC) ||
   8754                 (t_data->psc == BCM_TRUNK_PSC_DYNAMIC_ASSIGNED) ||
   8755                 (t_data->psc == BCM_TRUNK_PSC_DYNAMIC_OPTIMAL)) {
   8756 
   8757 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT)
   8758                 if (soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) {
   8759                     BCM_IF_ERROR_RETURN(bcm_th2_hgt_lag_dlb_member_attr_get(unit,
   8760                             port,
   8761                             &t_data->dynamic_scaling_factor[i],
   8762                             &t_data->dynamic_load_weight[i],
   8763                             &t_data->dynamic_queue_size_weight[i]));
   8764                 } else
   8765 #endif /* BCM_TOMAHAWK2_SUPPORT */
   8766 
   8767 #ifdef BCM_TRIUMPH3_SUPPORT 
   8768                 if (soc_feature(unit, soc_feature_hg_dlb_member_id)) {
   8769                     BCM_IF_ERROR_RETURN(_bcm_tr3_hg_dlb_member_attr_get(unit,
   8770                                 port,
   8771                                 &t_data->dynamic_scaling_factor[i],
   8772                                 &t_data->dynamic_load_weight[i]));
   8773                 } else
   8774 #endif /* BCM_TRIUMPH3_SUPPORT */
   8775                 {
   8776                     SOC_IF_ERROR_RETURN(READ_DLB_HGT_QUANTIZE_CONTROLr(unit,
   8777                                 port, &quantize_control_reg));
   8778                     t_data->dynamic_scaling_factor[i] = soc_reg_field_get(unit,
   8779                             DLB_HGT_QUANTIZE_CONTROLr, quantize_control_reg,
   8780                             PORT_LOADING_THRESHOLD_SCALING_FACTORf);
   8781                     profile_ptr = soc_reg_field_get(unit, 
   8782                             DLB_HGT_QUANTIZE_CONTROLr, quantize_control_reg,
   8783                             PORT_QUALITY_MAPPING_PROFILE_PTRf);
   8784                     t_data->dynamic_load_weight[i] =
   8785                         HG_DLB_INFO(unit)->hg_dlb_load_weight[profile_ptr];
   8786                 }
   8787             } 
   8788         }
   8789     }
   8790 
   8791     return BCM_E_NONE;
   8792 }
   8793 
   8794 /*
   8795  * Function:
   8796  *      _bcm_trident_trunk_fabric_find
   8797  * Description:
   8798  *      Get fabric trunk id that contains the given Higig port
   8799  * Parameters:
   8800  *      unit    - Unit number
   8801  *      port    - Port number
   8802  *      tid     - (OUT) Fabric trunk id
   8803  * Returns:
   8804  *      BCM_E_xxxx
   8805  */
   8806 int
   8807 _bcm_trident_trunk_fabric_find(int unit,
   8808         bcm_port_t port,
   8809         int *tid)
   8810 {
   8811     bcm_trunk_chip_info_t chip_info;
   8812     int                   num_hg_trunk_groups;
   8813     int                   hgtid;
   8814     hg_trunk_bitmap_entry_t hg_trunk_bitmap_entry;
   8815     pbmp_t                trunk_pbmp;
   8816 
   8817     BCM_IF_ERROR_RETURN(bcm_esw_trunk_chip_info_get(unit, &chip_info));
   8818     if (chip_info.trunk_fabric_id_min == -1) {
   8819         return BCM_E_NOT_FOUND;
   8820     } else {
   8821         num_hg_trunk_groups = chip_info.trunk_fabric_id_max - 
   8822             chip_info.trunk_fabric_id_min + 1;
   8823     }
   8824 
   8825     for (hgtid = 0; hgtid < num_hg_trunk_groups; hgtid++) {
   8826         SOC_IF_ERROR_RETURN
   8827             (READ_HG_TRUNK_BITMAPm(unit, MEM_BLOCK_ANY, hgtid, &hg_trunk_bitmap_entry));
   8828         SOC_PBMP_CLEAR(trunk_pbmp);
   8829         soc_mem_pbmp_field_get(unit, HG_TRUNK_BITMAPm, &hg_trunk_bitmap_entry,
   8830                 HIGIG_TRUNK_BITMAPf, &trunk_pbmp);
   8831         if (SOC_PBMP_MEMBER(trunk_pbmp, port)) {
   8832             *tid = hgtid + chip_info.trunk_fabric_id_min;
   8833             return BCM_E_NONE;
   8834         }
   8835     }
   8836     return BCM_E_NOT_FOUND;
   8837 }
   8838 
   8839 /*
   8840  * Function:
   8841  *      _bcm_trident_trunk_override_mcast_set
   8842  * Purpose:
   8843  *      Set Higig trunk override in L2MC table.
   8844  * Parameters:
   8845  *      unit   - (IN) SOC unit number. 
   8846  *      hgtid  - (IN) Higig trunk group ID.
   8847  *      idx    - (IN) L2MC table index.
   8848  *      enable - (IN) Higig trunk override enable.
   8849  * Returns:
   8850  *      BCM_E_xxx
   8851  */
   8852 int
   8853 _bcm_trident_trunk_override_mcast_set(int unit,
   8854         bcm_trunk_t hgtid,
   8855         int idx,
   8856         int enable)
   8857 {
   8858     l2mc_entry_t l2mc_entry;
   8859     ing_higig_trunk_override_profile_entry_t hgo_profile_entry;
   8860 
   8861     int    rv;
   8862     uint32 old_profile_ptr, new_profile_ptr;
   8863     int hgo_bits, alloc_sz;
   8864     SHR_BITDCL *hgo_bitmap = NULL;
   8865     void   *entry_ptr;
   8866 
   8867     /* Get old profile entry */
   8868 
   8869     soc_mem_lock(unit, L2MCm);
   8870     rv = READ_L2MCm(unit, MEM_BLOCK_ANY, idx, &l2mc_entry);
   8871     if (SOC_FAILURE(rv)) {
   8872         soc_mem_unlock(unit, L2MCm);
   8873         return rv;
   8874     }
   8875 
   8876     old_profile_ptr = soc_L2MCm_field32_get(unit, &l2mc_entry,
   8877             HIGIG_TRUNK_OVERRIDE_PROFILE_PTRf);
   8878     rv = READ_ING_HIGIG_TRUNK_OVERRIDE_PROFILEm(unit, MEM_BLOCK_ANY,
   8879             old_profile_ptr, &hgo_profile_entry);
   8880     if (SOC_FAILURE(rv)) {
   8881         soc_mem_unlock(unit, L2MCm);
   8882         return rv;
   8883     }
   8884 
   8885     hgo_bits = soc_mem_field_length(unit, 
   8886                                     ING_HIGIG_TRUNK_OVERRIDE_PROFILEm,
   8887                                     HIGIG_TRUNK_OVERRIDE_BITMAPf);
   8888     alloc_sz = SHR_BITALLOCSIZE(hgo_bits);
   8889     hgo_bitmap = sal_alloc(alloc_sz, "HGT override bitmap");
   8890     if (hgo_bitmap == NULL) {
   8891         soc_mem_unlock(unit, L2MCm);
   8892         return BCM_E_MEMORY;
   8893     }
   8894     /* Add new profile entry */ 
   8895     soc_ING_HIGIG_TRUNK_OVERRIDE_PROFILEm_field_get(unit,
   8896             &hgo_profile_entry, HIGIG_TRUNK_OVERRIDE_BITMAPf, hgo_bitmap);
   8897     if (enable) {
   8898         SHR_BITSET(hgo_bitmap, hgtid);
   8899     } else {
   8900         SHR_BITCLR(hgo_bitmap, hgtid);
   8901     }
   8902     soc_ING_HIGIG_TRUNK_OVERRIDE_PROFILEm_field_set(unit,
   8903             &hgo_profile_entry, HIGIG_TRUNK_OVERRIDE_BITMAPf, hgo_bitmap);
   8904     sal_free(hgo_bitmap);
   8905     hgo_bitmap = NULL;
   8906 
   8907     entry_ptr = &hgo_profile_entry;
   8908     rv = soc_profile_mem_add(unit, _trident_hg_trunk_override_profile[unit], 
   8909             &entry_ptr, 1, &new_profile_ptr);
   8910     if (SOC_FAILURE(rv)) {
   8911         soc_mem_unlock(unit, L2MCm);
   8912         return rv;
   8913     }
   8914 
   8915     soc_L2MCm_field32_set(unit, &l2mc_entry, HIGIG_TRUNK_OVERRIDE_PROFILE_PTRf,
   8916             new_profile_ptr);
   8917     rv = WRITE_L2MCm(unit, MEM_BLOCK_ALL, idx, &l2mc_entry);
   8918     soc_mem_unlock(unit, L2MCm);
   8919     if (SOC_FAILURE(rv)) {
   8920         return rv;
   8921     }
   8922 
   8923     /* Delete old profile entry */
   8924     rv = soc_profile_mem_delete(unit, _trident_hg_trunk_override_profile[unit], 
   8925             old_profile_ptr);
   8926 
   8927     return rv;
   8928 }
   8929 
   8930 /*
   8931  * Function:
   8932  *      _bcm_trident_trunk_override_mcast_get
   8933  * Purpose:
   8934  *      Get Higig trunk override for L2MC group.
   8935  * Parameters:
   8936  *      unit   - (IN) SOC unit number. 
   8937  *      hgtid  - (IN) Higig trunk group ID.
   8938  *      idx    - (IN) L2MC index.
   8939  *      enable - (OUT) Pointer to Higig trunk override enable.
   8940  * Returns:
   8941  *      BCM_E_xxx
   8942  */
   8943 int
   8944 _bcm_trident_trunk_override_mcast_get(int unit,
   8945         bcm_trunk_t hgtid,
   8946         int idx,
   8947         int *enable)
   8948 {
   8949     l2mc_entry_t l2mc_entry;
   8950     ing_higig_trunk_override_profile_entry_t hgo_profile_entry;
   8951 
   8952     int    profile_ptr;
   8953     int hgo_bits, alloc_sz;
   8954     SHR_BITDCL *hgo_bitmap = NULL;
   8955 
   8956     SOC_IF_ERROR_RETURN
   8957         (READ_L2MCm(unit, MEM_BLOCK_ANY, idx, &l2mc_entry));
   8958 
   8959     profile_ptr = soc_L2MCm_field32_get(unit, &l2mc_entry,
   8960             HIGIG_TRUNK_OVERRIDE_PROFILE_PTRf);
   8961 
   8962     SOC_IF_ERROR_RETURN
   8963         (READ_ING_HIGIG_TRUNK_OVERRIDE_PROFILEm(unit, MEM_BLOCK_ANY,
   8964                                                 profile_ptr, &hgo_profile_entry));
   8965     hgo_bits = soc_mem_field_length(unit, 
   8966                                     ING_HIGIG_TRUNK_OVERRIDE_PROFILEm,
   8967                                     HIGIG_TRUNK_OVERRIDE_BITMAPf);
   8968     alloc_sz = SHR_BITALLOCSIZE(hgo_bits);
   8969     hgo_bitmap = sal_alloc(alloc_sz, "HGT override bitmap");
   8970     if (hgo_bitmap == NULL) {
   8971         return BCM_E_MEMORY;
   8972     }
   8973     soc_ING_HIGIG_TRUNK_OVERRIDE_PROFILEm_field_get(unit,
   8974             &hgo_profile_entry, HIGIG_TRUNK_OVERRIDE_BITMAPf, hgo_bitmap);
   8975 
   8976     *enable = SHR_BITGET(hgo_bitmap, hgtid) ? 1 : 0;
   8977 
   8978     sal_free(hgo_bitmap);
   8979     hgo_bitmap = NULL;
   8980 
   8981     return BCM_E_NONE;
   8982 }
   8983 
   8984 /*
   8985  * Function:
   8986  *      _bcm_trident_trunk_override_ipmc_set
   8987  * Purpose:
   8988  *      Set Higig trunk override for IPMC group.
   8989  * Parameters:
   8990  *      unit   - (IN) SOC unit number. 
   8991  *      hgtid  - (IN) Higig trunk group ID.
   8992  *      idx    - (IN) IPMC index.
   8993  *      enable - (IN) Higig trunk override enable.
   8994  * Returns:
   8995  *      BCM_E_xxx
   8996  */
   8997 int
   8998 _bcm_trident_trunk_override_ipmc_set(int unit,
   8999         bcm_trunk_t hgtid,
   9000         int idx,
   9001         int enable)
   9002 {
   9003     ipmc_entry_t ipmc_entry;
   9004     ing_higig_trunk_override_profile_entry_t hgo_profile_entry;
   9005 
   9006     int    rv;
   9007     uint32 old_profile_ptr, new_profile_ptr;
   9008     int hgo_bits, alloc_sz;
   9009     SHR_BITDCL *hgo_bitmap = NULL;
   9010     void   *entry_ptr;
   9011     int    mc_base = 0, mc_size, mc_index;
   9012 
   9013     /* Get old profile entry */
   9014 
   9015     soc_mem_lock(unit, L3_IPMCm);
   9016     rv = READ_L3_IPMCm(unit, MEM_BLOCK_ANY, idx, &ipmc_entry);
   9017     if (SOC_FAILURE(rv)) {
   9018         soc_mem_unlock(unit, L3_IPMCm);
   9019         return rv;
   9020     }
   9021 
   9022     old_profile_ptr = soc_L3_IPMCm_field32_get(unit, &ipmc_entry,
   9023             HIGIG_TRUNK_OVERRIDE_PROFILE_PTRf);
   9024     rv = READ_ING_HIGIG_TRUNK_OVERRIDE_PROFILEm(unit, MEM_BLOCK_ANY,
   9025             old_profile_ptr, &hgo_profile_entry);
   9026     if (SOC_FAILURE(rv)) {
   9027         soc_mem_unlock(unit, L3_IPMCm);
   9028         return rv;
   9029     }
   9030 
   9031     hgo_bits = soc_mem_field_length(unit, 
   9032                                     ING_HIGIG_TRUNK_OVERRIDE_PROFILEm,
   9033                                     HIGIG_TRUNK_OVERRIDE_BITMAPf);
   9034     alloc_sz = SHR_BITALLOCSIZE(hgo_bits);
   9035     hgo_bitmap = sal_alloc(alloc_sz, "HGT override bitmap");
   9036     if (hgo_bitmap == NULL) {
   9037         soc_mem_unlock(unit, L3_IPMCm);
   9038         return BCM_E_MEMORY;
   9039     }
   9040     /* Add new profile entry */ 
   9041     soc_ING_HIGIG_TRUNK_OVERRIDE_PROFILEm_field_get(unit,
   9042             &hgo_profile_entry, HIGIG_TRUNK_OVERRIDE_BITMAPf, hgo_bitmap);
   9043     if (enable) {
   9044         SHR_BITSET(hgo_bitmap, hgtid);
   9045     } else {
   9046         SHR_BITCLR(hgo_bitmap, hgtid);
   9047     }
   9048     soc_ING_HIGIG_TRUNK_OVERRIDE_PROFILEm_field_set(unit, 
   9049             &hgo_profile_entry, HIGIG_TRUNK_OVERRIDE_BITMAPf, hgo_bitmap);
   9050     sal_free(hgo_bitmap);
   9051     hgo_bitmap = NULL;
   9052 
   9053     entry_ptr = &hgo_profile_entry;
   9054     rv = soc_profile_mem_add(unit, _trident_hg_trunk_override_profile[unit], 
   9055             &entry_ptr, 1, &new_profile_ptr);
   9056     if (SOC_FAILURE(rv)) {
   9057         soc_mem_unlock(unit, L3_IPMCm);
   9058         return rv;
   9059     }
   9060 
   9061     soc_L3_IPMCm_field32_set(unit, &ipmc_entry, HIGIG_TRUNK_OVERRIDE_PROFILE_PTRf,
   9062             new_profile_ptr);
   9063     rv = WRITE_L3_IPMCm(unit, MEM_BLOCK_ALL, idx, &ipmc_entry);
   9064     soc_mem_unlock(unit, L3_IPMCm);
   9065     if (SOC_FAILURE(rv)) {
   9066         return rv;
   9067     }
   9068 
   9069     /* Delete old profile entry */
   9070     SOC_IF_ERROR_RETURN
   9071         (soc_profile_mem_delete(unit, _trident_hg_trunk_override_profile[unit], 
   9072                                 old_profile_ptr));
   9073 
   9074     /* In Trident, for IPMC packets from Higig ports, the L2 port bitmap is 
   9075      * derived from L2MC table. Hence, the Higig trunk override in L2MC table
   9076      * also needs to be updated.
   9077      */
   9078     if(!(SOC_IS_MONTEREY(unit))) {
   9079         if (SOC_REG_FIELD_VALID(unit, MC_CONTROL_5r, SHARED_TABLE_L2MC_SIZEf) &&
   9080                 SOC_REG_FIELD_VALID(unit, MC_CONTROL_5r, SHARED_TABLE_IPMC_SIZEf)) {
   9081             SOC_IF_ERROR_RETURN(soc_hbx_ipmc_size_get(unit, &mc_base, &mc_size));
   9082             if (idx >= mc_size) {
   9083                 return BCM_E_PARAM;
   9084             }
   9085             mc_index = idx + mc_base;
   9086             SOC_IF_ERROR_RETURN
   9087                 (_bcm_trident_trunk_override_mcast_set(unit, hgtid, mc_index, enable));
   9088         }
   9089     }
   9090     return BCM_E_NONE;
   9091 }
   9092 
   9093 /*
   9094  * Function:
   9095  *      _bcm_trident_trunk_override_ipmc_get
   9096  * Purpose:
   9097  *      Get Higig trunk override for IPMC group.
   9098  * Parameters:
   9099  *      unit   - (IN) SOC unit number. 
   9100  *      hgtid  - (IN) Higig trunk group ID.
   9101  *      idx    - (IN) IPMC index.
   9102  *      enable - (OUT) Pointer to Higig trunk override enable.
   9103  * Returns:
   9104  *      BCM_E_xxx
   9105  */
   9106 int
   9107 _bcm_trident_trunk_override_ipmc_get(int unit,
   9108         bcm_trunk_t hgtid,
   9109         int idx,
   9110         int *enable)
   9111 {
   9112     ipmc_entry_t ipmc_entry;
   9113     ing_higig_trunk_override_profile_entry_t hgo_profile_entry;
   9114 
   9115     int    profile_ptr;
   9116     int hgo_bits, alloc_sz;
   9117     SHR_BITDCL *hgo_bitmap = NULL;
   9118 
   9119     SOC_IF_ERROR_RETURN
   9120         (READ_L3_IPMCm(unit, MEM_BLOCK_ANY, idx, &ipmc_entry));
   9121 
   9122     profile_ptr = soc_L3_IPMCm_field32_get(unit, &ipmc_entry,
   9123             HIGIG_TRUNK_OVERRIDE_PROFILE_PTRf);
   9124 
   9125     SOC_IF_ERROR_RETURN
   9126         (READ_ING_HIGIG_TRUNK_OVERRIDE_PROFILEm(unit, MEM_BLOCK_ANY,
   9127                                                 profile_ptr, &hgo_profile_entry));
   9128     hgo_bits = soc_mem_field_length(unit, 
   9129                                     ING_HIGIG_TRUNK_OVERRIDE_PROFILEm,
   9130                                     HIGIG_TRUNK_OVERRIDE_BITMAPf);
   9131     alloc_sz = SHR_BITALLOCSIZE(hgo_bits);
   9132     hgo_bitmap = sal_alloc(alloc_sz, "HGT override bitmap");
   9133     if (hgo_bitmap == NULL) {
   9134         return BCM_E_MEMORY;
   9135     }
   9136     soc_ING_HIGIG_TRUNK_OVERRIDE_PROFILEm_field_get(unit,
   9137             &hgo_profile_entry, HIGIG_TRUNK_OVERRIDE_BITMAPf, hgo_bitmap);
   9138 
   9139     *enable = SHR_BITGET(hgo_bitmap, hgtid) ? 1 : 0;
   9140 
   9141     sal_free(hgo_bitmap);
   9142     hgo_bitmap = NULL;
   9143 
   9144     return BCM_E_NONE;
   9145 }
   9146 
   9147 /*
   9148  * Function:
   9149  *      _bcm_trident_trunk_override_vlan_set
   9150  * Purpose:
   9151  *      Set Higig trunk override in VLAN table.
   9152  * Parameters:
   9153  *      unit   - (IN) SOC unit number. 
   9154  *      hgtid  - (IN) Higig trunk group ID.
   9155  *      idx    - (IN) VLAN table index.
   9156  *      enable - (IN) Higig trunk override enable.
   9157  * Returns:
   9158  *      BCM_E_xxx
   9159  */
   9160 int
   9161 _bcm_trident_trunk_override_vlan_set(int unit,
   9162         bcm_trunk_t hgtid,
   9163         int idx,
   9164         int enable)
   9165 {
   9166     vlan_tab_entry_t vlan_tab_entry;
   9167     ing_higig_trunk_override_profile_entry_t hgo_profile_entry;
   9168 
   9169     int    rv;
   9170     uint32 old_profile_ptr, new_profile_ptr;
   9171     int hgo_bits, alloc_sz;
   9172     SHR_BITDCL *hgo_bitmap = NULL;
   9173     void   *entry_ptr;
   9174 
   9175     /* Get old profile entry */
   9176 
   9177     soc_mem_lock(unit, VLAN_TABm);
   9178     rv = READ_VLAN_TABm(unit, MEM_BLOCK_ANY, idx, &vlan_tab_entry);
   9179     if (SOC_FAILURE(rv)) {
   9180         soc_mem_unlock(unit, VLAN_TABm);
   9181         return rv;
   9182     }
   9183 
   9184     old_profile_ptr = soc_VLAN_TABm_field32_get(unit, &vlan_tab_entry,
   9185             HIGIG_TRUNK_OVERRIDE_PROFILE_PTRf);
   9186     rv = READ_ING_HIGIG_TRUNK_OVERRIDE_PROFILEm(unit, MEM_BLOCK_ANY,
   9187             old_profile_ptr, &hgo_profile_entry);
   9188     if (SOC_FAILURE(rv)) {
   9189         soc_mem_unlock(unit, VLAN_TABm);
   9190         return rv;
   9191     }
   9192 
   9193     hgo_bits = soc_mem_field_length(unit, 
   9194                                     ING_HIGIG_TRUNK_OVERRIDE_PROFILEm,
   9195                                     HIGIG_TRUNK_OVERRIDE_BITMAPf);
   9196     alloc_sz = SHR_BITALLOCSIZE(hgo_bits);
   9197     hgo_bitmap = sal_alloc(alloc_sz, "HGT override bitmap");
   9198     if (hgo_bitmap == NULL) {
   9199         soc_mem_unlock(unit, VLAN_TABm);
   9200         return BCM_E_MEMORY;
   9201     }
   9202     /* Add new profile entry */ 
   9203     soc_ING_HIGIG_TRUNK_OVERRIDE_PROFILEm_field_get(unit,
   9204             &hgo_profile_entry, HIGIG_TRUNK_OVERRIDE_BITMAPf, hgo_bitmap);
   9205     if (enable) {
   9206         SHR_BITSET(hgo_bitmap, hgtid);
   9207     } else {
   9208         SHR_BITCLR(hgo_bitmap, hgtid);
   9209     }
   9210     soc_ING_HIGIG_TRUNK_OVERRIDE_PROFILEm_field_set(unit,
   9211             &hgo_profile_entry, HIGIG_TRUNK_OVERRIDE_BITMAPf, hgo_bitmap);
   9212     sal_free(hgo_bitmap);
   9213     hgo_bitmap = NULL;
   9214 
   9215     entry_ptr = &hgo_profile_entry;
   9216     rv = soc_profile_mem_add(unit, _trident_hg_trunk_override_profile[unit], 
   9217             &entry_ptr, 1, &new_profile_ptr);
   9218     if (SOC_FAILURE(rv)) {
   9219         soc_mem_unlock(unit, VLAN_TABm);
   9220         return rv;
   9221     }
   9222 
   9223     soc_VLAN_TABm_field32_set(unit, &vlan_tab_entry, HIGIG_TRUNK_OVERRIDE_PROFILE_PTRf,
   9224             new_profile_ptr);
   9225     rv = WRITE_VLAN_TABm(unit, MEM_BLOCK_ALL, idx, &vlan_tab_entry);
   9226     soc_mem_unlock(unit, VLAN_TABm);
   9227     if (SOC_FAILURE(rv)) {
   9228         return rv;
   9229     }
   9230 
   9231     /* Delete old profile entry */
   9232     rv = soc_profile_mem_delete(unit, _trident_hg_trunk_override_profile[unit], 
   9233             old_profile_ptr);
   9234 
   9235     return rv;
   9236 }
   9237 
   9238 /*
   9239  * Function:
   9240  *      _bcm_trident_trunk_override_vlan_get
   9241  * Purpose:
   9242  *      Get Higig trunk override for VLAN table.
   9243  * Parameters:
   9244  *      unit   - (IN) SOC unit number. 
   9245  *      hgtid  - (IN) Higig trunk group ID.
   9246  *      idx    - (IN) VLAN table index.
   9247  *      enable - (OUT) Pointer to Higig trunk override enable.
   9248  * Returns:
   9249  *      BCM_E_xxx
   9250  */
   9251 int
   9252 _bcm_trident_trunk_override_vlan_get(int unit,
   9253         bcm_trunk_t hgtid,
   9254         int idx,
   9255         int *enable)
   9256 {
   9257     vlan_tab_entry_t vlan_tab_entry;
   9258     ing_higig_trunk_override_profile_entry_t hgo_profile_entry;
   9259 
   9260     int    profile_ptr;
   9261     int hgo_bits, alloc_sz;
   9262     SHR_BITDCL *hgo_bitmap = NULL;
   9263 
   9264     SOC_IF_ERROR_RETURN
   9265         (READ_VLAN_TABm(unit, MEM_BLOCK_ANY, idx, &vlan_tab_entry));
   9266 
   9267     profile_ptr = soc_VLAN_TABm_field32_get(unit, &vlan_tab_entry,
   9268             HIGIG_TRUNK_OVERRIDE_PROFILE_PTRf);
   9269 
   9270     SOC_IF_ERROR_RETURN
   9271         (READ_ING_HIGIG_TRUNK_OVERRIDE_PROFILEm(unit, MEM_BLOCK_ANY,
   9272                                                 profile_ptr, &hgo_profile_entry));
   9273 
   9274     hgo_bits = soc_mem_field_length(unit, 
   9275                                     ING_HIGIG_TRUNK_OVERRIDE_PROFILEm,
   9276                                     HIGIG_TRUNK_OVERRIDE_BITMAPf);
   9277     alloc_sz = SHR_BITALLOCSIZE(hgo_bits);
   9278     hgo_bitmap = sal_alloc(alloc_sz, "HGT override bitmap");
   9279     if (hgo_bitmap == NULL) {
   9280         return BCM_E_MEMORY;
   9281     }
   9282     soc_ING_HIGIG_TRUNK_OVERRIDE_PROFILEm_field_get(unit,
   9283             &hgo_profile_entry, HIGIG_TRUNK_OVERRIDE_BITMAPf, hgo_bitmap);
   9284 
   9285     *enable = SHR_BITGET(hgo_bitmap, hgtid) ? 1 : 0;
   9286 
   9287     sal_free(hgo_bitmap);
   9288     hgo_bitmap = NULL;
   9289 
   9290     return BCM_E_NONE;
   9291 }
   9292 
   9293 /* ----------------------------------------------------------------------------- 
   9294  *
   9295  * Routines shared by front panel and Higig trunking 
   9296  *
   9297  * ----------------------------------------------------------------------------- 
   9298  */
   9299 
   9300 /*
   9301  * Function:
   9302  *      bcm_trident_trunk_destroy
   9303  * Purpose:
   9304  *      Remove trunk group.
   9305  * Parameters:
   9306  *      unit     - (IN) SOC unit number. 
   9307  *      tid      - (IN) Trunk group ID.
   9308  *      t_info   - (IN) Pointer to trunk info.
   9309  * Returns:
   9310  *      BCM_E_xxx
   9311  */
   9312 int
   9313 bcm_trident_trunk_destroy(int unit,
   9314         bcm_trunk_t tid,
   9315         trunk_private_t *t_info)
   9316 {
   9317     bcm_trunk_chip_info_t chip_info;
   9318     int                   hgtid;
   9319 
   9320     BCM_IF_ERROR_RETURN(bcm_esw_trunk_chip_info_get(unit, &chip_info));
   9321     if (chip_info.trunk_fabric_id_min >= 0 &&
   9322         tid >= chip_info.trunk_fabric_id_min) {        /* fabric trunk */
   9323         hgtid = tid - chip_info.trunk_fabric_id_min;
   9324         return _bcm_trident_trunk_fabric_destroy(unit, hgtid, t_info);
   9325     }
   9326 
   9327     /* Front panel trunks */
   9328     return _bcm_trident_trunk_fp_destroy(unit, tid, t_info);
   9329 }
   9330 
   9331 /*
   9332  * Function:
   9333  *      _trident_trunk_add_info_member_alloc
   9334  * Purpose:
   9335  *      Allocate member_flags, tp, and tm of _esw_trunk_add_info_t.
   9336  * Parameters:
   9337  *      add_info  - (IN) Pointer to trident trunk add info structure.
   9338  *      num_ports - (IN) Number of member ports.
   9339  * Returns:
   9340  *      BCM_E_xxx
   9341  */
   9342 STATIC int
   9343 _trident_trunk_add_info_member_alloc(_esw_trunk_add_info_t *add_info,
   9344         int num_ports)
   9345 {
   9346     int rv = BCM_E_NONE;
   9347 
   9348     add_info->member_flags = sal_alloc(sizeof(uint32) * num_ports,
   9349             "_trident_trunk_add_info_member_flags");
   9350     if (add_info->member_flags == NULL) {
   9351         rv = BCM_E_MEMORY;
   9352         goto error;
   9353     }
   9354     sal_memset(add_info->member_flags, 0, sizeof(uint32) * num_ports);
   9355 
   9356     add_info->tp = sal_alloc(sizeof(bcm_port_t) * num_ports,
   9357             "_trident_trunk_add_info_tp");
   9358     if (add_info->tp == NULL) {
   9359         rv = BCM_E_MEMORY;
   9360         goto error;
   9361     }
   9362     sal_memset(add_info->tp, 0, sizeof(bcm_port_t) * num_ports);
   9363 
   9364     add_info->tm = sal_alloc(sizeof(bcm_module_t) * num_ports,
   9365             "_trident_trunk_add_info_tm");
   9366     if (add_info->tm == NULL) {
   9367         rv = BCM_E_MEMORY;
   9368         goto error;
   9369     }
   9370     sal_memset(add_info->tm, 0, sizeof(bcm_module_t) * num_ports);
   9371 
   9372     add_info->dynamic_scaling_factor = sal_alloc(sizeof(int) * num_ports,
   9373             "_trident_trunk_add_info_dynamic_scaling_factor");
   9374     if (add_info->dynamic_scaling_factor == NULL) {
   9375         rv = BCM_E_MEMORY;
   9376         goto error;
   9377     }
   9378     sal_memset(add_info->dynamic_scaling_factor, 0, sizeof(int) * num_ports);
   9379 
   9380     add_info->dynamic_load_weight = sal_alloc(sizeof(int) * num_ports,
   9381             "_trident_trunk_add_info_dynamic_load_weight");
   9382     if (add_info->dynamic_load_weight == NULL) {
   9383         rv = BCM_E_MEMORY;
   9384         goto error;
   9385     }
   9386     sal_memset(add_info->dynamic_load_weight, 0, sizeof(int) * num_ports);
   9387 
   9388     add_info->dynamic_queue_size_weight = sal_alloc(sizeof(int) * num_ports,
   9389             "_trident_trunk_add_info_dynamic_queue_size_weight");
   9390     if (add_info->dynamic_queue_size_weight == NULL) {
   9391         rv = BCM_E_MEMORY;
   9392         goto error;
   9393     }
   9394     sal_memset(add_info->dynamic_queue_size_weight, 0, sizeof(int) * num_ports);
   9395 
   9396     return rv;
   9397 
   9398 error:
   9399     if (NULL != add_info->member_flags) {
   9400         sal_free(add_info->member_flags);
   9401     }
   9402     if (NULL != add_info->tp) {
   9403         sal_free(add_info->tp);
   9404     }
   9405     if (NULL != add_info->tm) {
   9406         sal_free(add_info->tm);
   9407     }
   9408     if (NULL != add_info->dynamic_scaling_factor) {
   9409         sal_free(add_info->dynamic_scaling_factor);
   9410     }
   9411     if (NULL != add_info->dynamic_load_weight) {
   9412         sal_free(add_info->dynamic_load_weight);
   9413     }
   9414     if (NULL != add_info->dynamic_queue_size_weight) {
   9415         sal_free(add_info->dynamic_queue_size_weight);
   9416     }
   9417 
   9418     return rv;
   9419 }
   9420 
   9421 /*
   9422  * Function:
   9423  *      _trident_trunk_add_info_member_free
   9424  * Purpose:
   9425  *      Free member_flags, tp, and tm of _esw_trunk_add_info_t.
   9426  * Parameters:
   9427  *      add_info  - (IN) Pointer to trident trunk add info structure.
   9428  * Returns:
   9429  *      BCM_E_xxx
   9430  */
   9431 STATIC void 
   9432 _trident_trunk_add_info_member_free(_esw_trunk_add_info_t *add_info)
   9433 {
   9434     if (NULL != add_info->member_flags) {
   9435         sal_free(add_info->member_flags);
   9436     }
   9437     if (NULL != add_info->tp) {
   9438         sal_free(add_info->tp);
   9439     }
   9440     if (NULL != add_info->tm) {
   9441         sal_free(add_info->tm);
   9442     }
   9443     if (NULL != add_info->dynamic_scaling_factor) {
   9444         sal_free(add_info->dynamic_scaling_factor);
   9445     }
   9446     if (NULL != add_info->dynamic_load_weight) {
   9447         sal_free(add_info->dynamic_load_weight);
   9448     }
   9449     if (NULL != add_info->dynamic_queue_size_weight) {
   9450         sal_free(add_info->dynamic_queue_size_weight);
   9451     }
   9452 }
   9453 
   9454 /*
   9455  * Function:
   9456  *      _bcm_trident_trunk_modify
   9457  * Purpose:
   9458  *      Set, add or delete trunk members.
   9459  * Parameters:
   9460  *      unit     - (IN) SOC unit number. 
   9461  *      tid      - (IN) Trunk group ID.
   9462  *      add_info - (IN) Pointer to trident trunk add info structure.
   9463  *      t_info   - (IN) Pointer to trunk info.
   9464  *      op       - (IN) Type of operation: TRUNK_MEMBER_OP_SET, ADD or DELETE.
   9465  *      member   - (IN) Member to add or delete.
   9466  * Returns:
   9467  *      BCM_E_xxx
   9468  */
   9469 STATIC int
   9470 _bcm_trident_trunk_modify(int unit,
   9471         bcm_trunk_t tid,
   9472         _esw_trunk_add_info_t *add_info,
   9473         trunk_private_t *t_info,
   9474         trunk_private_t *stored_info,
   9475         int op,
   9476         bcm_trunk_member_t *member)
   9477 {
   9478     bcm_trunk_chip_info_t chip_info;
   9479     int                   hgtid;
   9480 
   9481     BCM_IF_ERROR_RETURN(bcm_esw_trunk_chip_info_get(unit, &chip_info));
   9482 
   9483     if (chip_info.trunk_fabric_id_min >= 0 &&
   9484             tid >= chip_info.trunk_fabric_id_min) {
   9485         /* Higig trunks */
   9486         hgtid = tid - chip_info.trunk_fabric_id_min;
   9487         return _bcm_trident_trunk_fabric_modify(unit, hgtid, add_info, t_info,
   9488                 stored_info, op, member);
   9489     } 
   9490 
   9491     /* Front panel trunks */
   9492     return _bcm_trident_trunk_fp_modify(unit, tid, add_info, t_info,
   9493             stored_info, op, member);
   9494 }
   9495 
   9496 /*
   9497  * Function:
   9498  *      _bcm_trident_hg_dlb_status_get
   9499  * Purpose:
   9500  *      Check if dynamic load balancing is enabled on any Higig trunk group.
   9501  * Parameters:
   9502  *      unit  - (IN) SOC unit number. 
   9503  *      dlb_status - (OUT) Higig DLB status
   9504  * Returns:
   9505  *      BCM_E_xxx
   9506  */
   9507 STATIC int
   9508 _bcm_trident_hg_dlb_status_get(int unit, int *dlb_status)
   9509 {
   9510     int rv = BCM_E_NONE;
   9511     bcm_trunk_chip_info_t chip_info;
   9512     int i;
   9513     int psc;
   9514 
   9515     *dlb_status = FALSE;
   9516 
   9517     BCM_IF_ERROR_RETURN(bcm_esw_trunk_chip_info_get(unit, &chip_info));
   9518     if (chip_info.trunk_fabric_id_min < 0) {
   9519         /* There are no Higig trunk groups. */
   9520         return BCM_E_NOT_FOUND;
   9521     }
   9522 
   9523     for (i = chip_info.trunk_fabric_id_min;
   9524             i <= chip_info.trunk_fabric_id_max; i++) {
   9525         rv = bcm_esw_trunk_psc_get(unit, i, &psc);
   9526         if (rv == BCM_E_NOT_FOUND) {
   9527             continue;
   9528         }
   9529         if ((psc == BCM_TRUNK_PSC_DYNAMIC) ||
   9530             (psc == BCM_TRUNK_PSC_DYNAMIC_ASSIGNED) ||
   9531             (psc == BCM_TRUNK_PSC_DYNAMIC_OPTIMAL)) {
   9532             *dlb_status = TRUE;
   9533             break;
   9534         }
   9535     }
   9536 
   9537     return BCM_E_NONE;
   9538 }
   9539 
   9540 #ifdef BCM_TRIDENT3_SUPPORT
   9541 /*
   9542  * Function:
   9543  *      _bcm_trident_hg_dlb_status_get
   9544  * Purpose:
   9545  *      Check if dynamic load balancing is enabled on any lag trunk group.
   9546  * Parameters:
   9547  *      unit  - (IN) SOC unit number.
   9548  *      dlb_status - (OUT) lag DLB status
   9549  * Returns:
   9550  *      BCM_E_xxx
   9551  */
   9552 STATIC int
   9553 _bcm_trident_lag_dlb_status_get(int unit, int *dlb_status)
   9554 {
   9555     int rv = BCM_E_NONE;
   9556     bcm_trunk_chip_info_t chip_info;
   9557     int i;
   9558     int psc;
   9559 
   9560     *dlb_status = FALSE;
   9561 
   9562     BCM_IF_ERROR_RETURN(bcm_esw_trunk_chip_info_get(unit, &chip_info));
   9563     if (chip_info.trunk_id_min < 0) {
   9564         /* There are no Higig trunk groups. */
   9565         return BCM_E_NOT_FOUND;
   9566     }
   9567 
   9568     for (i = chip_info.trunk_id_min;
   9569             i <= chip_info.trunk_id_max; i++) {
   9570         rv = bcm_esw_trunk_psc_get(unit, i, &psc);
   9571         if (rv == BCM_E_NOT_FOUND) {
   9572             continue;
   9573         }
   9574         if ((psc == BCM_TRUNK_PSC_DYNAMIC) ||
   9575             (psc == BCM_TRUNK_PSC_DYNAMIC_ASSIGNED) ||
   9576             (psc == BCM_TRUNK_PSC_DYNAMIC_OPTIMAL)) {
   9577             *dlb_status = TRUE;
   9578             break;
   9579         }
   9580     }
   9581 
   9582     return BCM_E_NONE;
   9583 }
   9584 
   9585 /*
   9586  * Function:
   9587  *      bcm_td2_lag_rh_status_get
   9588  * Purpose:
   9589  *      Check if resilient hashing is enabled on any lag trunk group.
   9590  * Parameters:
   9591  *      unit  - (IN) SOC unit number.
   9592  *      rh_status - (OUT) lag resilient hashing status
   9593  * Returns:
   9594  *      BCM_E_xxx
   9595  */
   9596 static int
   9597 bcm_td2_lag_rh_status_get(int unit, int *rh_status)
   9598 {
   9599     bcm_trunk_chip_info_t chip_info;
   9600     int i;
   9601     int psc;
   9602     int rv;
   9603 
   9604     *rh_status = FALSE;
   9605 
   9606     BCM_IF_ERROR_RETURN(bcm_esw_trunk_chip_info_get(unit, &chip_info));
   9607     if (chip_info.trunk_id_min < 0) {
   9608         /* There are no Higig trunk groups. */
   9609         return BCM_E_NOT_FOUND;
   9610     }
   9611 
   9612     for (i = chip_info.trunk_id_min;
   9613             i <= chip_info.trunk_id_max; i++) {
   9614         rv = bcm_esw_trunk_psc_get(unit, i, &psc);
   9615         if ((rv != BCM_E_NONE) && (rv != BCM_E_NOT_FOUND)) {
   9616             return rv;
   9617         }
   9618         if (psc == BCM_TRUNK_PSC_DYNAMIC_RESILIENT) {
   9619             *rh_status = TRUE;
   9620             break;
   9621         }
   9622     }
   9623 
   9624     return BCM_E_NONE;
   9625 }
   9626 #endif
   9627 
   9628 
   9629 /*
   9630  * Function:
   9631  *      _bcm_trident_trunk_clear
   9632  * Purpose:
   9633  *      Clear existing trunk group members if any.
   9634  * Parameters:
   9635  *      unit     - (IN) SOC unit number. 
   9636  *      tid      - (IN) Trunk group ID.
   9637  *      t_info   - (IN) Pointer to trunk info.
   9638  * Returns:
   9639  *      BCM_E_xxx
   9640  */
   9641 STATIC int
   9642 _bcm_trident_trunk_clear(int unit,
   9643         bcm_trunk_t tid,
   9644         trunk_private_t *t_info)
   9645 {
   9646     bcm_trunk_chip_info_t chip_info;
   9647     int higig_trunk;
   9648 #ifdef BCM_TRIDENT2_SUPPORT
   9649     int hgtid;
   9650 #endif
   9651 
   9652     if (t_info->in_use) {
   9653         BCM_IF_ERROR_RETURN(bcm_trident_trunk_destroy(unit, tid, t_info));
   9654     }
   9655 
   9656     BCM_IF_ERROR_RETURN(bcm_esw_trunk_chip_info_get(unit, &chip_info));
   9657     if (chip_info.trunk_fabric_id_min >= 0 &&
   9658             tid >= chip_info.trunk_fabric_id_min) {
   9659         higig_trunk = 1;
   9660 #ifdef BCM_TRIDENT2_SUPPORT
   9661         hgtid = tid - chip_info.trunk_fabric_id_min;
   9662 #endif
   9663     } else {
   9664         higig_trunk = 0;
   9665     }
   9666 
   9667     if (higig_trunk) {
   9668 #ifdef BCM_TRIDENT2_SUPPORT
   9669         if (soc_feature(unit, soc_feature_hg_resilient_hash)) {
   9670             if (t_info->psc == BCM_TRUNK_PSC_DYNAMIC_RESILIENT) {
   9671                 /* Write the dynamic_size to hardware, so it can be recovered
   9672                  * during warm boot.
   9673                  */
   9674                 BCM_IF_ERROR_RETURN(bcm_td2_hg_rh_dynamic_size_set(unit, hgtid,
   9675                             t_info->dynamic_size));
   9676             }
   9677         }
   9678 #endif /* BCM_TRIDENT2_SUPPORT */
   9679     } else {
   9680 #ifdef BCM_TRIDENT2_SUPPORT
   9681         if (soc_feature(unit, soc_feature_lag_resilient_hash)) {
   9682             if (t_info->psc == BCM_TRUNK_PSC_DYNAMIC_RESILIENT) {
   9683                 /* Write the dynamic_size to hardware, so it can be recovered
   9684                  * during warm boot.
   9685                  */
   9686                 BCM_IF_ERROR_RETURN(bcm_td2_lag_rh_dynamic_size_set(unit, tid,
   9687                             t_info->dynamic_size));
   9688             }
   9689         }
   9690 #endif /* BCM_TRIDENT2_SUPPORT */
   9691     }
   9692 
   9693     return BCM_E_NONE;
   9694 }
   9695 
   9696 /*
   9697  * Function:
   9698  *      bcm_trident_trunk_modify
   9699  * Purpose:
   9700  *      Set, add or delete trunk members.
   9701  * Parameters:
   9702  *      unit       - (IN) SOC unit number. 
   9703  *      tid        - (IN) Trunk group ID.
   9704  *      trunk_info - (IN) Pointer to user provided trunk info.
   9705  *      member_count - (IN) Number of trunk members.
   9706  *      member_array - (IN) Array of trunk members.
   9707  *      t_info       - (IN) Pointer to internal trunk info.
   9708  *      op           - (IN) Type of operation: TRUNK_MEMBER_OP_SET, ADD or DELETE.
   9709  *      member       - (IN) Member to add or delete.
   9710  * Returns:
   9711  *      BCM_E_xxx
   9712  */
   9713 int
   9714 bcm_trident_trunk_modify(int unit,
   9715         bcm_trunk_t tid,
   9716         bcm_trunk_info_t *trunk_info,
   9717         int member_count,
   9718         bcm_trunk_member_t *member_array,
   9719         trunk_private_t *t_info,
   9720         int op,
   9721         bcm_trunk_member_t *member)
   9722 {
   9723     int dlb_enable=0, rh_enable=0;
   9724     bcm_trunk_chip_info_t chip_info;
   9725     int rv = BCM_E_NONE;
   9726     int dynamic_size_encode;
   9727     int dlb_status;
   9728     _esw_trunk_add_info_t add_info;
   9729     int i;
   9730     int higig_trunk;
   9731     trunk_private_t  stored_info;
   9732 #ifdef INCLUDE_L3
   9733     int old_member_count, old_local_member_cnt = 0;
   9734     bcm_trunk_info_t tmp_trunk_info;
   9735     bcm_trunk_member_t *tmp_member_array = NULL;
   9736     trunk_private_t  tmp_t_info;
   9737     bcm_port_t *tmp_member_port_array = NULL;
   9738     bcm_module_t member_modid;
   9739     bcm_trunk_t member_tgid;
   9740     int member_id, mod_is_local;
   9741     bcm_gport_t *tmp_member_gport_array = NULL;
   9742 #endif
   9743    
   9744     if (trunk_info->psc <= 0) {
   9745         trunk_info->psc = BCM_TRUNK_PSC_DEFAULT;
   9746     }
   9747 
   9748     if ((trunk_info->psc == BCM_TRUNK_PSC_DYNAMIC) ||
   9749         (trunk_info->psc == BCM_TRUNK_PSC_DYNAMIC_ASSIGNED) ||
   9750         (trunk_info->psc == BCM_TRUNK_PSC_DYNAMIC_OPTIMAL)) {
   9751         dlb_enable = 1;
   9752     } else if (trunk_info->psc == BCM_TRUNK_PSC_DYNAMIC_RESILIENT) {
   9753         rh_enable = 1;
   9754     }
   9755 
   9756 #ifdef INCLUDE_L3
   9757     sal_memset(&tmp_t_info, 0, sizeof(trunk_private_t));
   9758 #endif
   9759     sal_memcpy(&stored_info, t_info, sizeof(trunk_private_t));
   9760 
   9761     BCM_IF_ERROR_RETURN
   9762         (_bcm_trident_trunk_psc_to_rtag(unit, trunk_info->psc, &(t_info->rtag)));
   9763     t_info->psc = trunk_info->psc;
   9764 
   9765     t_info->flags = trunk_info->flags;
   9766 
   9767     if ((trunk_info->dlf_index != trunk_info->mc_index) ||
   9768         (trunk_info->dlf_index != trunk_info->ipmc_index)) {
   9769         return BCM_E_PARAM;
   9770     }
   9771     t_info->dlf_index_spec =
   9772         t_info->dlf_index_used =
   9773         t_info->mc_index_spec = 
   9774         t_info->mc_index_used =
   9775         t_info->ipmc_index_spec =
   9776         t_info->ipmc_index_used = trunk_info->dlf_index;
   9777 
   9778     BCM_IF_ERROR_RETURN(bcm_esw_trunk_chip_info_get(unit, &chip_info));
   9779     if (chip_info.trunk_fabric_id_min >= 0 &&
   9780             tid >= chip_info.trunk_fabric_id_min) {
   9781         higig_trunk = 1;
   9782     } else {
   9783         higig_trunk = 0;
   9784     }
   9785 
   9786     if (!higig_trunk) {
   9787         /* Front panel trunks */
   9788 
   9789         if (dlb_enable) {
   9790 #ifdef BCM_TRIUMPH3_SUPPORT
   9791             if (soc_feature(unit, soc_feature_lag_dlb)) {
   9792 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT)
   9793                 if (soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) {
   9794                     uint32 hw_limit;
   9795                     /* Verify dynamic_size */
   9796                     BCM_IF_ERROR_RETURN(bcm_th2_hgt_lag_dlb_dynamic_size_encode(
   9797                                 trunk_info->dynamic_size, &dynamic_size_encode));
   9798                     t_info->dynamic_size = trunk_info->dynamic_size;
   9799 
   9800                     /* Verify dynamic_age */
   9801                     hw_limit = (1 << soc_mem_field_length(
   9802                                 unit, DLB_HGT_LAG_GROUP_CONTROLm,
   9803                                 INACTIVITY_DURATIONf)) - 1;
   9804                     if (trunk_info->dynamic_age < 16 ||
   9805                         trunk_info->dynamic_age > hw_limit) {
   9806                         /* Hardware limits */
   9807                         return BCM_E_PARAM;
   9808                     }
   9809                     t_info->dynamic_age = trunk_info->dynamic_age;
   9810 #ifdef BCM_TRIDENT3_SUPPORT
   9811                     if (soc_feature(unit, soc_feature_td3_dlb)) {
   9812                         int lag_rh_status;
   9813 
   9814                         BCM_IF_ERROR_RETURN(bcm_td2_lag_rh_status_get(unit, &lag_rh_status));
   9815                         if (lag_rh_status) {
   9816                         /* LAG DLB and resilient hashing cannot be enabled
   9817                         * at the same time.
   9818                         */
   9819                             return BCM_E_PARAM;
   9820                         }
   9821                     }
   9822 #endif /* BCM_TRIDENT3_SUPPORT */
   9823                 } else
   9824 #endif /* BCM_TOMAHAWK2_SUPPORT */
   9825                 {
   9826                     /* Verify dynamic_size */
   9827                     BCM_IF_ERROR_RETURN(bcm_tr3_lag_dlb_dynamic_size_encode(
   9828                                 trunk_info->dynamic_size, &dynamic_size_encode));
   9829                     t_info->dynamic_size = trunk_info->dynamic_size;
   9830 
   9831                     /* Verify dynamic_age */
   9832                     /* Error rate in calculating INACTIVITY_DURATION is higher
   9833                        if it is allowed to be configured too low.
   9834                        Minimum limit of 16 microseconds is required to reduce
   9835                        the error rate in time duration calculation.*/
   9836                     if ((trunk_info->dynamic_age < 16) ||
   9837                             (trunk_info->dynamic_age > 0xffff)) {
   9838                         return BCM_E_PARAM;
   9839                     }
   9840                     t_info->dynamic_age = trunk_info->dynamic_age;
   9841 
   9842                     /* Verify dynamic exponents */
   9843                     if (trunk_info->dynamic_load_exponent > 0xf) {
   9844                         return BCM_E_PARAM;
   9845                     }
   9846                     t_info->dynamic_load_exponent =
   9847                         trunk_info->dynamic_load_exponent;
   9848 
   9849                     if (trunk_info->dynamic_expected_load_exponent > 0xf) {
   9850                         return BCM_E_PARAM;
   9851                     }
   9852                     t_info->dynamic_expected_load_exponent =
   9853                         trunk_info->dynamic_expected_load_exponent;
   9854                    if (soc_feature(unit, soc_feature_td3_dlb)) {
   9855                        SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit,
   9856                                 ENHANCED_HASHING_CONTROL_2r, REG_PORT_ANY,
   9857                                 RH_DLB_SELECTIONf, 0));
   9858                     }
   9859                 }
   9860             } else
   9861 #endif /* BCM_TRIUMPH3_SUPPORT */
   9862             {
   9863                 /* Dynamic load balancing not supported for LAGs */
   9864                 return BCM_E_UNAVAIL;
   9865             }
   9866         } else if (rh_enable) {
   9867 #ifdef BCM_TRIDENT2_SUPPORT
   9868             if (soc_feature(unit, soc_feature_lag_resilient_hash)) {
   9869                 /* Verify dynamic_size */
   9870                 BCM_IF_ERROR_RETURN(bcm_td2_lag_rh_dynamic_size_encode(unit,
   9871                             trunk_info->dynamic_size, &dynamic_size_encode));
   9872                 t_info->dynamic_size = trunk_info->dynamic_size;
   9873 #ifdef BCM_TRIDENT3_SUPPORT
   9874                 if (soc_feature(unit, soc_feature_td3_dlb)) {
   9875                     BCM_IF_ERROR_RETURN
   9876                        (_bcm_trident_lag_dlb_status_get(unit, &dlb_status));
   9877                     if (dlb_status) {
   9878                     /* DLB and resilient hashing cannot be enabled
   9879                      * at the same time.
   9880                      */
   9881                         return BCM_E_PARAM;
   9882                     }
   9883                     SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit,
   9884                                         ENHANCED_HASHING_CONTROL_2r,
   9885                                         REG_PORT_ANY, RH_DLB_SELECTIONf,1));
   9886                }
   9887 #endif /* BCM_TRIDENT3_SUPPORT */
   9888             } else 
   9889 #endif /* BCM_TRIDENT2_SUPPORT */
   9890             {
   9891                 /* Resilient hashing not supported for LAGs */
   9892                 return BCM_E_UNAVAIL;
   9893             }
   9894         }
   9895 
   9896     } else {
   9897         /* Higig trunk */
   9898 
   9899         if (dlb_enable) {
   9900             if (soc_feature(unit, soc_feature_hg_dlb)) {
   9901 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT)
   9902                 if (soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) {
   9903                     uint32 hw_limit;
   9904                     /* Verify dynamic_size */
   9905                     BCM_IF_ERROR_RETURN(bcm_th2_hgt_lag_dlb_dynamic_size_encode(
   9906                                 trunk_info->dynamic_size, &dynamic_size_encode));
   9907                     t_info->dynamic_size = trunk_info->dynamic_size;
   9908 
   9909                     /* Verify dynamic_age */
   9910                     hw_limit = (1 << soc_mem_field_length(
   9911                                 unit, DLB_HGT_LAG_GROUP_CONTROLm,
   9912                                 INACTIVITY_DURATIONf)) - 1;
   9913                     if (trunk_info->dynamic_age < 16 ||
   9914                         trunk_info->dynamic_age > hw_limit) {
   9915                         /* Hardware limits */
   9916                         return BCM_E_PARAM;
   9917                     }
   9918                     t_info->dynamic_age = trunk_info->dynamic_age;
   9919                 } else
   9920 #endif /* BCM_TOMAHAWK2_SUPPORT */
   9921                 {
   9922                     /* Verify dynamic_size */
   9923                     BCM_IF_ERROR_RETURN(_bcm_trident_hg_dlb_dynamic_size_encode(
   9924                                 trunk_info->dynamic_size, &dynamic_size_encode));
   9925                     t_info->dynamic_size = trunk_info->dynamic_size;
   9926 
   9927                     /* Verify dynamic_age */
   9928                     if ((trunk_info->dynamic_age < 16) ||
   9929                             (trunk_info->dynamic_age > 0x7fff)) {
   9930                         return BCM_E_PARAM;
   9931                     }
   9932                     t_info->dynamic_age = trunk_info->dynamic_age;
   9933                 }
   9934             } else {
   9935                 /* Dynamic load balancing not supported for Higig trunks */
   9936                 return BCM_E_UNAVAIL;
   9937             }
   9938 
   9939 #ifdef BCM_TRIDENT2_SUPPORT
   9940             if (soc_feature(unit, soc_feature_hg_resilient_hash)) {
   9941                 int rh_status;
   9942 
   9943                 BCM_IF_ERROR_RETURN(bcm_td2_hg_rh_status_get(unit, &rh_status));
   9944                 if (rh_status) {
   9945                     /* Higig DLB and resilient hashing cannot be enabled
   9946                      * at the same time.
   9947                      */
   9948                     return BCM_E_PARAM;
   9949                 }
   9950             }
   9951 
   9952             if (SOC_REG_IS_VALID(unit, ENHANCED_HASHING_CONTROLr)) {
   9953                 if (soc_feature(unit, soc_feature_td3_dlb)) {
   9954                     SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit,
   9955                            ENHANCED_HASHING_CONTROL_2r, REG_PORT_ANY,
   9956                       RH_DLB_SELECTIONf, 0));
   9957                 } else {
   9958                 SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit,
   9959                             ENHANCED_HASHING_CONTROLr, REG_PORT_ANY,
   9960                             RH_HGT_ENABLEf, 0));
   9961                  }
   9962             }
   9963             /* On TD2/TD2+ even when DLB is disabled, parity is still calculated 
   9964             * for both RH_HGT_FLOWSET view and DLB_HGT_FLOWSET view. As a result, 
   9965             * erroneous parity error would be reported for DLB_HGT_FLOWSET. So only when
   9966             * using DLB enable DLB parity control, otherwise disable.
   9967             */
   9968             if ((SOC_IS_TRIDENT2X(unit) || SOC_IS_TITAN2PLUS(unit))) {
   9969                 soc_td2x_ser_dlb_parity_set(unit, 1);
   9970             }
   9971 #endif /* BCM_TRIDENT2_SUPPORT */
   9972 
   9973         } else if (rh_enable) {
   9974 
   9975 #ifdef BCM_TRIDENT2_SUPPORT
   9976             if (soc_feature(unit, soc_feature_hg_resilient_hash)) {
   9977                 /* Verify dynamic_size */
   9978                 BCM_IF_ERROR_RETURN(bcm_td2_hg_rh_dynamic_size_encode(unit,
   9979                             trunk_info->dynamic_size, &dynamic_size_encode));
   9980                 t_info->dynamic_size = trunk_info->dynamic_size;
   9981             } else 
   9982 #endif /* BCM_TRIDENT2_SUPPORT */
   9983             {
   9984                 /* Resilient hashing not supported for Higig trunks */
   9985                 return BCM_E_UNAVAIL;
   9986             }
   9987 
   9988             if (soc_feature(unit, soc_feature_hg_dlb)) {
   9989                 BCM_IF_ERROR_RETURN
   9990                     (_bcm_trident_hg_dlb_status_get(unit, &dlb_status));
   9991                 if (dlb_status) {
   9992                     /* DLB and resilient hashing cannot be enabled
   9993                      * at the same time.
   9994                      */
   9995                     return BCM_E_PARAM;
   9996                 }
   9997             }
   9998 
   9999 #ifdef BCM_TRIDENT2_SUPPORT
  10000             if (SOC_REG_IS_VALID(unit, ENHANCED_HASHING_CONTROLr)) {
  10001                 if (soc_feature(unit, soc_feature_td3_dlb)) {
  10002                     SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit,
  10003                                         ENHANCED_HASHING_CONTROL_2r,
  10004                                         REG_PORT_ANY, RH_DLB_SELECTIONf,1));
  10005                 } else {
  10006                 SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit,
  10007                             ENHANCED_HASHING_CONTROLr, REG_PORT_ANY,
  10008                             RH_HGT_ENABLEf, 1));
  10009             }
  10010             }
  10011             if ((SOC_IS_TRIDENT2X(unit) || SOC_IS_TITAN2PLUS(unit))) {
  10012                 soc_td2x_ser_dlb_parity_set(unit, 0);
  10013             }
  10014 #endif /* BCM_TRIDENT2_SUPPORT */
  10015         }
  10016     }
  10017 
  10018     if (member_count < 1) {
  10019         /* Member count is less than 1 when the operation is
  10020          * TRUNK_MEMBER_OP_SET with zero members or TRUNK_MEMBER_OP_DELETE
  10021          * on the final member of the group. In either case,
  10022          * clear the existing trunk member ports if any.
  10023          */
  10024 #ifdef INCLUDE_L3
  10025     if ((chip_info.trunk_fabric_id_min >= 0 &&
  10026         tid >= chip_info.trunk_fabric_id_min) == 0) {
  10027         if (soc_feature(unit, soc_feature_trill)
  10028             || soc_feature(unit, soc_feature_mpls)
  10029             || soc_feature(unit, soc_feature_vxlan)
  10030             || soc_feature(unit, soc_feature_l2gre)) {
  10031             if (op == TRUNK_MEMBER_OP_SET) {
  10032                 tmp_t_info.in_use = t_info->in_use;
  10033                 /* Get count of ports in this trunk. */
  10034                 BCM_IF_ERROR_RETURN(
  10035                     bcm_trident_trunk_get(unit, tid, &tmp_trunk_info, 0, 
  10036                         NULL, &old_member_count, &tmp_t_info));
  10037                 if (old_member_count) {
  10038                     tmp_member_array = sal_alloc(sizeof(bcm_trunk_member_t) *
  10039                         old_member_count, "trunk_member_array");
  10040                     if (tmp_member_array == NULL) {
  10041                         rv = BCM_E_MEMORY;
  10042                         goto clean_up;
  10043                     } 
  10044                     sal_memset(tmp_member_array, 0,
  10045                          sizeof(bcm_trunk_member_t) * old_member_count);
  10046                     /* Get trunk info  */
  10047                     rv = bcm_trident_trunk_get(unit, tid, &tmp_trunk_info, 
  10048                               old_member_count, tmp_member_array, 
  10049                               &old_member_count, &tmp_t_info);
  10050                     if (BCM_FAILURE(rv)) {
  10051                         goto clean_up;
  10052                     }
  10053                     tmp_member_port_array = sal_alloc(sizeof(bcm_port_t) *
  10054                         old_member_count, "trunk_member_port_array");
  10055                     if (tmp_member_port_array == NULL) {
  10056                         rv = BCM_E_MEMORY;
  10057                         goto clean_up;                         
  10058                     }      
  10059                     sal_memset(tmp_member_port_array, 0,
  10060                         sizeof(bcm_port_t) * old_member_count);
  10061 
  10062                     tmp_member_gport_array = sal_alloc(sizeof(bcm_gport_t) *
  10063                         old_member_count, "trunk_member_gport_array");
  10064                     if (tmp_member_gport_array == NULL) {
  10065                         rv = BCM_E_MEMORY;
  10066                         goto clean_up;
  10067                     }
  10068                     sal_memset(tmp_member_gport_array, 0,
  10069                         sizeof(bcm_gport_t) * old_member_count);
  10070 
  10071                     old_local_member_cnt = 0;
  10072                     for (i = 0; i < old_member_count; i++) {
  10073                         tmp_member_gport_array[i] = tmp_member_array[i].gport;
  10074                         rv = _bcm_esw_gport_resolve(unit, tmp_member_array[i].gport,
  10075                                  &member_modid, &tmp_member_port_array[i], 
  10076                                  &member_tgid, &member_id);
  10077                         if (BCM_FAILURE(rv)) {
  10078                             goto clean_up; 
  10079                         }
  10080                         rv = _bcm_esw_modid_is_local(unit, member_modid,
  10081                                                      &mod_is_local);
  10082                         if (BCM_FAILURE(rv)) {
  10083                             goto clean_up; 
  10084                         }
  10085                         
  10086                         if (!mod_is_local) {
  10087                             continue;
  10088                         }
  10089                         
  10090                         tmp_member_port_array[old_local_member_cnt] =
  10091                             tmp_member_port_array[i];
  10092                         old_local_member_cnt++;    
  10093                     }
  10094                 }
  10095             } else if (op == TRUNK_MEMBER_OP_DELETE) {
  10096                 old_member_count = 1;
  10097                 tmp_member_port_array = sal_alloc(sizeof(bcm_port_t) *
  10098                     old_member_count, "trunk_member_port_array");
  10099                 if (tmp_member_port_array == NULL) {
  10100                     rv = BCM_E_MEMORY;
  10101                     goto clean_up;                         
  10102                 }      
  10103                 sal_memset(tmp_member_port_array, 0,
  10104                     sizeof(bcm_port_t) * old_member_count);
  10105 
  10106                 tmp_member_gport_array = sal_alloc(sizeof(bcm_gport_t) *
  10107                     old_member_count, "trunk_member_gport_array");
  10108                 if (tmp_member_gport_array == NULL) {
  10109                     rv = BCM_E_MEMORY;
  10110                     goto clean_up;
  10111                 }
  10112                 sal_memset(tmp_member_gport_array, 0,
  10113                     sizeof(bcm_gport_t) * old_member_count);
  10114 
  10115                 tmp_member_gport_array[0] = member->gport;
  10116                 rv = _bcm_esw_gport_resolve(unit, member->gport,
  10117                          &member_modid, &tmp_member_port_array[0],
  10118                          &member_tgid, &member_id);
  10119                 if (BCM_FAILURE(rv)) {
  10120                     goto clean_up;
  10121                 }
  10122 
  10123                 rv = _bcm_esw_modid_is_local(unit, member_modid, &mod_is_local);
  10124                 if (BCM_FAILURE(rv)) {
  10125                     goto clean_up;
  10126                 }
  10127 
  10128                 if (mod_is_local) {
  10129                     old_local_member_cnt = 1;
  10130                 }
  10131                 
  10132             } else {
  10133                 rv = BCM_E_PARAM;
  10134                 goto clean_up;
  10135             }
  10136         }
  10137     }
  10138 #endif
  10139         rv = _bcm_trident_trunk_clear(unit, tid, t_info);
  10140         if (BCM_FAILURE(rv)) {
  10141 #ifdef INCLUDE_L3            
  10142             goto clean_up;
  10143 #else
  10144             return rv;
  10145 #endif
  10146         }
  10147 #ifdef INCLUDE_L3
  10148         if ((chip_info.trunk_fabric_id_min >= 0 &&
  10149             tid >= chip_info.trunk_fabric_id_min) == 0) {
  10150             /* Front Panel trunks */
  10151             /* Remove the my_station_tcam entry for TRILL,
  10152                     * VxLAN and L2GRE when clearing the trunk.
  10153                     */
  10154 #ifdef BCM_TRIDENT2_SUPPORT
  10155             if (soc_feature(unit, soc_feature_vxlan)) {
  10156                 if (old_member_count) {
  10157                     rv = _bcm_esw_vxlan_trunk_member_delete(unit, tid,
  10158                              old_member_count, tmp_member_gport_array);
  10159                 }
  10160             }
  10161 #endif
  10162 #ifdef BCM_TRIUMPH3_SUPPORT
  10163             if (soc_feature(unit, soc_feature_l2gre)) {
  10164                 if (old_member_count) {
  10165                     rv = _bcm_esw_l2gre_trunk_member_delete(unit, tid,
  10166                              old_member_count, tmp_member_gport_array);
  10167                 }
  10168             }
  10169 #endif
  10170             if (soc_feature(unit, soc_feature_trill)) {
  10171                 if (old_local_member_cnt) {
  10172                     rv = _bcm_esw_trill_trunk_member_delete(unit, tid,
  10173                              old_local_member_cnt, tmp_member_port_array);
  10174                 }
  10175             }
  10176 #ifdef BCM_TRIUMPH_SUPPORT
  10177             if (soc_feature(unit, soc_feature_mpls)) {
  10178                 if (old_local_member_cnt) {
  10179                     rv = _bcm_esw_mpls_trunk_member_delete(unit, tid,
  10180                              old_local_member_cnt, tmp_member_port_array);
  10181                 }
  10182             }
  10183 #endif
  10184         }
  10185 #endif
  10186     } else {
  10187         sal_memset(&add_info, 0, sizeof(_esw_trunk_add_info_t));
  10188         add_info.flags = trunk_info->flags;
  10189         add_info.num_ports = member_count;
  10190         add_info.psc = trunk_info->psc;
  10191         add_info.ipmc_psc = trunk_info->ipmc_psc;
  10192         add_info.dlf_index = trunk_info->dlf_index;
  10193         add_info.mc_index = trunk_info->mc_index;
  10194         add_info.ipmc_index = trunk_info->ipmc_index;
  10195         add_info.dynamic_size = trunk_info->dynamic_size;
  10196         add_info.dynamic_age = trunk_info->dynamic_age;
  10197         add_info.dynamic_load_exponent = trunk_info->dynamic_load_exponent;
  10198         add_info.dynamic_expected_load_exponent =
  10199             trunk_info->dynamic_expected_load_exponent;
  10200 
  10201         BCM_IF_ERROR_RETURN
  10202             (_trident_trunk_add_info_member_alloc(&add_info, member_count));
  10203         for (i = 0; i < member_count; i++) {
  10204             add_info.member_flags[i] = member_array[i].flags;
  10205             add_info.tp[i] = member_array[i].gport;
  10206             add_info.tm[i] = -1;
  10207             add_info.dynamic_scaling_factor[i] =
  10208                 member_array[i].dynamic_scaling_factor;
  10209             add_info.dynamic_load_weight[i] =
  10210                 member_array[i].dynamic_load_weight;
  10211             add_info.dynamic_queue_size_weight[i] =
  10212                 member_array[i].dynamic_queue_size_weight;
  10213         }
  10214 
  10215         /* Convert member gport to module and port */
  10216         rv = _bcm_esw_trunk_gport_array_resolve(unit,
  10217                 higig_trunk,
  10218                 member_count,
  10219                 add_info.tp,
  10220                 add_info.tp,
  10221                 add_info.tm);
  10222         if (BCM_FAILURE(rv)) {
  10223             _trident_trunk_add_info_member_free(&add_info);
  10224             return rv;
  10225         }
  10226 
  10227         rv = _bcm_trident_trunk_modify(unit, tid, &add_info, 
  10228                 t_info, &stored_info, op, member);
  10229         _trident_trunk_add_info_member_free(&add_info);
  10230     }
  10231 
  10232 #ifdef INCLUDE_L3
  10233 clean_up:
  10234     if (NULL != tmp_member_array) {
  10235         sal_free(tmp_member_array);
  10236     }
  10237 
  10238     if (NULL != tmp_member_port_array) {
  10239         sal_free(tmp_member_port_array);
  10240     }
  10241 
  10242     if (NULL != tmp_member_gport_array) {
  10243         sal_free(tmp_member_gport_array);
  10244     }
  10245 #endif
  10246 
  10247 
  10248     return rv;
  10249 }
  10250 
  10251 /*
  10252  * Function:
  10253  *	_bcm_trident_trunk_get
  10254  * Purpose:
  10255  *      Return a trunk information of given trunk ID.
  10256  * Parameters:
  10257  *      unit   - (IN) StrataSwitch PCI device unit number (driver internal).
  10258  *      tid    - (IN) Trunk ID.
  10259  *      t_data - (OUT) Place to store returned trunk add info.
  10260  *      t_info - (IN) Trunk info.
  10261  * Returns:
  10262  *      BCM_E_NONE              Success.
  10263  *      BCM_E_XXX
  10264  */
  10265 STATIC int
  10266 _bcm_trident_trunk_get(int unit,
  10267         bcm_trunk_t tid,
  10268         _esw_trunk_add_info_t *t_data,
  10269         trunk_private_t *t_info)
  10270 {
  10271     bcm_trunk_chip_info_t chip_info;
  10272     int hgtid;
  10273 
  10274     t_data->flags = t_info->flags;
  10275     t_data->psc = t_info->psc;
  10276     t_data->ipmc_psc = t_info->ipmc_psc;
  10277     t_data->dlf_index = t_info->dlf_index_used;
  10278     t_data->mc_index = t_info->mc_index_used;
  10279     t_data->ipmc_index = t_info->ipmc_index_used;
  10280     t_data->dynamic_size = t_info->dynamic_size;
  10281     t_data->dynamic_age = t_info->dynamic_age;
  10282     t_data->dynamic_load_exponent =
  10283         t_info->dynamic_load_exponent;
  10284     t_data->dynamic_expected_load_exponent =
  10285         t_info->dynamic_expected_load_exponent;
  10286 
  10287     if (!t_info->in_use) {
  10288         t_data->num_ports = 0;
  10289         return BCM_E_NONE;
  10290     }
  10291 
  10292     BCM_IF_ERROR_RETURN(bcm_esw_trunk_chip_info_get(unit, &chip_info));
  10293     if (chip_info.trunk_fabric_id_min >= 0 &&
  10294         tid >= chip_info.trunk_fabric_id_min) {        /* fabric trunk */
  10295         hgtid = tid - chip_info.trunk_fabric_id_min;
  10296         return _bcm_trident_trunk_fabric_get(unit, hgtid, t_data, t_info);
  10297     }
  10298 
  10299     /* Front panel trunk */
  10300     return _bcm_trident_trunk_fp_get(unit, tid, t_data, t_info);
  10301 }
  10302 
  10303 /*
  10304  * Function:
  10305  *	bcm_trident_trunk_get
  10306  * Purpose:
  10307  *      Return a trunk information of given trunk ID.
  10308  * Parameters:
  10309  *      unit   - (IN) StrataSwitch PCI device unit number (driver internal).
  10310  *      tid    - (IN) Trunk ID.
  10311  *      trunk_info   - (OUT) Place to store returned trunk info.
  10312  *      member_max   - (IN) Size of member_array.
  10313  *      member_array - (OUT) Array of trunk member structures.
  10314  *      member_count - (OUT) Number of trunk members returned.
  10315  *      t_info       - (IN) Internal trunk info.
  10316  * Returns:
  10317  *      BCM_E_NONE              Success.
  10318  *      BCM_E_XXX
  10319  */
  10320 int
  10321 bcm_trident_trunk_get(int unit,
  10322         bcm_trunk_t tid,
  10323         bcm_trunk_info_t *trunk_info,
  10324         int member_max, 
  10325         bcm_trunk_member_t *member_array,
  10326         int *member_count,
  10327         trunk_private_t *t_info)
  10328 {
  10329     _esw_trunk_add_info_t add_info;
  10330     int i;
  10331     int rv = BCM_E_NONE;
  10332     bcm_trunk_chip_info_t chip_info;
  10333     int higig_trunk;
  10334 
  10335     sal_memset(&add_info, 0, sizeof(_esw_trunk_add_info_t));
  10336     add_info.num_ports = member_max;
  10337     if (member_max > 0) {
  10338         BCM_IF_ERROR_RETURN
  10339             (_trident_trunk_add_info_member_alloc(&add_info, member_max));
  10340     }
  10341 
  10342     rv = _bcm_trident_trunk_get(unit, tid, &add_info, t_info);
  10343     if (BCM_FAILURE(rv)) {
  10344         if (member_max > 0) {
  10345             _trident_trunk_add_info_member_free(&add_info);
  10346         }
  10347         return rv;
  10348     }
  10349 
  10350     trunk_info->flags = add_info.flags;
  10351     trunk_info->psc = add_info.psc;
  10352     trunk_info->ipmc_psc = add_info.ipmc_psc;
  10353     trunk_info->dlf_index = add_info.dlf_index;
  10354     trunk_info->mc_index = add_info.mc_index;
  10355     trunk_info->ipmc_index = add_info.ipmc_index;
  10356     trunk_info->dynamic_size = add_info.dynamic_size;
  10357     trunk_info->dynamic_age = add_info.dynamic_age;
  10358     trunk_info->dynamic_load_exponent =
  10359         add_info.dynamic_load_exponent;
  10360     trunk_info->dynamic_expected_load_exponent =
  10361         add_info.dynamic_expected_load_exponent;
  10362 
  10363     *member_count = add_info.num_ports;
  10364 
  10365     if (member_max > 0) {
  10366         if (member_max < *member_count) {
  10367             *member_count = member_max;
  10368         }
  10369 
  10370         /* Construct member gport */
  10371         rv = bcm_esw_trunk_chip_info_get(unit, &chip_info);
  10372         if (BCM_FAILURE(rv)) {
  10373             _trident_trunk_add_info_member_free(&add_info);
  10374             return rv;
  10375         }
  10376         if (chip_info.trunk_fabric_id_min >= 0 &&
  10377             tid >= chip_info.trunk_fabric_id_min) {
  10378             higig_trunk = 1;
  10379         } else {
  10380             higig_trunk = 0;
  10381         }
  10382         rv = _bcm_esw_trunk_gport_construct(unit, higig_trunk,
  10383                 *member_count,
  10384                 add_info.tp, add_info.tm,
  10385                 add_info.tp);
  10386         if (BCM_FAILURE(rv)) {
  10387             _trident_trunk_add_info_member_free(&add_info);
  10388             return rv;
  10389         }
  10390 
  10391         for (i = 0; i < *member_count; i++) {
  10392             bcm_trunk_member_t_init(&member_array[i]);
  10393             member_array[i].flags = add_info.member_flags[i];
  10394             member_array[i].gport = add_info.tp[i];
  10395             member_array[i].dynamic_scaling_factor =
  10396                 add_info.dynamic_scaling_factor[i];
  10397             member_array[i].dynamic_load_weight =
  10398                 add_info.dynamic_load_weight[i];
  10399             member_array[i].dynamic_queue_size_weight=
  10400                 add_info.dynamic_queue_size_weight[i];
  10401         }
  10402 
  10403         _trident_trunk_add_info_member_free(&add_info);
  10404     }
  10405 
  10406     return rv;
  10407 }
  10408 
  10409 /*
  10410  * Function:
  10411  *	bcm_trident_trunk_mcast_join
  10412  * Purpose:
  10413  *	Add the trunk group to existing MAC multicast entry.
  10414  * Parameters:
  10415  *      unit - StrataSwitch PCI device unit number (driver internal).
  10416  *      tid - Trunk Id.
  10417  *      vid - Vlan ID.
  10418  *      mac - MAC address.
  10419  * Returns:
  10420  *	BCM_E_XXX
  10421  * Notes:
  10422  *      Applications have to remove the MAC multicast entry and re-add in with
  10423  *      new port bitmap to remove the trunk group from MAC multicast entry.
  10424  */
  10425 int
  10426 bcm_trident_trunk_mcast_join(int unit,
  10427         bcm_trunk_t tid,
  10428         bcm_vlan_t vid,
  10429         sal_mac_addr_t mac,
  10430         trunk_private_t *t_info)
  10431 {
  10432     trunk_bitmap_entry_t        trunk_bitmap_entry;
  10433     bcm_mcast_addr_t            mc_addr;
  10434     bcm_trunk_chip_info_t chip_info;
  10435    
  10436     /* Initialising and setting the mc_addr by bcm_mcast_addr_t_init() */
  10437     bcm_mcast_addr_t_init(&mc_addr, mac, vid); 
  10438 
  10439     BCM_IF_ERROR_RETURN(bcm_esw_trunk_chip_info_get(unit, &chip_info));
  10440     if ((tid >= chip_info.trunk_id_min) && (tid <= chip_info.trunk_id_max)) {
  10441         /* get the ports in the trunk group */
  10442         SOC_IF_ERROR_RETURN
  10443             (soc_mem_read(unit, TRUNK_BITMAPm, MEM_BLOCK_ANY, tid,
  10444                           &trunk_bitmap_entry));
  10445         soc_mem_pbmp_field_get(unit, TRUNK_BITMAPm, &trunk_bitmap_entry,
  10446                                TRUNK_BITMAPf, &mc_addr.pbmp);
  10447     } else {
  10448         return BCM_E_PARAM;
  10449     }
  10450 
  10451     /* Add the trunk group's ports to the multicast group. */
  10452     return bcm_esw_mcast_port_add(unit, &mc_addr);
  10453 }
  10454 
  10455 /*
  10456  * Function:
  10457  *      bcm_trident_hg_dlb_member_status_set
  10458  * Purpose:
  10459  *      Set Higig DLB member status.
  10460  * Parameters:
  10461  *      unit   - (IN) SOC unit number.
  10462  *      port   - (IN) Member port number.
  10463  *      status - (IN) Member status.
  10464  * Returns:
  10465  *      BCM_E_xxx
  10466  */
  10467 int
  10468 bcm_trident_hg_dlb_member_status_set(int unit, bcm_port_t port,
  10469         int status)
  10470 {
  10471     dlb_hgt_link_control_entry_t dlb_hgt_link_control_entry;
  10472     bcm_pbmp_t sw_port_state, override_port_map;
  10473 
  10474 #ifdef BCM_TRIUMPH3_SUPPORT
  10475     if (soc_feature(unit, soc_feature_hg_dlb_member_id)) {
  10476         dlb_hgt_port_member_map_entry_t port_member_map_entry;
  10477         int member_id;
  10478         dlb_hgt_member_sw_state_entry_t sw_state_entry;
  10479         int member_bitmap_width, alloc_size;
  10480         SHR_BITDCL *status_bitmap = NULL;
  10481         SHR_BITDCL *override_bitmap = NULL;
  10482 
  10483         /* Get Higig port's DLB member ID */
  10484         SOC_IF_ERROR_RETURN(READ_DLB_HGT_PORT_MEMBER_MAPm(unit, MEM_BLOCK_ANY,
  10485                     port, &port_member_map_entry));
  10486         if (soc_DLB_HGT_PORT_MEMBER_MAPm_field32_get(unit,
  10487                     &port_member_map_entry, VALIDf)) {
  10488             member_id = soc_DLB_HGT_PORT_MEMBER_MAPm_field32_get(unit,
  10489                     &port_member_map_entry, MEMBER_IDf);
  10490         } else {
  10491             /* The given Higig port is not assigned a DLB member ID */
  10492             return BCM_E_NOT_FOUND;
  10493         }
  10494 
  10495         /* Get status bitmap and override bitmap */
  10496         SOC_IF_ERROR_RETURN(READ_DLB_HGT_MEMBER_SW_STATEm(unit, MEM_BLOCK_ANY,
  10497                     0, &sw_state_entry));
  10498         member_bitmap_width = soc_mem_field_length(unit,
  10499                 DLB_HGT_MEMBER_SW_STATEm, MEMBER_BITMAPf);
  10500         alloc_size = SHR_BITALLOCSIZE(member_bitmap_width);
  10501         status_bitmap = sal_alloc(alloc_size, "DLB HGT member status bitmap"); 
  10502         if (NULL == status_bitmap) {
  10503             return BCM_E_MEMORY;
  10504         }
  10505         soc_DLB_HGT_MEMBER_SW_STATEm_field_get(unit, &sw_state_entry,
  10506                 MEMBER_BITMAPf, status_bitmap);
  10507 
  10508         override_bitmap = sal_alloc(alloc_size, "DLB HGT member override bitmap"); 
  10509         if (NULL == override_bitmap) {
  10510             sal_free(status_bitmap);
  10511             return BCM_E_MEMORY;
  10512         }
  10513         soc_DLB_HGT_MEMBER_SW_STATEm_field_get(unit, &sw_state_entry,
  10514                 OVERRIDE_MEMBER_BITMAPf, override_bitmap);
  10515 
  10516         /* Update status and override bitmaps */
  10517         switch (status) {
  10518             case BCM_TRUNK_DYNAMIC_MEMBER_FORCE_DOWN:
  10519                 SHR_BITSET(override_bitmap, member_id);
  10520                 SHR_BITCLR(status_bitmap, member_id);
  10521                 break;
  10522             case BCM_TRUNK_DYNAMIC_MEMBER_FORCE_UP:
  10523                 SHR_BITSET(override_bitmap, member_id);
  10524                 SHR_BITSET(status_bitmap, member_id);
  10525                 break;
  10526             case BCM_TRUNK_DYNAMIC_MEMBER_HW:
  10527                 SHR_BITCLR(override_bitmap, member_id);
  10528                 SHR_BITCLR(status_bitmap, member_id);
  10529                 break;
  10530             default:
  10531                 sal_free(status_bitmap);
  10532                 sal_free(override_bitmap);
  10533                 return BCM_E_PARAM;
  10534         }
  10535 
  10536         /* Write status and override bitmaps to hardware */
  10537         soc_DLB_HGT_MEMBER_SW_STATEm_field_set(unit, &sw_state_entry,
  10538                 MEMBER_BITMAPf, status_bitmap);
  10539         soc_DLB_HGT_MEMBER_SW_STATEm_field_set(unit, &sw_state_entry,
  10540                 OVERRIDE_MEMBER_BITMAPf, override_bitmap);
  10541         sal_free(status_bitmap);
  10542         sal_free(override_bitmap);
  10543         SOC_IF_ERROR_RETURN(WRITE_DLB_HGT_MEMBER_SW_STATEm(unit, MEM_BLOCK_ALL,
  10544                     0, &sw_state_entry));
  10545     } else
  10546 #endif /* BCM_TRIUMPH3_SUPPORT */
  10547     {
  10548         /* Get status bitmap and override bitmap */
  10549         SOC_IF_ERROR_RETURN(READ_DLB_HGT_LINK_CONTROLm(unit, MEM_BLOCK_ANY,
  10550                     0, &dlb_hgt_link_control_entry));
  10551         soc_mem_pbmp_field_get(unit, DLB_HGT_LINK_CONTROLm,
  10552                 &dlb_hgt_link_control_entry, SW_PORT_STATEf, &sw_port_state);
  10553         soc_mem_pbmp_field_get(unit, DLB_HGT_LINK_CONTROLm,
  10554                 &dlb_hgt_link_control_entry, SW_OVERRIDE_PORT_MAPf,
  10555                 &override_port_map);
  10556 
  10557         /* Update status and override bitmaps */
  10558         switch (status) {
  10559             case BCM_TRUNK_DYNAMIC_MEMBER_FORCE_DOWN:
  10560                 BCM_PBMP_PORT_ADD(override_port_map, port);
  10561                 BCM_PBMP_PORT_REMOVE(sw_port_state, port);
  10562                 break;
  10563             case BCM_TRUNK_DYNAMIC_MEMBER_FORCE_UP:
  10564                 BCM_PBMP_PORT_ADD(override_port_map, port);
  10565                 BCM_PBMP_PORT_ADD(sw_port_state, port);
  10566                 break;
  10567             case BCM_TRUNK_DYNAMIC_MEMBER_HW:
  10568                 BCM_PBMP_PORT_REMOVE(override_port_map, port);
  10569                 BCM_PBMP_PORT_REMOVE(sw_port_state, port);
  10570                 break;
  10571             default:
  10572                 return BCM_E_PARAM;
  10573         }
  10574 
  10575         /* Write status and override bitmaps to hardware */
  10576         soc_mem_pbmp_field_set(unit, DLB_HGT_LINK_CONTROLm,
  10577                 &dlb_hgt_link_control_entry, SW_PORT_STATEf, &sw_port_state);
  10578         soc_mem_pbmp_field_set(unit, DLB_HGT_LINK_CONTROLm,
  10579                 &dlb_hgt_link_control_entry, SW_OVERRIDE_PORT_MAPf,
  10580                 &override_port_map);
  10581         SOC_IF_ERROR_RETURN(WRITE_DLB_HGT_LINK_CONTROLm(unit, MEM_BLOCK_ALL,
  10582                     0, &dlb_hgt_link_control_entry));
  10583     }
  10584 
  10585     return BCM_E_NONE;
  10586 }
  10587 
  10588 /*
  10589  * Function:
  10590  *      bcm_trident_hg_dlb_member_status_get
  10591  * Purpose:
  10592  *      Get Higig DLB member status.
  10593  * Parameters:
  10594  *      unit - (IN) SOC unit number.
  10595  *      port - (IN) Higig port number.
  10596  *      status - (OUT) Member status.
  10597  * Returns:
  10598  *      BCM_E_xxx
  10599  */
  10600 int
  10601 bcm_trident_hg_dlb_member_status_get(int unit, bcm_port_t port,
  10602         int *status)
  10603 {
  10604     int rv = BCM_E_NONE;
  10605     dlb_hgt_link_control_entry_t dlb_hgt_link_control_entry;
  10606     bcm_pbmp_t sw_port_state, override_port_map, port_pbmp;
  10607     dlb_hgt_port_state_entry_t port_state_entry;
  10608     bcm_pbmp_t hw_port_state;
  10609 
  10610 #ifdef BCM_TRIUMPH3_SUPPORT
  10611     if (soc_feature(unit, soc_feature_hg_dlb_member_id)) {
  10612         dlb_hgt_port_member_map_entry_t port_member_map_entry;
  10613         int member_id;
  10614         dlb_hgt_member_sw_state_entry_t sw_state_entry;
  10615         int member_bitmap_width, alloc_size;
  10616         SHR_BITDCL *status_bitmap = NULL;
  10617         SHR_BITDCL *override_bitmap = NULL;
  10618         uint32 hw_state_reg, hw_state_reg_bitmap;
  10619 
  10620         /* Get Higig port's DLB member ID */
  10621         SOC_IF_ERROR_RETURN(READ_DLB_HGT_PORT_MEMBER_MAPm(unit, MEM_BLOCK_ANY,
  10622                     port, &port_member_map_entry));
  10623         if (soc_DLB_HGT_PORT_MEMBER_MAPm_field32_get(unit,
  10624                     &port_member_map_entry, VALIDf)) {
  10625             member_id = soc_DLB_HGT_PORT_MEMBER_MAPm_field32_get(unit,
  10626                     &port_member_map_entry, MEMBER_IDf);
  10627         } else {
  10628             /* The given Higig port is not assigned a DLB member ID */
  10629             return BCM_E_NOT_FOUND;
  10630         }
  10631 
  10632         /* Get status bitmap and override bitmap */
  10633         SOC_IF_ERROR_RETURN(READ_DLB_HGT_MEMBER_SW_STATEm(unit, MEM_BLOCK_ANY,
  10634                     0, &sw_state_entry));
  10635         member_bitmap_width = soc_mem_field_length(unit,
  10636                 DLB_HGT_MEMBER_SW_STATEm, MEMBER_BITMAPf);
  10637         alloc_size = SHR_BITALLOCSIZE(member_bitmap_width);
  10638         status_bitmap = sal_alloc(alloc_size, "DLB HGT member status bitmap"); 
  10639         if (NULL == status_bitmap) {
  10640             return BCM_E_MEMORY;
  10641         }
  10642         soc_DLB_HGT_MEMBER_SW_STATEm_field_get(unit, &sw_state_entry,
  10643                 MEMBER_BITMAPf, status_bitmap);
  10644 
  10645         override_bitmap = sal_alloc(alloc_size, "DLB HGT member override bitmap"); 
  10646         if (NULL == override_bitmap) {
  10647             sal_free(status_bitmap);
  10648             return BCM_E_MEMORY;
  10649         }
  10650         soc_DLB_HGT_MEMBER_SW_STATEm_field_get(unit, &sw_state_entry,
  10651                 OVERRIDE_MEMBER_BITMAPf, override_bitmap);
  10652 
  10653         /* Derive status from software override and status bitmaps or
  10654          * hardware state bitmap.
  10655          */
  10656         if (SHR_BITGET(override_bitmap, member_id)) {
  10657             if (SHR_BITGET(status_bitmap, member_id)) {
  10658                 *status = BCM_TRUNK_DYNAMIC_MEMBER_FORCE_UP;
  10659             } else {
  10660                 *status = BCM_TRUNK_DYNAMIC_MEMBER_FORCE_DOWN;
  10661             }
  10662         } else {
  10663 #ifdef BCM_TRIDENT2_SUPPORT
  10664             if (soc_mem_is_valid(unit, DLB_HGT_MEMBER_HW_STATEm)) {
  10665                 dlb_hgt_member_hw_state_entry_t hw_state_entry;
  10666                 SHR_BITDCL *hw_state_bitmap = NULL;
  10667 
  10668                 rv = READ_DLB_HGT_MEMBER_HW_STATEm(unit, MEM_BLOCK_ANY, 0,
  10669                         &hw_state_entry);
  10670                 if (BCM_FAILURE(rv)) {
  10671                     sal_free(status_bitmap);
  10672                     sal_free(override_bitmap);
  10673                     return rv;
  10674                 }
  10675                 hw_state_bitmap = sal_alloc(alloc_size, "DLB HGT HW status bitmap"); 
  10676                 if (NULL == hw_state_bitmap) {
  10677                     sal_free(status_bitmap);
  10678                     sal_free(override_bitmap);
  10679                     return BCM_E_MEMORY;
  10680                 }
  10681                 soc_DLB_HGT_MEMBER_HW_STATEm_field_get(unit, &hw_state_entry,
  10682                         BITMAPf, hw_state_bitmap);
  10683                 if (SHR_BITGET(hw_state_bitmap, member_id)) {
  10684                     *status = BCM_TRUNK_DYNAMIC_MEMBER_HW_UP;
  10685                 } else {
  10686                     *status = BCM_TRUNK_DYNAMIC_MEMBER_HW_DOWN;
  10687                 }
  10688                 sal_free(hw_state_bitmap);
  10689             } else
  10690 #endif /* BCM_TRIDENT2_SUPPORT */
  10691             {
  10692                 rv = READ_DLB_HGT_MEMBER_HW_STATEr(unit, &hw_state_reg); 
  10693                 if (BCM_FAILURE(rv)) {
  10694                     sal_free(status_bitmap);
  10695                     sal_free(override_bitmap);
  10696                     return rv;
  10697                 }
  10698                 hw_state_reg_bitmap = soc_reg_field_get(unit,
  10699                         DLB_HGT_MEMBER_HW_STATEr, hw_state_reg, BITMAPf);
  10700                 if (hw_state_reg_bitmap & (1 << member_id)) {
  10701                     *status = BCM_TRUNK_DYNAMIC_MEMBER_HW_UP;
  10702                 } else {
  10703                     *status = BCM_TRUNK_DYNAMIC_MEMBER_HW_DOWN;
  10704                 }
  10705             }
  10706         }
  10707 
  10708         sal_free(status_bitmap);
  10709         sal_free(override_bitmap);
  10710 
  10711     } else
  10712 #endif /* BCM_TRIUMPH3_SUPPORT */
  10713     {
  10714         /* Get status bitmap and override bitmap */
  10715         SOC_IF_ERROR_RETURN(READ_DLB_HGT_LINK_CONTROLm(unit, MEM_BLOCK_ANY,
  10716                     0, &dlb_hgt_link_control_entry));
  10717         soc_mem_pbmp_field_get(unit, DLB_HGT_LINK_CONTROLm,
  10718                 &dlb_hgt_link_control_entry, SW_PORT_STATEf, &sw_port_state);
  10719         soc_mem_pbmp_field_get(unit, DLB_HGT_LINK_CONTROLm,
  10720                 &dlb_hgt_link_control_entry, SW_OVERRIDE_PORT_MAPf,
  10721                 &override_port_map);
  10722 
  10723         /* Derive status from software override and status bitmaps or
  10724          * hardware state bitmap.
  10725          */
  10726         BCM_PBMP_PORT_SET(port_pbmp, port);
  10727         BCM_PBMP_AND(override_port_map, port_pbmp);
  10728         BCM_PBMP_AND(sw_port_state, port_pbmp);
  10729         if (BCM_PBMP_NOT_NULL(override_port_map)) {
  10730             if (BCM_PBMP_NOT_NULL(sw_port_state)) {
  10731                 *status = BCM_TRUNK_DYNAMIC_MEMBER_FORCE_UP;
  10732             } else {
  10733                 *status = BCM_TRUNK_DYNAMIC_MEMBER_FORCE_DOWN;
  10734             }
  10735         } else {
  10736             SOC_IF_ERROR_RETURN(READ_DLB_HGT_PORT_STATEm(unit, MEM_BLOCK_ANY,
  10737                         0, &port_state_entry)); 
  10738             soc_mem_pbmp_field_get(unit, DLB_HGT_PORT_STATEm,
  10739                     &port_state_entry, BITMAPf, &hw_port_state);
  10740             BCM_PBMP_AND(hw_port_state, port_pbmp);
  10741             if (BCM_PBMP_NOT_NULL(hw_port_state)) {
  10742                 *status = BCM_TRUNK_DYNAMIC_MEMBER_HW_UP;
  10743             } else {
  10744                 *status = BCM_TRUNK_DYNAMIC_MEMBER_HW_DOWN;
  10745             }
  10746         }
  10747     }
  10748 
  10749     return rv;
  10750 }
  10751 
  10752 #ifdef BCM_TRIUMPH3_SUPPORT
  10753 /*
  10754  * Function:
  10755  *      bcm_tr3_hg_dlb_ethertype_set
  10756  * Purpose:
  10757  *      Set the Ethertypes that are eligible or ineligible for
  10758  *      Higig dynamic load balancing.
  10759  * Parameters:
  10760  *      unit - (IN) Unit number.
  10761  *      flags - (IN) BCM_TRUNK_DYNAMIC_ETHERTYPE_xxx flags.
  10762  *      ethertype_count - (IN) Number of elements in ethertype_array.
  10763  *      ethertype_array - (IN) Array of Ethertypes.
  10764  * Returns:
  10765  *      BCM_E_XXX
  10766  */
  10767 int 
  10768 bcm_tr3_hg_dlb_ethertype_set(
  10769     int unit, 
  10770     uint32 flags, 
  10771     int ethertype_count, 
  10772     int *ethertype_array)
  10773 {
  10774     uint32 measure_control_reg;
  10775     int i, j;
  10776     dlb_hgt_ethertype_eligibility_map_entry_t ethertype_entry;
  10777 
  10778     /* Input check */
  10779     if (ethertype_count > soc_mem_index_count(unit,
  10780                 DLB_HGT_ETHERTYPE_ELIGIBILITY_MAPm)) {
  10781         return BCM_E_RESOURCE;
  10782     }
  10783 
  10784     /* Update quality measure control register */
  10785     SOC_IF_ERROR_RETURN
  10786         (READ_DLB_HGT_QUALITY_MEASURE_CONTROLr(unit, &measure_control_reg));
  10787     soc_reg_field_set(unit, DLB_HGT_QUALITY_MEASURE_CONTROLr,
  10788             &measure_control_reg, ETHERTYPE_ELIGIBILITY_CONFIGf,
  10789             flags & BCM_TRUNK_DYNAMIC_ETHERTYPE_ELIGIBLE ? 1 : 0);
  10790     soc_reg_field_set(unit, DLB_HGT_QUALITY_MEASURE_CONTROLr,
  10791             &measure_control_reg, INNER_OUTER_ETHERTYPE_SELECTIONf,
  10792             flags & BCM_TRUNK_DYNAMIC_ETHERTYPE_INNER ? 1 : 0);
  10793     SOC_IF_ERROR_RETURN
  10794         (WRITE_DLB_HGT_QUALITY_MEASURE_CONTROLr(unit, measure_control_reg));
  10795 
  10796     /* Update Ethertype eligibility map table */
  10797     for (i = 0; i < ethertype_count; i++) {
  10798         sal_memset(&ethertype_entry, 0,
  10799                 sizeof(dlb_hgt_ethertype_eligibility_map_entry_t));
  10800         soc_DLB_HGT_ETHERTYPE_ELIGIBILITY_MAPm_field32_set(unit,
  10801                 &ethertype_entry, VALIDf, 1);
  10802         soc_DLB_HGT_ETHERTYPE_ELIGIBILITY_MAPm_field32_set(unit,
  10803                 &ethertype_entry, ETHERTYPEf, ethertype_array[i]);
  10804         SOC_IF_ERROR_RETURN(WRITE_DLB_HGT_ETHERTYPE_ELIGIBILITY_MAPm(unit,
  10805                     MEM_BLOCK_ALL, i, &ethertype_entry));
  10806     }
  10807 
  10808     /* Zero out remaining entries of Ethertype eligibility map table */
  10809     for (j = i; j < soc_mem_index_count(unit,
  10810                 DLB_HGT_ETHERTYPE_ELIGIBILITY_MAPm); j++) {
  10811         SOC_IF_ERROR_RETURN(WRITE_DLB_HGT_ETHERTYPE_ELIGIBILITY_MAPm(unit,
  10812                     MEM_BLOCK_ALL, j, soc_mem_entry_null(unit,
  10813                         DLB_HGT_ETHERTYPE_ELIGIBILITY_MAPm)));
  10814     }
  10815 
  10816     return BCM_E_NONE;
  10817 }
  10818 
  10819 /*
  10820  * Function:
  10821  *      bcm_tr3_hg_dlb_ethertype_get
  10822  * Purpose:
  10823  *      Get the Ethertypes that are eligible or ineligible for
  10824  *      Higig dynamic load balancing.
  10825  * Parameters:
  10826  *      unit - (IN) Unit number.
  10827  *      flags - (INOUT) BCM_TRUNK_DYNAMIC_ETHERTYPE_xxx flags.
  10828  *      ethertype_max - (IN) Number of elements in ethertype_array.
  10829  *      ethertype_array - (OUT) Array of Ethertypes.
  10830  *      ethertype_count - (OUT) Number of elements returned in ethertype_array.
  10831  * Returns:
  10832  *      BCM_E_XXX
  10833  */
  10834 int 
  10835 bcm_tr3_hg_dlb_ethertype_get(
  10836     int unit, 
  10837     uint32 *flags, 
  10838     int ethertype_max, 
  10839     int *ethertype_array, 
  10840     int *ethertype_count)
  10841 {
  10842     uint32 measure_control_reg;
  10843     int i;
  10844     int ethertype;
  10845     dlb_hgt_ethertype_eligibility_map_entry_t ethertype_entry;
  10846 
  10847     *ethertype_count = 0;
  10848 
  10849     /* Get flags */
  10850     SOC_IF_ERROR_RETURN
  10851         (READ_DLB_HGT_QUALITY_MEASURE_CONTROLr(unit, &measure_control_reg));
  10852     if (soc_reg_field_get(unit, DLB_HGT_QUALITY_MEASURE_CONTROLr,
  10853                 measure_control_reg, ETHERTYPE_ELIGIBILITY_CONFIGf)) {
  10854         *flags |= BCM_TRUNK_DYNAMIC_ETHERTYPE_ELIGIBLE;
  10855     }
  10856     if (soc_reg_field_get(unit, DLB_HGT_QUALITY_MEASURE_CONTROLr,
  10857                 measure_control_reg, INNER_OUTER_ETHERTYPE_SELECTIONf)) {
  10858         *flags |= BCM_TRUNK_DYNAMIC_ETHERTYPE_INNER;
  10859     }
  10860 
  10861     /* Get Ethertypes */
  10862     for (i = 0; i < soc_mem_index_count(unit,
  10863                 DLB_HGT_ETHERTYPE_ELIGIBILITY_MAPm); i++) {
  10864         SOC_IF_ERROR_RETURN(READ_DLB_HGT_ETHERTYPE_ELIGIBILITY_MAPm(unit,
  10865                     MEM_BLOCK_ANY, i, &ethertype_entry));
  10866         if (soc_DLB_HGT_ETHERTYPE_ELIGIBILITY_MAPm_field32_get(unit,
  10867                     &ethertype_entry, VALIDf)) {
  10868             ethertype = soc_DLB_HGT_ETHERTYPE_ELIGIBILITY_MAPm_field32_get(unit,
  10869                     &ethertype_entry, ETHERTYPEf);
  10870             if (NULL != ethertype_array) {
  10871                 ethertype_array[*ethertype_count] = ethertype;
  10872             }
  10873             (*ethertype_count)++;
  10874             if ((ethertype_max > 0) && (*ethertype_count == ethertype_max)) {
  10875                 break;
  10876             }
  10877         }
  10878     }
  10879 
  10880     return BCM_E_NONE;
  10881 }
  10882 
  10883 #endif /* BCM_TRIUMPH3_SUPPORT */
  10884 
  10885 /* ----------------------------------------------------------------------------- 
  10886  *
  10887  * Warm Boot routines
  10888  *
  10889  * ----------------------------------------------------------------------------- 
  10890  */
  10891 #ifdef BCM_WARM_BOOT_SUPPORT
  10892 
  10893 void
  10894 _bcm_trident_hw_failover_num_ports_set(int unit, bcm_trunk_t tid,
  10895                                        int hg_trunk, uint16 num_ports)
  10896 {
  10897     bcm_trunk_chip_info_t chip_info;
  10898     int tid_ix;
  10899 
  10900     (void) bcm_esw_trunk_chip_info_get(unit, &chip_info);
  10901     tid_ix = tid + (hg_trunk ? chip_info.trunk_group_count : 0);
  10902     _trident_trunk_hwfail[unit]->hw_tinfo[tid_ix].num_ports = num_ports;
  10903 
  10904     return;
  10905 }
  10906 
  10907 uint16
  10908 _bcm_trident_hw_failover_num_ports_get(int unit, bcm_trunk_t tid,
  10909                                        int hg_trunk)
  10910 {
  10911     bcm_trunk_chip_info_t chip_info;
  10912     int tid_ix;
  10913     uint16 num_ports;
  10914 
  10915     (void) bcm_esw_trunk_chip_info_get(unit, &chip_info);
  10916     tid_ix = tid + (hg_trunk ? chip_info.trunk_group_count : 0);
  10917     num_ports = _trident_trunk_hwfail[unit]->hw_tinfo[tid_ix].num_ports;
  10918 
  10919     return num_ports;
  10920 }
  10921 
  10922 int
  10923 _bcm_trident_hw_failover_flags_set(int unit, bcm_trunk_t tid,
  10924                                    int port_index, int hg_trunk, uint8 flags)
  10925 {
  10926     bcm_trunk_chip_info_t chip_info;
  10927     int tid_ix;
  10928     _trident_hw_tinfo_t *hwft;
  10929 
  10930     BCM_IF_ERROR_RETURN(bcm_esw_trunk_chip_info_get(unit, &chip_info));
  10931     tid_ix = tid + (hg_trunk ? chip_info.trunk_group_count : 0);
  10932     hwft = &(_trident_trunk_hwfail[unit]->hw_tinfo[tid_ix]);
  10933 
  10934     if (NULL == hwft->flags) {
  10935         hwft->flags = sal_alloc(sizeof(uint32) * hwft->num_ports,
  10936                 "hw_tinfo_flags");
  10937         if (hwft->flags == NULL) {
  10938             return BCM_E_MEMORY;
  10939         }
  10940     }
  10941     hwft->flags[port_index] = flags;
  10942 
  10943     return BCM_E_NONE;
  10944 }
  10945 
  10946 uint8
  10947 _bcm_trident_hw_failover_flags_get(int unit, bcm_trunk_t tid,
  10948                                    int port_index, int hg_trunk)
  10949 {
  10950     bcm_trunk_chip_info_t chip_info;
  10951     int tid_ix;
  10952     uint8 flags;
  10953     _trident_hw_tinfo_t *hwft;
  10954 
  10955     (void) bcm_esw_trunk_chip_info_get(unit, &chip_info);
  10956     tid_ix = tid + (hg_trunk ? chip_info.trunk_group_count : 0);
  10957     hwft = &(_trident_trunk_hwfail[unit]->hw_tinfo[tid_ix]);
  10958 
  10959     if (NULL != hwft->flags) {
  10960         flags = _trident_trunk_hwfail[unit]->hw_tinfo[tid_ix].flags[port_index];
  10961     } else {
  10962         flags = 0;
  10963     }
  10964 
  10965     return flags;
  10966 }
  10967 
  10968 int
  10969 _bcm_trident_trunk_member_info_set(int unit, bcm_trunk_t tid,
  10970                                 uint16 num_ports,
  10971                                 uint16 *modport,
  10972                                 uint32 *member_flags)
  10973 {
  10974     int i;
  10975 
  10976     if (MEMBER_INFO(unit, tid).modport) {
  10977         sal_free(MEMBER_INFO(unit, tid).modport);
  10978         MEMBER_INFO(unit, tid).modport = NULL;
  10979     }
  10980     if (MEMBER_INFO(unit, tid).member_flags) {
  10981         sal_free(MEMBER_INFO(unit, tid).member_flags);
  10982         MEMBER_INFO(unit, tid).member_flags = NULL;
  10983     }
  10984 
  10985     MEMBER_INFO(unit, tid).num_ports = num_ports;
  10986 
  10987     MEMBER_INFO(unit, tid).modport = sal_alloc(
  10988             sizeof(uint16) * MEMBER_INFO(unit, tid).num_ports,
  10989             "member info modport");
  10990     if (NULL == MEMBER_INFO(unit, tid).modport) {
  10991         return BCM_E_MEMORY;
  10992     }
  10993 
  10994     MEMBER_INFO(unit, tid).member_flags = sal_alloc(
  10995             sizeof(uint32) * MEMBER_INFO(unit, tid).num_ports,
  10996             "member info flags");
  10997     if (NULL == MEMBER_INFO(unit, tid).member_flags) {
  10998         sal_free(MEMBER_INFO(unit, tid).modport);
  10999         MEMBER_INFO(unit, tid).modport = NULL;
  11000         return BCM_E_MEMORY;
  11001     }
  11002 
  11003     for (i = 0; i < MEMBER_INFO(unit, tid).num_ports; i++) {
  11004         MEMBER_INFO(unit, tid).modport[i] = modport[i];
  11005         MEMBER_INFO(unit, tid).member_flags[i] = member_flags[i];
  11006     }
  11007 
  11008     MEMBER_INFO(unit, tid).recovered_from_scache = 1;
  11009 
  11010     return BCM_E_NONE;
  11011 }
  11012 
  11013 int
  11014 _bcm_trident_trunk_member_info_get(int unit, bcm_trunk_t tid,
  11015                                 uint16 array_size,
  11016                                 uint16 *modport,
  11017                                 uint32 *member_flags,
  11018                                 uint16 *num_ports)
  11019 {
  11020     int i;
  11021 
  11022     if (NULL == num_ports) {
  11023         return BCM_E_PARAM;
  11024     }
  11025     *num_ports = MEMBER_INFO(unit, tid).num_ports;
  11026 
  11027     if (array_size == 0) {
  11028         return BCM_E_NONE;
  11029     }
  11030 
  11031     for (i = 0; i < array_size; i++) {
  11032         if (i == *num_ports) {
  11033            break;
  11034         } 
  11035         modport[i] = MEMBER_INFO(unit, tid).modport[i];
  11036         member_flags[i] = MEMBER_INFO(unit, tid).member_flags[i];
  11037     }
  11038 
  11039     return BCM_E_NONE;
  11040 }
  11041 
  11042 STATIC int
  11043 _bcm_trident_trunk_rtag_to_psc(int unit, int rtag, int *psc)
  11044 {
  11045     if (7 == rtag) {
  11046         if (soc_feature(unit, soc_feature_port_flow_hash)) {
  11047             *psc = BCM_TRUNK_PSC_PORTFLOW;
  11048         } else if (soc_feature(unit, soc_feature_port_trunk_index)) {
  11049             *psc = BCM_TRUNK_PSC_PORTINDEX;
  11050         } else {
  11051             return BCM_E_PARAM;
  11052         }
  11053     } else if (0 <= rtag) {
  11054         /* HW and SW values match */
  11055         *psc = rtag;
  11056     } else {
  11057         /* Unknown rtag value */
  11058         return BCM_E_PARAM;
  11059     }
  11060 
  11061     return BCM_E_NONE;
  11062 }
  11063 
  11064 /*
  11065  * Function:
  11066  *      _bcm_trident_trunk_mod_port_map_reinit
  11067  * Purpose:
  11068  *      Reinitialize the software cache for the SOURCE_TRUNK_MAP_TABLE.
  11069  *      Recover trunk members with egress disable flag set.
  11070  * Parameters:
  11071  *      unit - (IN) SOC unit number. 
  11072  *      mod - (IN) Module ID.
  11073  *      base_index - (IN) Module ID's base index.
  11074  *      num_ports - (IN) Number of ports in the given module.
  11075  * Returns:
  11076  *      BCM_X_XXX
  11077  * Notes:
  11078  *      This function is called during stacking module reinit, since
  11079  *      the number of ports in a given module is not known until then.
  11080  */
  11081 int 
  11082 _bcm_trident_trunk_mod_port_map_reinit(int unit, bcm_module_t mod,
  11083         int base_index, int num_ports) 
  11084 {
  11085     bcm_port_t port;
  11086     int	rv = BCM_E_NONE;
  11087     source_trunk_map_table_entry_t stm; 
  11088     int port_type;
  11089     bcm_trunk_t tid;
  11090     int array_size;
  11091     bcm_module_t *mod_array = NULL;
  11092     bcm_port_t *port_array = NULL;
  11093     uint32 *flags_array = NULL;
  11094     int i, found;
  11095     soc_field_t tgid_f = TGIDf;
  11096 
  11097     if (soc_mem_field_valid(unit, SOURCE_TRUNK_MAP_TABLEm, SRC_TGIDf)) {
  11098         tgid_f = SRC_TGIDf;
  11099     }
  11100     /*
  11101      * Recover from SOURCE_TRUNK_MAP tables.
  11102      */
  11103     for (port = 0; port < num_ports; port++) {
  11104 
  11105         rv = soc_mem_read(unit, SOURCE_TRUNK_MAP_TABLEm, MEM_BLOCK_ANY,
  11106                 base_index + port, &stm);
  11107         if (BCM_FAILURE(rv)) {
  11108             break;
  11109         }
  11110 
  11111         port_type = soc_SOURCE_TRUNK_MAP_TABLEm_field32_get(unit, &stm,
  11112                 PORT_TYPEf);
  11113         if (port_type != 1) {
  11114             continue;
  11115         }
  11116 
  11117         tid = soc_SOURCE_TRUNK_MAP_TABLEm_field32_get(unit, &stm, tgid_f);
  11118 
  11119         /* Recover source trunk map cache */
  11120         rv = _bcm_trident_trunk_mod_port_map_set(unit, mod, port, tid);  
  11121         if (BCM_FAILURE(rv)) {
  11122             break;
  11123         }
  11124 
  11125         /* Allocate arrays that can accommodate an additional member,
  11126          * in case a new member needs to be added to the trunk group.
  11127          */
  11128         array_size = MEMBER_INFO(unit, tid).num_ports + 1;
  11129         mod_array = sal_alloc(sizeof(bcm_module_t) * array_size, "mod_array");
  11130         if (mod_array == NULL) {
  11131             rv = BCM_E_MEMORY;
  11132             break;
  11133         }
  11134         sal_memset(mod_array, 0, sizeof(bcm_module_t) * array_size); 
  11135 
  11136         port_array = sal_alloc(sizeof(bcm_port_t) * array_size, "port_array");
  11137         if (port_array == NULL) {
  11138             rv = BCM_E_MEMORY;
  11139             break;
  11140         }
  11141         sal_memset(port_array, 0, sizeof(bcm_port_t) * array_size); 
  11142 
  11143         flags_array = sal_alloc(sizeof(uint32) * array_size, "flags_array");
  11144         if (flags_array == NULL) {
  11145             rv = BCM_E_MEMORY;
  11146             break;
  11147         }
  11148         sal_memset(flags_array, 0, sizeof(uint32) * array_size); 
  11149 
  11150         /* Try to find mod-port in the trunk group */
  11151         found = 0; 
  11152         for (i = 0; i < MEMBER_INFO(unit, tid).num_ports; i++) {
  11153             mod_array[i] = MEMBER_INFO(unit, tid).modport[i] >> 8;
  11154             port_array[i] = MEMBER_INFO(unit, tid).modport[i] & 0xff;
  11155             flags_array[i] = MEMBER_INFO(unit, tid).member_flags[i];
  11156             if (port_array[i] == port && mod_array[i] == mod) {
  11157                 found = 1;
  11158                 break;
  11159             }
  11160         }
  11161 
  11162         /* If the mod-port was not found, then add it with
  11163          * EGRESS_DISABLE flag set.
  11164          */  
  11165         if (!found && !MEMBER_INFO(unit, tid).recovered_from_scache) {
  11166             /* Find where to insert */
  11167             for (i = 0; i < MEMBER_INFO(unit, tid).num_ports; i++) {
  11168                 if (port > port_array[i] || mod != mod_array[i]) {
  11169                     continue;
  11170                 } 
  11171                 break;
  11172             }
  11173 
  11174             /* Insert at the required location in sw state */
  11175             mod_array[i] = mod;
  11176             port_array[i] = port;
  11177             flags_array[i] |= BCM_TRUNK_MEMBER_EGRESS_DISABLE;
  11178 
  11179             /* Copy remaining members as is */
  11180             for (; i < MEMBER_INFO(unit, tid).num_ports; i++) {
  11181                 mod_array[i+1] = MEMBER_INFO(unit, tid).modport[i] >> 8;
  11182                 port_array[i+1] = MEMBER_INFO(unit, tid).modport[i] & 0xff;
  11183                 flags_array[i+1] = MEMBER_INFO(unit, tid).member_flags[i];
  11184             }
  11185 
  11186             MEMBER_INFO(unit, tid).num_ports++;
  11187 
  11188             if (MEMBER_INFO(unit, tid).modport) {
  11189                 sal_free(MEMBER_INFO(unit, tid).modport);
  11190                 MEMBER_INFO(unit, tid).modport = NULL;
  11191             }
  11192             if (MEMBER_INFO(unit, tid).member_flags) {
  11193                 sal_free(MEMBER_INFO(unit, tid).member_flags);
  11194                 MEMBER_INFO(unit, tid).member_flags = NULL;
  11195             }
  11196 
  11197             MEMBER_INFO(unit, tid).modport = sal_alloc(
  11198                     sizeof(uint16) * MEMBER_INFO(unit, tid).num_ports,
  11199                     "member info modport");
  11200             if (NULL == MEMBER_INFO(unit, tid).modport) {
  11201                 rv = BCM_E_MEMORY;
  11202                 break;
  11203             }
  11204 
  11205             MEMBER_INFO(unit, tid).member_flags = sal_alloc(
  11206                     sizeof(uint32) * MEMBER_INFO(unit, tid).num_ports, "member info flags");
  11207             if (NULL == MEMBER_INFO(unit, tid).member_flags) {
  11208                 sal_free(MEMBER_INFO(unit, tid).modport);
  11209                 MEMBER_INFO(unit, tid).modport = NULL;
  11210                 rv = BCM_E_MEMORY;
  11211                 break;
  11212             }
  11213 
  11214             for (i = 0; i < MEMBER_INFO(unit, tid).num_ports; i++) {
  11215                 MEMBER_INFO(unit, tid).modport[i] = (mod_array[i] << 8) |
  11216                     port_array[i];
  11217                 MEMBER_INFO(unit, tid).member_flags[i] = flags_array[i];
  11218             }
  11219         } 
  11220 
  11221         sal_free(mod_array);
  11222         mod_array = NULL;
  11223         sal_free(port_array);
  11224         port_array = NULL;
  11225         sal_free(flags_array);
  11226         flags_array = NULL;
  11227     }
  11228 
  11229     if (mod_array) {
  11230         sal_free(mod_array);
  11231     }
  11232     if (port_array) {
  11233         sal_free(port_array);
  11234     }
  11235     if (flags_array) {
  11236         sal_free(flags_array);
  11237     }
  11238 
  11239     return rv;
  11240 }
  11241 
  11242 /*
  11243  * Handle state recovery for front panel trunks
  11244  */
  11245 int
  11246 _bcm_trident_trunk_lag_reinit(int unit, int ngroups_fp, trunk_private_t *trunk_info)
  11247 {
  11248     int rv = BCM_E_NONE;
  11249     int tid, tid_get;
  11250     int ptype;
  11251     trunk_group_entry_t tg_entry;
  11252     trunk_member_entry_t tm_entry;
  11253     int mod_id = 0, port_num = 0;
  11254     int base_ptr, tg_size, rtag;
  11255     bcm_module_t *egr_hw_mods;
  11256     bcm_port_t *egr_hw_ports;
  11257     uint32 *egr_member_flags;
  11258     trunk_member_entry_t trunk_member_entry;
  11259     source_trunk_map_table_entry_t stm;
  11260     int stm_idx;
  11261     int i, j, mod_is_local;
  11262     int hwf_rtag, hwf_psc;
  11263     _trident_hw_tinfo_t *hwft;
  11264     int num_egr_ports;
  11265     int num_entries;
  11266     int num_ports_temp = 0;
  11267     soc_field_t tgid_f = TGIDf;
  11268 #ifdef BCM_TRIDENT2_SUPPORT
  11269     trunk_private_t *trunk_info_temp = trunk_info;
  11270 #endif
  11271 
  11272     /*
  11273      * On warmboot, reserve entry "0" only if indicated so
  11274      * by the flag.
  11275      * Else, reserve entry "0" if indicated by the HW entry
  11276      * Else, do not reserve entry "0".
  11277      */
  11278     if (bcm_trident_trunk_mbr_zero_rsvd[unit] == TRUE) {
  11279         _BCM_FP_TRUNK_MEMBER_USED_SET(unit, 0);
  11280     } else {
  11281         SOC_IF_ERROR_RETURN
  11282             (READ_TRUNK_MEMBERm(unit, MEM_BLOCK_ANY, 0, &tm_entry));
  11283         mod_id = soc_TRUNK_MEMBERm_field32_get(unit, &tm_entry, MODULE_IDf);
  11284         port_num = soc_TRUNK_MEMBERm_field32_get(unit, &tm_entry, PORT_NUMf);
  11285         if ((mod_id == 0xff) && (port_num == 0x7f)) {
  11286             bcm_trident_trunk_mbr_zero_rsvd[unit] = TRUE;
  11287             _BCM_FP_TRUNK_MEMBER_USED_SET(unit, 0);
  11288         }
  11289     }
  11290 
  11291     if (soc_mem_field_valid(unit, SOURCE_TRUNK_MAP_TABLEm, SRC_TGIDf)) {
  11292         tgid_f = SRC_TGIDf;
  11293     }
  11294 
  11295     for (tid = 0; tid < ngroups_fp; tid++, trunk_info++) {
  11296 
  11297         SOC_IF_ERROR_RETURN
  11298             (READ_TRUNK_GROUPm(unit, MEM_BLOCK_ANY, tid, &tg_entry));
  11299 
  11300         base_ptr = soc_TRUNK_GROUPm_field32_get(unit, &tg_entry, BASE_PTRf);
  11301         tg_size = 1 + soc_TRUNK_GROUPm_field32_get(unit, &tg_entry, TG_SIZEf);
  11302         rtag = soc_TRUNK_GROUPm_field32_get(unit, &tg_entry, RTAGf);
  11303         
  11304         num_ports_temp = MEMBER_INFO(unit, tid).num_ports;
  11305         /* if BCM_TRUNK_MEMBER_EGRESS_DISABLE is set, the rtag will be zero.
  11306            we should not return if a trunk has some ports and even if rtag is 0 */
  11307         if (0 == rtag && num_ports_temp == 0 ) { 
  11308             /* Invalid trunk group */
  11309             continue;
  11310         }
  11311 
  11312         /* Recover trunk_info */
  11313         trunk_info->tid = tid;
  11314         trunk_info->in_use = TRUE;
  11315         if(rtag != 0)  {
  11316             BCM_IF_ERROR_RETURN
  11317                 (_bcm_trident_trunk_rtag_to_psc(unit, rtag, &trunk_info->psc));
  11318         }
  11319         trunk_info->rtag = rtag;
  11320 
  11321 #ifdef BCM_APACHE_SUPPORT
  11322         trunk_info->rr_lag_select = -1;
  11323         if (soc_feature(unit, soc_feature_apache_round_robin_fp_lag)) {
  11324             if (soc_TRUNK_GROUPm_field32_get(unit, &tg_entry, RR_LB_ENABLEf)) {
  11325                 trunk_info->rr_lag_select = soc_TRUNK_GROUPm_field32_get(unit, &tg_entry, RR_LB_COUNTER_SELECTf);
  11326             }
  11327         }
  11328 #endif /* BCM_APACHE_SUPPORT */
  11329 
  11330         /* Recover trunk member table bookkeeping info */
  11331         num_entries = tg_size;
  11332         if (rtag >= 1 && rtag <= 6) {
  11333 #ifdef BCM_KATANA_SUPPORT
  11334             if (SOC_IS_KATANAX(unit)) {
  11335                 num_entries = _BCM_KATANA_FP_TRUNK_RTAG1_6_MAX_PORTCNT;
  11336             } else
  11337 #endif
  11338             if (soc_feature(unit,
  11339                         soc_feature_rtag1_6_max_portcnt_less_than_rtag7)) { 
  11340                 num_entries = _BCM_TD_FP_TRUNK_RTAG1_6_MAX_PORTCNT;
  11341             }
  11342         } 
  11343         _BCM_FP_TRUNK_MEMBER_USED_SET_RANGE(unit, base_ptr, num_entries);
  11344 
  11345         /* Recover trunk members */
  11346         if (MEMBER_INFO(unit, tid).recovered_from_scache) {
  11347             egr_hw_mods = sal_alloc(sizeof(bcm_module_t) *
  11348                     MEMBER_INFO(unit, tid).num_ports, "egr_hw_mods");
  11349             if (egr_hw_mods == NULL) {
  11350                 return BCM_E_MEMORY;
  11351             }
  11352 
  11353             egr_hw_ports = sal_alloc(sizeof(bcm_port_t) * 
  11354                     MEMBER_INFO(unit, tid).num_ports, "egr_hw_ports");
  11355             if (egr_hw_ports == NULL) {
  11356                 sal_free(egr_hw_mods);
  11357                 return BCM_E_MEMORY;
  11358             }
  11359 
  11360             egr_member_flags = sal_alloc(sizeof(uint32) *
  11361                     MEMBER_INFO(unit, tid).num_ports, "egr_member_flags");
  11362             if (egr_member_flags == NULL) {
  11363                 sal_free(egr_hw_mods);
  11364                 sal_free(egr_hw_ports);
  11365                 return BCM_E_MEMORY;
  11366             }
  11367 
  11368             for (i = 0, j = 0; i < MEMBER_INFO(unit, tid).num_ports; i++) {
  11369                 if (MEMBER_INFO(unit, tid).member_flags[i] &
  11370                         BCM_TRUNK_MEMBER_EGRESS_DISABLE) {
  11371                     continue;
  11372                 }
  11373                 egr_hw_mods[j] = MEMBER_INFO(unit, tid).modport[i] >> 8;
  11374                 egr_hw_ports[j] = MEMBER_INFO(unit, tid).modport[i] & 0xff;
  11375                 egr_member_flags[j] = MEMBER_INFO(unit, tid).member_flags[i];
  11376                 j++;
  11377             }
  11378             num_egr_ports = j;
  11379 
  11380         } else {
  11381             /* In level 1 warm boot, not all egress trunk members can be
  11382              * recovered from TRUNK_MEMBER table, as those members with
  11383              * the UNICAST_EGRESS_DISABLE flag set will not be in
  11384              * TRUNK_MEMBER table.
  11385              */
  11386 
  11387             egr_hw_mods = sal_alloc(sizeof(bcm_module_t) * tg_size,
  11388                     "egr_hw_mods");
  11389             if (egr_hw_mods == NULL) {
  11390                 return BCM_E_MEMORY;
  11391             }
  11392 
  11393             egr_hw_ports = sal_alloc(sizeof(bcm_port_t) * tg_size,
  11394                     "egr_hw_ports");
  11395             if (egr_hw_ports == NULL) {
  11396                 sal_free(egr_hw_mods);
  11397                 return BCM_E_MEMORY;
  11398             }
  11399 
  11400             egr_member_flags = sal_alloc(sizeof(uint32) * tg_size,
  11401                     "egr_member_flags");
  11402             if (egr_member_flags == NULL) {
  11403                 sal_free(egr_hw_mods);
  11404                 sal_free(egr_hw_ports);
  11405                 return BCM_E_MEMORY;
  11406             }
  11407 
  11408             for (i = 0; i < tg_size; i++) {
  11409                 rv = READ_TRUNK_MEMBERm(unit, MEM_BLOCK_ANY, base_ptr + i,
  11410                         &trunk_member_entry);
  11411                 if (BCM_FAILURE(rv)) {
  11412                     sal_free(egr_hw_mods);
  11413                     sal_free(egr_hw_ports);
  11414                     sal_free(egr_member_flags);
  11415                     return rv;
  11416                 }
  11417                 egr_hw_mods[i] = soc_TRUNK_MEMBERm_field32_get
  11418                     (unit, &trunk_member_entry, MODULE_IDf); 
  11419                 egr_hw_ports[i] = soc_TRUNK_MEMBERm_field32_get
  11420                     (unit, &trunk_member_entry, PORT_NUMf); 
  11421                 egr_member_flags[i] = 0;
  11422 
  11423                 /* Recreate INGRESS_DISABLE flag */
  11424                 rv = _bcm_esw_src_mod_port_table_index_get(unit, egr_hw_mods[i],
  11425                         egr_hw_ports[i], &stm_idx);
  11426                 if (BCM_FAILURE(rv)) {
  11427                     sal_free(egr_hw_mods);
  11428                     sal_free(egr_hw_ports);
  11429                     sal_free(egr_member_flags);
  11430                     return rv;
  11431                 }
  11432                 rv = soc_mem_read(unit, SOURCE_TRUNK_MAP_TABLEm, MEM_BLOCK_ANY,
  11433                         stm_idx, &stm);
  11434                 if (BCM_FAILURE(rv)) {
  11435                     sal_free(egr_hw_mods);
  11436                     sal_free(egr_hw_ports);
  11437                     sal_free(egr_member_flags);
  11438                     return rv;
  11439                 }
  11440                 ptype = soc_SOURCE_TRUNK_MAP_TABLEm_field32_get(unit, &stm,
  11441                         PORT_TYPEf);
  11442                 tid_get = soc_SOURCE_TRUNK_MAP_TABLEm_field32_get(unit, &stm,
  11443                             tgid_f);
  11444                 if (ptype != 1 || tid_get != tid) {
  11445                     egr_member_flags[i] |= BCM_TRUNK_MEMBER_INGRESS_DISABLE;
  11446                 }
  11447             }
  11448 
  11449             num_egr_ports = tg_size;
  11450 
  11451             if (MEMBER_INFO(unit, tid).modport) {
  11452                 sal_free(MEMBER_INFO(unit, tid).modport);
  11453                 MEMBER_INFO(unit, tid).modport = NULL;
  11454             }
  11455             if (MEMBER_INFO(unit, tid).member_flags) {
  11456                 sal_free(MEMBER_INFO(unit, tid).member_flags);
  11457                 MEMBER_INFO(unit, tid).member_flags = NULL;
  11458             }
  11459 
  11460             MEMBER_INFO(unit, tid).num_ports = tg_size;
  11461             MEMBER_INFO(unit, tid).modport = sal_alloc(
  11462                     sizeof(uint16) * MEMBER_INFO(unit, tid).num_ports,
  11463                     "member info modport");
  11464             if (NULL == MEMBER_INFO(unit, tid).modport) {
  11465                 sal_free(egr_hw_mods);
  11466                 sal_free(egr_hw_ports);
  11467                 sal_free(egr_member_flags);
  11468                 return BCM_E_MEMORY;
  11469             }
  11470 
  11471             MEMBER_INFO(unit, tid).member_flags = sal_alloc(
  11472                     sizeof(uint32) * MEMBER_INFO(unit, tid).num_ports,
  11473                     "member info flags");
  11474             if (NULL == MEMBER_INFO(unit, tid).member_flags) {
  11475                 sal_free(egr_hw_mods);
  11476                 sal_free(egr_hw_ports);
  11477                 sal_free(egr_member_flags);
  11478                 sal_free(MEMBER_INFO(unit, tid).modport);
  11479                 MEMBER_INFO(unit, tid).modport = NULL;
  11480                 return BCM_E_MEMORY;
  11481             }
  11482 
  11483             for (i = 0; i < MEMBER_INFO(unit, tid).num_ports; i++) {
  11484                 MEMBER_INFO(unit, tid).modport[i] =
  11485                     (egr_hw_mods[i] << 8) | egr_hw_ports[i];
  11486                 MEMBER_INFO(unit, tid).member_flags[i] = egr_member_flags[i];
  11487             }
  11488         }
  11489 
  11490         /* Recover software trunk failover state */
  11491         rv = _bcm_trident_trunk_swfailover_fp_set(unit, tid, rtag,
  11492                 num_egr_ports,
  11493                 egr_hw_mods,
  11494                 egr_hw_ports,
  11495                 egr_member_flags,
  11496                 trunk_info->flags);
  11497         if (BCM_FAILURE(rv)) {
  11498             sal_free(egr_hw_mods);
  11499             sal_free(egr_hw_ports);
  11500             sal_free(egr_member_flags);
  11501             return rv;
  11502         }
  11503 
  11504         /* Recover hardware trunk failover state. */
  11505         if (soc_feature(unit, soc_feature_port_lag_failover)) {
  11506             hwft = &(_trident_trunk_hwfail[unit]->hw_tinfo[tid]);
  11507             hwft->num_ports = num_egr_ports;
  11508             if (hwft->modport == NULL) {
  11509                 hwft->modport = sal_alloc(sizeof(uint16) * num_egr_ports,
  11510                         "hw_tinfo_modport");
  11511                 if (hwft->modport == NULL) {
  11512                     sal_free(egr_hw_mods);
  11513                     sal_free(egr_hw_ports);
  11514                     sal_free(egr_member_flags);
  11515                     return BCM_E_MEMORY;
  11516                 }
  11517             }
  11518             sal_memset(hwft->modport, 0, sizeof(uint16) * num_egr_ports);
  11519 
  11520             if (hwft->psc == NULL) {
  11521                 hwft->psc = sal_alloc(sizeof(uint8) * num_egr_ports,
  11522                         "hw_tinfo_psc");
  11523                 if (hwft->psc == NULL) {
  11524                     sal_free(hwft->modport);
  11525                     hwft->modport = NULL;
  11526                     sal_free(egr_hw_mods);
  11527                     sal_free(egr_hw_ports);
  11528                     sal_free(egr_member_flags);
  11529                     return BCM_E_MEMORY;
  11530                 }
  11531             }
  11532             sal_memset(hwft->psc, 0, sizeof(uint8) * num_egr_ports);
  11533 
  11534             if (hwft->flags == NULL) {
  11535                 /* If flags are not recovered from scache, allocate flags and
  11536                  * set them to zero.
  11537                  */
  11538                 hwft->flags = sal_alloc(sizeof(uint32) * num_egr_ports,
  11539                         "hw_tinfo_flags");
  11540                 if (hwft->flags == NULL) {
  11541                     sal_free(hwft->modport);
  11542                     hwft->modport = NULL;
  11543                     sal_free(hwft->psc);
  11544                     hwft->psc = NULL;
  11545                     sal_free(egr_hw_mods);
  11546                     sal_free(egr_hw_ports);
  11547                     sal_free(egr_member_flags);
  11548                     return BCM_E_MEMORY;
  11549                 }
  11550                 sal_memset(hwft->flags, 0, sizeof(uint32) * num_egr_ports);
  11551             }
  11552 
  11553 
  11554             for (i = 0; i < num_egr_ports; i++) {
  11555                 hwft->modport[i] = (egr_hw_mods[i] << 8) | egr_hw_ports[i];
  11556                 rv = _bcm_esw_modid_is_local(unit, egr_hw_mods[i], &mod_is_local);
  11557                 if (BCM_FAILURE(rv)) {
  11558                     sal_free(egr_hw_mods);
  11559                     sal_free(egr_hw_ports);
  11560                     sal_free(egr_member_flags);
  11561                     return rv;
  11562                 }
  11563                 if (mod_is_local) { 
  11564 #if defined(BCM_HELIX5_SUPPORT)
  11565                     /* Skip q-ports in HX5 since trunk hardware failover is not
  11566                      * supported for PM4x10Q.
  11567                      */
  11568                     if (IS_QSGMII_PORT(unit, egr_hw_ports[i])) {
  11569                         continue;
  11570                     }
  11571 #endif /* BCM_HELIX5_SUPPORT */
  11572                     rv = _bcm_trident_trunk_hwfailover_read(unit,
  11573                             egr_hw_ports[i], 0, &hwf_rtag, NULL, NULL, NULL);
  11574                     if (BCM_FAILURE(rv)) {
  11575                         sal_free(egr_hw_mods);
  11576                         sal_free(egr_hw_ports);
  11577                         sal_free(egr_member_flags);
  11578                         return rv;
  11579                     }
  11580                     if (hwf_rtag > 0) {
  11581                         rv = _bcm_trident_trunk_rtag_to_psc(unit, hwf_rtag,
  11582                                 &hwf_psc);
  11583                         if (BCM_FAILURE(rv)) {
  11584                             sal_free(egr_hw_mods);
  11585                             sal_free(egr_hw_ports);
  11586                             sal_free(egr_member_flags);
  11587                             return rv;
  11588                         }
  11589                     } else {
  11590                         hwf_psc = trunk_info->psc;
  11591                     }
  11592                     hwft->psc[i] = hwf_psc;
  11593                 }
  11594             }
  11595         }
  11596 
  11597         sal_free(egr_hw_mods);
  11598         sal_free(egr_hw_ports);
  11599         sal_free(egr_member_flags);
  11600 
  11601 #ifdef BCM_TRIUMPH3_SUPPORT
  11602         if (soc_feature(unit, soc_feature_lag_dlb) &&
  11603             !soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) {
  11604             BCM_IF_ERROR_RETURN
  11605                 (bcm_tr3_lag_dlb_group_recover(unit, tid, trunk_info));
  11606         }
  11607 #endif /* BCM_TRIUMPH3_SUPPORT */
  11608 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT)
  11609         if (soc_feature(unit, soc_feature_lag_dlb) &&
  11610             soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) {
  11611             BCM_IF_ERROR_RETURN
  11612                 (bcm_th2_hgt_lag_dlb_group_recover(unit, tid, 0, trunk_info));
  11613         }
  11614 #endif /* BCM_TOMAHAWK2_SUPPORT */
  11615 
  11616 
  11617     }
  11618 
  11619 #ifdef BCM_TRIDENT2_SUPPORT
  11620     if (soc_feature(unit, soc_feature_lag_resilient_hash)) {
  11621         for (tid = 0; tid < ngroups_fp; tid++, trunk_info_temp++) {
  11622             if (trunk_info_temp->psc == 0) {
  11623                 continue;
  11624             }
  11625             BCM_IF_ERROR_RETURN(
  11626                 bcm_td2_lag_rh_recover(unit, tid, trunk_info_temp));
  11627         }
  11628     }
  11629 #endif /* BCM_TRIDENT2_SUPPORT */
  11630 
  11631 #ifdef BCM_TRIUMPH3_SUPPORT
  11632     if (soc_feature(unit, soc_feature_lag_dlb) &&
  11633         !soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) {
  11634         BCM_IF_ERROR_RETURN(bcm_tr3_lag_dlb_member_recover(unit));
  11635         BCM_IF_ERROR_RETURN(bcm_tr3_lag_dlb_quality_parameters_recover(unit));
  11636     }
  11637 #endif /* BCM_TRIUMPH3_SUPPORT */
  11638 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined (BCM_TRIDENT3_SUPPORT)
  11639     if (soc_feature(unit, soc_feature_lag_dlb) &&
  11640         soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) {
  11641         BCM_IF_ERROR_RETURN(bcm_th2_hgt_lag_dlb_quality_parameters_recover(unit));
  11642     }
  11643 #endif /* BCM_TOMAHAWK2_SUPPORT */
  11644 
  11645 
  11646     return rv;
  11647 }
  11648 
  11649 /*
  11650  * Function:
  11651  *      bcm_trident_hg_dlb_wb_alloc_size_get
  11652  * Purpose:
  11653  *      Get level 2 warm boot scache size for Higig DLB.
  11654  * Parameters:
  11655  *      unit - (IN) SOC unit number.
  11656  *      size - (OUT) Allocation size.
  11657  * Returns:
  11658  *      BCM_E_XXX
  11659  */
  11660 int
  11661 bcm_trident_hg_dlb_wb_alloc_size_get(int unit, int *size) 
  11662 {
  11663     int alloc_size = 0;
  11664     int num_elements = 0;
  11665     soc_field_t profile_ptr_f;
  11666 
  11667     /* Allocate size for the following Higig DLB parameters: 
  11668      * int hg_dlb_sample_rate;
  11669      * int hg_dlb_tx_load_min_th;
  11670      * int hg_dlb_tx_load_max_th;
  11671      * int hg_dlb_qsize_min_th;
  11672      * int hg_dlb_qsize_max_th;
  11673      */
  11674     alloc_size += sizeof(int) * 5;
  11675 
  11676     /* Allocate size of hg_dlb_load_weight array */
  11677     if (soc_reg_field_valid(unit, DLB_HGT_QUANTIZE_CONTROLr,
  11678                 PORT_QUALITY_MAPPING_PROFILE_PTRf)) {
  11679         num_elements = 1 << soc_reg_field_length(unit,
  11680                 DLB_HGT_QUANTIZE_CONTROLr, PORT_QUALITY_MAPPING_PROFILE_PTRf);
  11681     } else {
  11682         profile_ptr_f = soc_mem_field_valid(unit, DLB_HGT_QUALITY_CONTROLm,
  11683                 PROFILE_PTRf) ? PROFILE_PTRf : QMT_PROFILE_PTRf;
  11684         num_elements = 1 << soc_mem_field_length(unit,
  11685                 DLB_HGT_QUALITY_CONTROLm, profile_ptr_f);
  11686     }
  11687     alloc_size += sizeof(uint8) * num_elements;
  11688 
  11689     *size = alloc_size;
  11690 
  11691     return BCM_E_NONE;
  11692 }
  11693 
  11694 /*
  11695  * Function:
  11696  *      bcm_trident_hg_dlb_sync
  11697  * Purpose:
  11698  *      Store Higig DLB parameters into scache.
  11699  * Parameters:
  11700  *      unit - (IN) SOC unit number.
  11701  *      scache_ptr - (IN/OUT) Scache pointer
  11702  * Returns:
  11703  *      BCM_E_XXX
  11704  */
  11705 int
  11706 bcm_trident_hg_dlb_sync(int unit, uint8 **scache_ptr) 
  11707 {
  11708     int value;
  11709     int num_elements = 0;
  11710     int i;
  11711     uint8 load_weight;
  11712     soc_field_t profile_ptr_f;
  11713 
  11714     /* Store the following Higig DLB parameters: 
  11715      * int hg_dlb_sample_rate;
  11716      * int hg_dlb_tx_load_min_th;
  11717      * int hg_dlb_tx_load_max_th;
  11718      * int hg_dlb_qsize_min_th;
  11719      * int hg_dlb_qsize_max_th;
  11720      */
  11721     value = HG_DLB_INFO(unit)->hg_dlb_sample_rate;
  11722     sal_memcpy((*scache_ptr), &value, sizeof(int));
  11723     (*scache_ptr) += sizeof(int);
  11724 
  11725     value = HG_DLB_INFO(unit)->hg_dlb_tx_load_min_th;
  11726     sal_memcpy((*scache_ptr), &value, sizeof(int));
  11727     (*scache_ptr) += sizeof(int);
  11728 
  11729     value = HG_DLB_INFO(unit)->hg_dlb_tx_load_max_th;
  11730     sal_memcpy((*scache_ptr), &value, sizeof(int));
  11731     (*scache_ptr) += sizeof(int);
  11732 
  11733     value = HG_DLB_INFO(unit)->hg_dlb_qsize_min_th;
  11734     sal_memcpy((*scache_ptr), &value, sizeof(int));
  11735     (*scache_ptr) += sizeof(int);
  11736 
  11737     value = HG_DLB_INFO(unit)->hg_dlb_qsize_max_th;
  11738     sal_memcpy((*scache_ptr), &value, sizeof(int));
  11739     (*scache_ptr) += sizeof(int);
  11740 
  11741     /* Store hg_dlb_load_weight array */
  11742     if (soc_reg_field_valid(unit, DLB_HGT_QUANTIZE_CONTROLr,
  11743                 PORT_QUALITY_MAPPING_PROFILE_PTRf)) {
  11744         num_elements = 1 << soc_reg_field_length(unit,
  11745                 DLB_HGT_QUANTIZE_CONTROLr, PORT_QUALITY_MAPPING_PROFILE_PTRf);
  11746     } else {
  11747         profile_ptr_f = soc_mem_field_valid(unit, DLB_HGT_QUALITY_CONTROLm,
  11748                 PROFILE_PTRf) ? PROFILE_PTRf : QMT_PROFILE_PTRf;
  11749         num_elements = 1 << soc_mem_field_length(unit,
  11750                 DLB_HGT_QUALITY_CONTROLm, profile_ptr_f);
  11751     }
  11752     for (i = 0; i < num_elements; i++) {
  11753         load_weight = HG_DLB_INFO(unit)->hg_dlb_load_weight[i];
  11754         sal_memcpy((*scache_ptr), &load_weight, sizeof(uint8));
  11755         (*scache_ptr) += sizeof(uint8);
  11756     }
  11757         
  11758     return BCM_E_NONE;
  11759 }
  11760 
  11761 /*
  11762  * Function:
  11763  *      bcm_trident_hg_dlb_scache_recover
  11764  * Purpose:
  11765  *      Recover Higig DLB parameters from scache.
  11766  * Parameters:
  11767  *      unit - (IN) SOC unit number.
  11768  *      scache_ptr - (IN/OUT) Scache pointer
  11769  * Returns:
  11770  *      BCM_E_XXX
  11771  */
  11772 int
  11773 bcm_trident_hg_dlb_scache_recover(int unit, uint8 **scache_ptr) 
  11774 {
  11775     int value;
  11776     int num_elements = 0;
  11777     int i;
  11778     uint8 load_weight;
  11779     soc_field_t profile_ptr_f;
  11780 
  11781     /* Recover the following Higig DLB parameters: 
  11782      * int hg_dlb_sample_rate;
  11783      * int hg_dlb_tx_load_min_th;
  11784      * int hg_dlb_tx_load_max_th;
  11785      * int hg_dlb_qsize_min_th;
  11786      * int hg_dlb_qsize_max_th;
  11787      */
  11788     sal_memcpy(&value, (*scache_ptr), sizeof(int));
  11789     HG_DLB_INFO(unit)->hg_dlb_sample_rate = value;
  11790     (*scache_ptr) += sizeof(int);
  11791 
  11792     sal_memcpy(&value, (*scache_ptr), sizeof(int));
  11793     HG_DLB_INFO(unit)->hg_dlb_tx_load_min_th = value;
  11794     (*scache_ptr) += sizeof(int);
  11795 
  11796     sal_memcpy(&value, (*scache_ptr), sizeof(int));
  11797     HG_DLB_INFO(unit)->hg_dlb_tx_load_max_th = value;
  11798     (*scache_ptr) += sizeof(int);
  11799 
  11800     sal_memcpy(&value, (*scache_ptr), sizeof(int));
  11801     HG_DLB_INFO(unit)->hg_dlb_qsize_min_th = value;
  11802     (*scache_ptr) += sizeof(int);
  11803 
  11804     sal_memcpy(&value, (*scache_ptr), sizeof(int));
  11805     HG_DLB_INFO(unit)->hg_dlb_qsize_max_th = value;
  11806     (*scache_ptr) += sizeof(int);
  11807 
  11808     /* Recover hg_dlb_load_weight array */
  11809     if (soc_reg_field_valid(unit, DLB_HGT_QUANTIZE_CONTROLr,
  11810                 PORT_QUALITY_MAPPING_PROFILE_PTRf)) {
  11811         num_elements = 1 << soc_reg_field_length(unit,
  11812                 DLB_HGT_QUANTIZE_CONTROLr, PORT_QUALITY_MAPPING_PROFILE_PTRf);
  11813     } else {
  11814         profile_ptr_f = soc_mem_field_valid(unit, DLB_HGT_QUALITY_CONTROLm,
  11815                 PROFILE_PTRf) ? PROFILE_PTRf : QMT_PROFILE_PTRf;
  11816         num_elements = 1 << soc_mem_field_length(unit,
  11817                 DLB_HGT_QUALITY_CONTROLm, profile_ptr_f);
  11818     }
  11819     for (i = 0; i < num_elements; i++) {
  11820         sal_memcpy(&load_weight, (*scache_ptr), sizeof(uint8));
  11821         HG_DLB_INFO(unit)->hg_dlb_load_weight[i] = load_weight;
  11822         (*scache_ptr) += sizeof(uint8);
  11823     }
  11824         
  11825     HG_DLB_INFO(unit)->recovered_from_scache = TRUE;
  11826 
  11827     return BCM_E_NONE;
  11828 }
  11829 
  11830 #ifdef BCM_TRIUMPH3_SUPPORT
  11831 /*
  11832  * Function:
  11833  *      _bcm_tr3_hg_dlb_member_recover
  11834  * Purpose:
  11835  *      Recover Higig DLB member ID usage.
  11836  * Parameters:
  11837  *      unit - (IN) SOC unit number.
  11838  * Returns:
  11839  *      BCM_E_XXX
  11840  */
  11841 STATIC int
  11842 _bcm_tr3_hg_dlb_member_recover(int unit) 
  11843 {
  11844     int i, member_id;
  11845     dlb_hgt_port_member_map_entry_t port_member_map_entry;
  11846 
  11847     for (i = 0; i < soc_mem_index_count(unit, DLB_HGT_PORT_MEMBER_MAPm);
  11848             i++) {
  11849         SOC_IF_ERROR_RETURN(READ_DLB_HGT_PORT_MEMBER_MAPm(unit,
  11850                     MEM_BLOCK_ANY, i, &port_member_map_entry));
  11851         if (soc_DLB_HGT_PORT_MEMBER_MAPm_field32_get(unit,
  11852                     &port_member_map_entry, VALIDf)) {
  11853             member_id = soc_DLB_HGT_PORT_MEMBER_MAPm_field32_get(unit,
  11854                     &port_member_map_entry, MEMBER_IDf);
  11855             _BCM_HG_DLB_MEMBER_ID_USED_SET(unit, member_id);
  11856         }
  11857     }
  11858 
  11859     return BCM_E_NONE;
  11860 }
  11861 #endif /* BCM_TRIUMPH3_SUPPORT */
  11862 
  11863 /*
  11864  * Function:
  11865  *      _bcm_trident_hg_dlb_quality_parameters_recover
  11866  * Purpose:
  11867  *      Recover Higig DLB parameters used to derive a member's quality.
  11868  * Parameters:
  11869  *      unit - (IN) SOC unit number.
  11870  * Returns:
  11871  *      BCM_E_XXX
  11872  */
  11873 STATIC int
  11874 _bcm_trident_hg_dlb_quality_parameters_recover(int unit) 
  11875 {
  11876     uint32 measure_control_reg;
  11877     int num_time_units;
  11878     dlb_hgt_glb_quantize_thresholds_entry_t thresholds_entry;
  11879     int max_th_bytes;
  11880     int min_th_bytes;
  11881     int max_th_cells;
  11882     int min_th_cells;
  11883     int entries_per_profile;
  11884     int base_index;
  11885     int profile_ptr;
  11886     dlb_hgt_port_quality_mapping_entry_t port_quality_mapping_entry;
  11887     int quality;
  11888 
  11889     if (HG_DLB_INFO(unit)->recovered_from_scache) {
  11890         /* If already recovered fro scache, do nothing */
  11891         return BCM_E_NONE;
  11892     }
  11893 
  11894     /* Recover sampling rate */
  11895     SOC_IF_ERROR_RETURN(READ_DLB_HGT_QUALITY_MEASURE_CONTROLr(unit,
  11896                 &measure_control_reg));
  11897     num_time_units = soc_reg_field_get(unit, DLB_HGT_QUALITY_MEASURE_CONTROLr,
  11898             measure_control_reg, SAMPLING_PERIODf);
  11899 #ifdef BCM_TRIUMPH3_SUPPORT
  11900     if (SOC_IS_TRIUMPH3(unit) || SOC_IS_TD2_TT2(unit)) {
  11901         /* Sampling rate = 10^6 / num_time_units */
  11902         if (num_time_units > 0) {
  11903             HG_DLB_INFO(unit)->hg_dlb_sample_rate = 1000000 / num_time_units;
  11904         }
  11905     } else
  11906 #endif /* BCM_TRIUMPH3_SUPPORT */
  11907     {
  11908         /* Sampling rate = 10^9 ns / (256 ns * num_time_units)
  11909          *               = 3906250 / num_time_units
  11910          */
  11911         if (num_time_units > 0) {
  11912             HG_DLB_INFO(unit)->hg_dlb_sample_rate = 3906250 / num_time_units;
  11913         }
  11914     }
  11915 
  11916     /* Recover max and min load and queue size thresholds */
  11917         /* Threshold (in mbps)
  11918          *     = (bytes per sampling period) * 8 bits per byte /
  11919          *       (sampling period in seconds) / 10^6
  11920          *     = (bytes per sampling period) * 8 bits per byte /
  11921          *       (num_time_units * 1 us per time unit * 10^-6) / 10^6
  11922          *     = (bytes per sampling period) * 8 / num_time_units 
  11923          */ 
  11924 
  11925 #ifdef BCM_TRIDENT2_SUPPORT
  11926     if (SOC_IS_TD2_TT2(unit)) {
  11927         dlb_hgt_pla_quantize_threshold_entry_t quantize_threshold_entry;
  11928 
  11929         SOC_IF_ERROR_RETURN(READ_DLB_HGT_PLA_QUANTIZE_THRESHOLDm(unit,
  11930                     MEM_BLOCK_ANY, 0, &quantize_threshold_entry));
  11931         min_th_bytes = soc_DLB_HGT_PLA_QUANTIZE_THRESHOLDm_field32_get
  11932             (unit, &quantize_threshold_entry, LOADING_THRESHOLDf); 
  11933         HG_DLB_INFO(unit)->hg_dlb_tx_load_min_th = (min_th_bytes << 3) /
  11934             num_time_units;
  11935 
  11936         min_th_cells = soc_DLB_HGT_PLA_QUANTIZE_THRESHOLDm_field32_get
  11937             (unit, &quantize_threshold_entry, QSIZE_THRESHOLDf); 
  11938         HG_DLB_INFO(unit)->hg_dlb_qsize_min_th = min_th_cells * 208;
  11939 
  11940         SOC_IF_ERROR_RETURN(READ_DLB_HGT_PLA_QUANTIZE_THRESHOLDm(unit,
  11941                     MEM_BLOCK_ANY, 6, &quantize_threshold_entry));
  11942         max_th_bytes = soc_DLB_HGT_PLA_QUANTIZE_THRESHOLDm_field32_get
  11943             (unit, &quantize_threshold_entry, LOADING_THRESHOLDf); 
  11944         HG_DLB_INFO(unit)->hg_dlb_tx_load_max_th = (max_th_bytes << 3) /
  11945             num_time_units;
  11946 
  11947         max_th_cells = soc_DLB_HGT_PLA_QUANTIZE_THRESHOLDm_field32_get
  11948             (unit, &quantize_threshold_entry, QSIZE_THRESHOLDf); 
  11949         HG_DLB_INFO(unit)->hg_dlb_qsize_max_th = max_th_cells * 208;
  11950 
  11951     } else
  11952 #endif /* BCM_TRIDENT2_SUPPORT */
  11953 #ifdef BCM_TRIUMPH3_SUPPORT
  11954     if (SOC_IS_TRIUMPH3(unit)) {
  11955         dlb_hgt_quantize_threshold_entry_t quantize_threshold_entry;
  11956 
  11957         SOC_IF_ERROR_RETURN(READ_DLB_HGT_QUANTIZE_THRESHOLDm(unit,
  11958                     MEM_BLOCK_ANY, 0, &quantize_threshold_entry));
  11959         min_th_bytes = soc_DLB_HGT_QUANTIZE_THRESHOLDm_field32_get
  11960             (unit, &quantize_threshold_entry, LOADING_THRESHOLDf); 
  11961         HG_DLB_INFO(unit)->hg_dlb_tx_load_min_th = (min_th_bytes << 3) /
  11962             num_time_units;
  11963 
  11964         min_th_cells = soc_DLB_HGT_QUANTIZE_THRESHOLDm_field32_get
  11965             (unit, &quantize_threshold_entry, QSIZE_THRESHOLDf); 
  11966         HG_DLB_INFO(unit)->hg_dlb_qsize_min_th = min_th_cells * 208;
  11967 
  11968         SOC_IF_ERROR_RETURN(READ_DLB_HGT_QUANTIZE_THRESHOLDm(unit,
  11969                     MEM_BLOCK_ANY, 6, &quantize_threshold_entry));
  11970         max_th_bytes = soc_DLB_HGT_QUANTIZE_THRESHOLDm_field32_get
  11971             (unit, &quantize_threshold_entry, LOADING_THRESHOLDf); 
  11972         HG_DLB_INFO(unit)->hg_dlb_tx_load_max_th = (max_th_bytes << 3) /
  11973             num_time_units;
  11974 
  11975         max_th_cells = soc_DLB_HGT_QUANTIZE_THRESHOLDm_field32_get
  11976             (unit, &quantize_threshold_entry, QSIZE_THRESHOLDf); 
  11977         HG_DLB_INFO(unit)->hg_dlb_qsize_max_th = max_th_cells * 208;
  11978     } else
  11979 #endif /* BCM_TRIUMPH3_SUPPORT */
  11980     {
  11981         /* Threshold (in mbps)
  11982          *     = (bytes per sampling period) * 8 bits per byte /
  11983          *       (sampling period in seconds) / 10^6
  11984          *     = (bytes per sampling period) * 8 bits per byte /
  11985          *       (num_time_units * 256 ns per time unit * 10^-9) / 10^6
  11986          *     = (bytes per sampling period) * 8000 / num_time_units / 256
  11987          */ 
  11988         SOC_IF_ERROR_RETURN(READ_DLB_HGT_GLB_QUANTIZE_THRESHOLDSm(unit,
  11989                     MEM_BLOCK_ANY, 0, &thresholds_entry));
  11990         min_th_bytes = soc_DLB_HGT_GLB_QUANTIZE_THRESHOLDSm_field32_get
  11991             (unit, &thresholds_entry, PORT_LOADING_THRESHOLD_1f); 
  11992         HG_DLB_INFO(unit)->hg_dlb_tx_load_min_th =
  11993             ((min_th_bytes << 3) * 1000 / num_time_units) >> 8;
  11994 
  11995         max_th_bytes = soc_DLB_HGT_GLB_QUANTIZE_THRESHOLDSm_field32_get
  11996             (unit, &thresholds_entry, PORT_LOADING_THRESHOLD_7f); 
  11997         HG_DLB_INFO(unit)->hg_dlb_tx_load_max_th = 
  11998             ((max_th_bytes << 3) * 1000 / num_time_units) >> 8;
  11999 
  12000         min_th_cells = soc_DLB_HGT_GLB_QUANTIZE_THRESHOLDSm_field32_get
  12001             (unit, &thresholds_entry, PORT_QSIZE_THRESHOLD_1f); 
  12002         HG_DLB_INFO(unit)->hg_dlb_qsize_min_th = min_th_cells * 208;
  12003 
  12004         max_th_cells = soc_DLB_HGT_GLB_QUANTIZE_THRESHOLDSm_field32_get
  12005             (unit, &thresholds_entry, PORT_QSIZE_THRESHOLD_7f); 
  12006         HG_DLB_INFO(unit)->hg_dlb_qsize_max_th = max_th_cells * 208;
  12007     }
  12008 
  12009     /* Recover load weights */
  12010 
  12011 #ifdef BCM_TRIUMPH3_SUPPORT
  12012     if (soc_feature(unit, soc_feature_hg_dlb_member_id)) {
  12013         soc_field_t profile_ptr_f, quality_f;
  12014         dlb_hgt_quality_mapping_entry_t quality_mapping_entry;
  12015 
  12016         entries_per_profile = 64;
  12017         profile_ptr_f = soc_mem_field_valid(unit, DLB_HGT_QUALITY_CONTROLm,
  12018                 PROFILE_PTRf) ? PROFILE_PTRf : QMT_PROFILE_PTRf;
  12019         quality_f = soc_mem_field_valid(unit, DLB_HGT_QUALITY_MAPPINGm,
  12020                 QUALITYf) ? QUALITYf : ASSIGNED_QUALITYf;
  12021         for (profile_ptr = 0;
  12022              profile_ptr < (1 << soc_mem_field_length(unit,
  12023                         DLB_HGT_QUALITY_CONTROLm, profile_ptr_f));
  12024              profile_ptr++) {
  12025             base_index = profile_ptr * entries_per_profile;
  12026             /* quality = (quantized_tx_load * tx_load_percent +
  12027              *            quantized_qsize * (100 - tx_load_percent)) /
  12028              *           100;
  12029              * quality = ((quantized_tx_load - quantized_qsize) *
  12030              *            tx_load_percent + quantized_qsize * 100) /
  12031              *           100;
  12032              * quality = (quantized_tx_load - quantized_qsize) *
  12033              *           tx_load_percent / 100 + quantized_qsize;
  12034              * tx_load_percent = (quality - quantized_qsize) * 100 /
  12035              *                   (quantized_tx_load - quantized_qsize); 
  12036              *
  12037              * The index to DLB_HGT_QUALITY_MAPPING table consists of
  12038              * base_index + quantized_tx_load * 8 + quantized_qsize,
  12039              * where quantized_tx_load and quantized_qsize range from
  12040              * 0 to 7.
  12041              *
  12042              * With quantized_tx_load = 7 and quantized_qsize = 0, the 
  12043              * index to DLB_HGT_QUALITY_MAPPING table is
  12044              * base_index + 56, and the tx_load_present expression
  12045              * simplifies to quality * 100 / 7;
  12046              */
  12047             BCM_IF_ERROR_RETURN(READ_DLB_HGT_QUALITY_MAPPINGm(unit,
  12048                         MEM_BLOCK_ANY, base_index + 56,
  12049                         &quality_mapping_entry));
  12050             quality = soc_DLB_HGT_QUALITY_MAPPINGm_field32_get(unit,
  12051                     &port_quality_mapping_entry, quality_f);
  12052             HG_DLB_INFO(unit)->hg_dlb_load_weight[profile_ptr] =
  12053                 quality * 100 / 7;
  12054         }
  12055     } else
  12056 #endif /* BCM_TRIUMPH3_SUPPORT */
  12057     {
  12058         entries_per_profile = 64;
  12059         for (profile_ptr = 0;
  12060              profile_ptr < (1 << soc_reg_field_length(unit,
  12061                         DLB_HGT_QUANTIZE_CONTROLr,
  12062                         PORT_QUALITY_MAPPING_PROFILE_PTRf));
  12063              profile_ptr++) {
  12064             base_index = profile_ptr * entries_per_profile;
  12065             /* quality = (quantized_tx_load * tx_load_percent +
  12066              *            quantized_qsize * (100 - tx_load_percent)) / 100;
  12067              * quality = ((quantized_tx_load - quantized_qsize) *
  12068              *            tx_load_percent + quantized_qsize * 100) / 100;
  12069              * quality = (quantized_tx_load - quantized_qsize) *
  12070              *           tx_load_percent / 100 + quantized_qsize;
  12071              * tx_load_percent = (quality - quantized_qsize) * 100 /
  12072              *                   (quantized_tx_load - quantized_qsize); 
  12073              *
  12074              * The index to DLB_HGT_PORT_QUALITY_MAPPING table consists of
  12075              * base_index + quantized_tx_load * 8 + quantized_qsize, where
  12076              * quantized_tx_load and quantized_qsize range from 0 to 7.
  12077              *
  12078              * With quantized_tx_load = 7 and quantized_qsize = 0, the 
  12079              * index to DLB_HGT_PORT_QUALITY_MAPPING table is
  12080              * base_index + 56, and the tx_load_present expression
  12081              * simplifies to quality * 100 / 7;
  12082              */
  12083             BCM_IF_ERROR_RETURN(READ_DLB_HGT_PORT_QUALITY_MAPPINGm(unit,
  12084                         MEM_BLOCK_ANY, base_index + 56,
  12085                         &port_quality_mapping_entry));
  12086             quality = soc_DLB_HGT_PORT_QUALITY_MAPPINGm_field32_get(unit,
  12087                     &port_quality_mapping_entry, ASSIGNED_QUALITYf);
  12088             HG_DLB_INFO(unit)->hg_dlb_load_weight[profile_ptr] =
  12089                 quality * 100 / 7;
  12090         }
  12091     }
  12092 
  12093     return BCM_E_NONE;
  12094 }
  12095 
  12096 /*
  12097  * Function:
  12098  *      _bcm_trident_hg_tg_size_field_forced
  12099  * Purpose:
  12100  *      Determine if the TG_SIZE field in HG_TRUNK_GROUP table is forced
  12101  *      by hardware to be 0xf when RTAG field is less than or equal to 6.
  12102  * Parameters:
  12103  *      unit  - (IN) SOC unit number. 
  12104  * Returns:
  12105  *      BCM_E_xxx
  12106  */
  12107 STATIC int
  12108 _bcm_trident_hg_tg_size_field_forced(int unit)
  12109 {
  12110     uint16 dev_id;
  12111     uint8  rev_id;
  12112 
  12113     soc_cm_get_id(unit, &dev_id, &rev_id);
  12114 
  12115     if ((dev_id == BCM56841_DEVICE_ID && rev_id >= BCM56841_B0_REV_ID) ||
  12116         (dev_id == BCM56843_DEVICE_ID && rev_id >= BCM56843_B0_REV_ID) ||
  12117         (dev_id == BCM56845_DEVICE_ID && rev_id >= BCM56845_B0_REV_ID)) {
  12118         /* For these devices, the HG_TRUNK_GROUP.TG_SIZE field is forced
  12119          * by harware to be 0xf when RTAG field is less than or equal to 6.
  12120          */
  12121        return TRUE;
  12122     } else {
  12123        return FALSE;
  12124     } 
  12125 }
  12126 
  12127 /*
  12128  * Function:
  12129  *      _bcm_trident_hg_dlb_group_recover
  12130  * Purpose:
  12131  *      Recover HGT DLB group usage and flowset table usage.
  12132  * Parameters:
  12133  *      unit        - (IN) SOC unit number.
  12134  *      hgtid       - (IN) HiGig Trunk group ID.
  12135  *      trunk_info  - (OUT) Per trunk group DLB info.
  12136  * Returns:
  12137  *      BCM_E_XXX
  12138  */
  12139 STATIC int
  12140 _bcm_trident_hg_dlb_group_recover(int unit, bcm_trunk_t hgtid,
  12141                                   trunk_private_t *trunk_info)
  12142 {
  12143     hgt_dlb_control_entry_t hgt_dlb_control_entry;
  12144 
  12145     int dlb_enable, dlb_id;
  12146     dlb_hgt_group_control_entry_t dlb_hgt_group_control_entry;
  12147     int dlb_mode;
  12148     int dynamic_size_encode, dynamic_size;
  12149     int entry_base_ptr;
  12150     int block_base_ptr, num_blocks;
  12151 
  12152 #ifdef BCM_TRIDENT2_SUPPORT
  12153     if (soc_feature(unit, soc_feature_hg_dlb_id_equal_hg_tid)) {
  12154         SOC_IF_ERROR_RETURN(READ_DLB_HGT_GROUP_CONTROLm(unit, MEM_BLOCK_ANY,
  12155                     hgtid, &dlb_hgt_group_control_entry));
  12156         dlb_enable = soc_DLB_HGT_GROUP_CONTROLm_field32_get(unit,
  12157                 &dlb_hgt_group_control_entry, GROUP_ENABLEf);
  12158         dlb_id = hgtid;
  12159     } else
  12160 #endif /* BCM_TRIDENT2_SUPPORT */
  12161     {
  12162         SOC_IF_ERROR_RETURN(READ_HGT_DLB_CONTROLm(unit, MEM_BLOCK_ANY,
  12163                     hgtid, &hgt_dlb_control_entry));
  12164         dlb_enable = soc_HGT_DLB_CONTROLm_field32_get(unit,
  12165                 &hgt_dlb_control_entry, GROUP_ENABLEf);
  12166         dlb_id = soc_HGT_DLB_CONTROLm_field32_get(unit,
  12167                 &hgt_dlb_control_entry, DLB_IDf);
  12168     }
  12169 
  12170     if (dlb_enable) {
  12171 
  12172         /* Mark Higig DLB group as used */
  12173         _BCM_HG_DLB_ID_USED_SET(unit, dlb_id);
  12174 
  12175         SOC_IF_ERROR_RETURN(READ_DLB_HGT_GROUP_CONTROLm(unit,
  12176                     MEM_BLOCK_ANY, dlb_id, &dlb_hgt_group_control_entry));
  12177 
  12178         /* Recover DLB mode */
  12179 #ifdef BCM_TRIUMPH3_SUPPORT
  12180         if (soc_mem_field_valid(unit, DLB_HGT_GROUP_CONTROLm,
  12181                     MEMBER_ASSIGNMENT_MODEf)) {
  12182             dlb_mode = soc_DLB_HGT_GROUP_CONTROLm_field32_get(unit,
  12183                     &dlb_hgt_group_control_entry, MEMBER_ASSIGNMENT_MODEf);
  12184         } else
  12185 #endif /* BCM_TRIUMPH3_SUPPORT */
  12186         {
  12187             dlb_mode = soc_DLB_HGT_GROUP_CONTROLm_field32_get(unit,
  12188                     &dlb_hgt_group_control_entry, PORT_ASSIGNMENT_MODEf);
  12189         }
  12190         switch (dlb_mode) {
  12191             case 0:
  12192                 trunk_info->psc = BCM_TRUNK_PSC_DYNAMIC;
  12193                 break;
  12194             case 1:
  12195                 trunk_info->psc = BCM_TRUNK_PSC_DYNAMIC_ASSIGNED;
  12196                 break;
  12197             case 2:
  12198                 trunk_info->psc = BCM_TRUNK_PSC_DYNAMIC_OPTIMAL;
  12199                 break;
  12200             default:
  12201                 return BCM_E_INTERNAL;
  12202         }
  12203 
  12204         /* Recover dynamic_size */
  12205         dynamic_size_encode = soc_DLB_HGT_GROUP_CONTROLm_field32_get(unit,
  12206                 &dlb_hgt_group_control_entry, FLOW_SET_SIZEf);
  12207         BCM_IF_ERROR_RETURN
  12208             (_bcm_trident_hg_dlb_dynamic_size_decode(dynamic_size_encode,
  12209                                                      &dynamic_size));
  12210         trunk_info->dynamic_size = dynamic_size;
  12211 
  12212         /* Recover dynamic_age */
  12213         trunk_info->dynamic_age = soc_DLB_HGT_GROUP_CONTROLm_field32_get(unit,
  12214                 &dlb_hgt_group_control_entry, INACTIVITY_DURATIONf);
  12215 
  12216 
  12217         /* Recover flow set table usage */
  12218         entry_base_ptr = soc_DLB_HGT_GROUP_CONTROLm_field32_get(unit,
  12219                 &dlb_hgt_group_control_entry, FLOW_SET_BASEf);
  12220         block_base_ptr = entry_base_ptr >> 9;
  12221         num_blocks = trunk_info->dynamic_size >> 9;
  12222         _BCM_HG_DLB_FLOWSET_BLOCK_USED_SET_RANGE(unit, block_base_ptr,
  12223                 num_blocks);
  12224     }
  12225     return BCM_E_NONE;
  12226 }
  12227 /*
  12228  * Handle state recovery for fabric trunks
  12229  */
  12230 int
  12231 _bcm_trident_trunk_fabric_reinit(int unit, int min_tid, int max_tid,
  12232                           trunk_private_t *trunk_info)
  12233 {
  12234     int rv = BCM_E_NONE;
  12235     int tid, hgtid;
  12236     hg_trunk_group_entry_t hg_tg_entry;
  12237     hg_trunk_member_entry_t hg_trunk_member_entry;
  12238     hg_trunk_bitmap_entry_t hg_trunk_bitmap_entry;
  12239     int base_ptr, tg_size, rtag;
  12240     bcm_port_t *hwport;
  12241     int i;
  12242     bcm_pbmp_t hg_trunk_pbmp;
  12243     int hwf_rtag, hwf_psc;
  12244     _trident_hw_tinfo_t *hwft;
  12245     int num_entries;
  12246 
  12247     for (tid = min_tid; tid <= max_tid; tid++, trunk_info++) {
  12248 
  12249         hgtid = tid - min_tid;
  12250 
  12251         SOC_IF_ERROR_RETURN
  12252             (READ_HG_TRUNK_GROUPm(unit, MEM_BLOCK_ANY, hgtid,
  12253                                   &hg_tg_entry));
  12254         base_ptr = soc_HG_TRUNK_GROUPm_field32_get(unit, &hg_tg_entry,
  12255                 BASE_PTRf);
  12256         if (_bcm_trident_hg_tg_size_field_forced(unit)) {
  12257             tg_size = _bcm_trident_hw_failover_num_ports_get(unit, hgtid, TRUE);
  12258             if (tg_size == 0) {
  12259                 /* Invalid Higig trunk group */
  12260                 continue;
  12261             }
  12262         } else {
  12263             tg_size = 1 + soc_HG_TRUNK_GROUPm_field32_get(unit, &hg_tg_entry,
  12264                     TG_SIZEf);
  12265             if ((0 == base_ptr) && (tg_size == 1)) {
  12266                 /* Invalid Higig trunk group */
  12267                 continue;
  12268             }
  12269         }
  12270 
  12271         rtag = soc_HG_TRUNK_GROUPm_field32_get(unit, &hg_tg_entry, RTAGf);
  12272 
  12273         /* Recover trunk info */
  12274         trunk_info->tid = tid;
  12275         trunk_info->in_use = TRUE;
  12276         BCM_IF_ERROR_RETURN
  12277             (_bcm_trident_trunk_rtag_to_psc(unit, rtag, &trunk_info->psc));
  12278         trunk_info->rtag = rtag;
  12279         /* trunk_info->flags already recovered from scache */
  12280 
  12281         /* Recover trunk member table bookkeeping info */
  12282         num_entries = tg_size;
  12283         if (rtag >= 1 && rtag <= 6) {
  12284 #ifdef BCM_KATANA_SUPPORT
  12285             if (SOC_IS_KATANAX(unit)) {
  12286                 num_entries = _BCM_KATANA_FABRIC_TRUNK_RTAG1_6_MAX_PORTCNT;
  12287             } else
  12288 #endif
  12289             if (soc_feature(unit,
  12290                         soc_feature_rtag1_6_max_portcnt_less_than_rtag7)) { 
  12291                 num_entries = _BCM_TD_FABRIC_TRUNK_RTAG1_6_MAX_PORTCNT;
  12292             }
  12293         } 
  12294         _BCM_HG_TRUNK_MEMBER_USED_SET_RANGE(unit, base_ptr, num_entries);
  12295 
  12296         /* Recover Higig DLB group info */
  12297         if (soc_feature(unit, soc_feature_hg_dlb) &&
  12298             !soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) {
  12299             BCM_IF_ERROR_RETURN
  12300                 (_bcm_trident_hg_dlb_group_recover(unit, hgtid, trunk_info));
  12301         }
  12302 
  12303 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT)
  12304         if (soc_feature(unit, soc_feature_hg_dlb) &&
  12305             soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) {
  12306             BCM_IF_ERROR_RETURN
  12307                 (bcm_th2_hgt_lag_dlb_group_recover(unit, hgtid, 1, trunk_info));
  12308         }
  12309 #endif /* BCM_TOMAHAWK2_SUPPORT */
  12310 
  12311 #ifdef BCM_TRIDENT2_SUPPORT
  12312         /* Recover Higig resilient hashing group info */
  12313         if (soc_feature(unit, soc_feature_hg_resilient_hash)) {
  12314             BCM_IF_ERROR_RETURN(bcm_td2_hg_rh_recover(unit, hgtid, trunk_info));
  12315         }
  12316 #endif /* BCM_TRIDENT2_SUPPORT */
  12317 
  12318         /* Recover trunk member info */
  12319         hwport = sal_alloc(sizeof(bcm_port_t) * tg_size, "hwport");
  12320         if (hwport == NULL) {
  12321             return BCM_E_MEMORY;
  12322         }
  12323         sal_memset(hwport, 0, sizeof(bcm_port_t) * tg_size); 
  12324         for (i = 0; i < tg_size; i++) {
  12325             rv = READ_HG_TRUNK_MEMBERm(unit, MEM_BLOCK_ANY, base_ptr + i,
  12326                     &hg_trunk_member_entry);
  12327             if (BCM_FAILURE(rv)) {
  12328                 sal_free(hwport);
  12329                 return rv;
  12330             }
  12331 #if defined(BCM_KATANA2_SUPPORT)
  12332             if (SOC_IS_KATANA2(unit)) {
  12333                 hwport[i] = soc_HG_TRUNK_MEMBERm_field32_get
  12334                     (unit, &hg_trunk_member_entry, PHYSICAL_PORTf);
  12335             } else
  12336 #endif /* BCM_KATANA2_SUPPORT */
  12337             {
  12338                 hwport[i] = soc_HG_TRUNK_MEMBERm_field32_get
  12339                     (unit, &hg_trunk_member_entry, PORT_NUMf);
  12340             }
  12341         }
  12342 
  12343         if (MEMBER_INFO(unit, tid).modport) {
  12344             sal_free(MEMBER_INFO(unit, tid).modport);
  12345             MEMBER_INFO(unit, tid).modport = NULL;
  12346         }
  12347         if (MEMBER_INFO(unit, tid).member_flags) {
  12348             sal_free(MEMBER_INFO(unit, tid).member_flags);
  12349             MEMBER_INFO(unit, tid).member_flags = NULL;
  12350         }
  12351         MEMBER_INFO(unit, tid).num_ports = tg_size;
  12352         MEMBER_INFO(unit, tid).modport = sal_alloc(
  12353                 sizeof(uint16) * MEMBER_INFO(unit, tid).num_ports,
  12354                 "member info modport");
  12355         if (NULL == MEMBER_INFO(unit, tid).modport) {
  12356             sal_free(hwport);
  12357             return BCM_E_MEMORY;
  12358         }
  12359         MEMBER_INFO(unit, tid).member_flags = sal_alloc(
  12360                 sizeof(uint32) * MEMBER_INFO(unit, tid).num_ports,
  12361                 "member info flags");
  12362         if (NULL == MEMBER_INFO(unit, tid).member_flags) {
  12363             sal_free(hwport);
  12364             sal_free(MEMBER_INFO(unit, tid).modport);
  12365             MEMBER_INFO(unit, tid).modport = NULL;
  12366             return BCM_E_MEMORY;
  12367         }
  12368         for (i = 0; i < tg_size; i++) {
  12369             MEMBER_INFO(unit, tid).modport[i] = hwport[i];
  12370             MEMBER_INFO(unit, tid).member_flags[i] = 0;
  12371         }
  12372 
  12373         /* Recover software trunk failover state */
  12374         rv = READ_HG_TRUNK_BITMAPm(unit, MEM_BLOCK_ANY, hgtid,
  12375                                    &hg_trunk_bitmap_entry);
  12376         if (BCM_FAILURE(rv)) {
  12377             sal_free(hwport);
  12378             return rv;
  12379         }
  12380         soc_mem_pbmp_field_get(unit, HG_TRUNK_BITMAPm, &hg_trunk_bitmap_entry,
  12381             HIGIG_TRUNK_BITMAPf, &hg_trunk_pbmp);
  12382         rv = _bcm_trident_trunk_swfailover_fabric_set(unit, hgtid,
  12383                 trunk_info->rtag, hg_trunk_pbmp);
  12384         if (BCM_FAILURE(rv)) {
  12385             sal_free(hwport);
  12386             return rv;
  12387         }
  12388 
  12389         /* Recover hardware trunk failover state. */
  12390         if (soc_feature(unit, soc_feature_hg_trunk_failover)) {
  12391             hwft = &(_trident_trunk_hwfail[unit]->hw_tinfo[tid]);
  12392             hwft->num_ports = tg_size;
  12393             if (hwft->modport == NULL) {
  12394                 hwft->modport = sal_alloc(sizeof(uint16) * tg_size,
  12395                         "hw_tinfo_modport");
  12396                 if (hwft->modport == NULL) {
  12397                     sal_free(hwport);
  12398                     return BCM_E_MEMORY;
  12399                 }
  12400             }
  12401             sal_memset(hwft->modport, 0, sizeof(uint16) * tg_size);
  12402 
  12403             if (hwft->psc == NULL) {
  12404                 hwft->psc = sal_alloc(sizeof(uint8) * tg_size,
  12405                         "hw_tinfo_psc");
  12406                 if (hwft->psc == NULL) {
  12407                     sal_free(hwft->modport);
  12408                     hwft->modport = NULL;
  12409                     sal_free(hwport);
  12410                     return BCM_E_MEMORY;
  12411                 }
  12412             }
  12413             sal_memset(hwft->psc, 0, sizeof(uint8) * tg_size);
  12414 
  12415             if (hwft->flags == NULL) {
  12416                 /* If flags are not recovered from scache, allocate flags and
  12417                  * set them to zero.
  12418                  */
  12419                 hwft->flags = sal_alloc(sizeof(uint32) * tg_size,
  12420                         "hw_tinfo_flags");
  12421                 if (hwft->flags == NULL) {
  12422                     sal_free(hwft->modport);
  12423                     hwft->modport = NULL;
  12424                     sal_free(hwft->psc);
  12425                     hwft->psc = NULL;
  12426                     sal_free(hwport);
  12427                     return BCM_E_MEMORY;
  12428                 }
  12429                 sal_memset(hwft->flags, 0, sizeof(uint32) * tg_size);
  12430             }
  12431 
  12432             for (i = 0; i < tg_size; i++) {
  12433                 hwft->modport[i] = hwport[i];
  12434                 rv = _bcm_trident_trunk_hwfailover_hg_read(unit, hwport[i],
  12435                         0, &hwf_rtag, NULL, NULL, NULL);
  12436                 if (BCM_FAILURE(rv)) {
  12437                     sal_free(hwport);
  12438                     return rv;
  12439                 }
  12440                 if (hwf_rtag != 0) {
  12441                     rv = _bcm_trident_trunk_rtag_to_psc(unit, hwf_rtag,
  12442                             &hwf_psc);
  12443                     if (BCM_FAILURE(rv)) {
  12444                         sal_free(hwport);
  12445                         return rv;
  12446                     }
  12447                     hwft->psc[i] = hwf_psc;
  12448                 } else {
  12449                     /* Use trunk group value as the default */
  12450                     hwft->psc[i] = trunk_info->psc;
  12451                 }
  12452             }
  12453         }
  12454 
  12455         sal_free(hwport);
  12456     }
  12457 
  12458     if (soc_feature(unit, soc_feature_hg_dlb) &&
  12459         !soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) {
  12460 #ifdef BCM_TRIUMPH3_SUPPORT
  12461         if (soc_feature(unit, soc_feature_hg_dlb_member_id)) {
  12462             BCM_IF_ERROR_RETURN(_bcm_tr3_hg_dlb_member_recover(unit));
  12463         }
  12464 #endif /* BCM_TRIUMPH3_SUPPORT */
  12465 
  12466         BCM_IF_ERROR_RETURN
  12467             (_bcm_trident_hg_dlb_quality_parameters_recover(unit));
  12468     }
  12469 
  12470 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT)
  12471     if (soc_feature(unit, soc_feature_hg_dlb) &&
  12472         soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) {
  12473         BCM_IF_ERROR_RETURN(bcm_th2_hgt_lag_dlb_quality_parameters_recover(unit));
  12474     }
  12475 #endif /* BCM_TOMAHAWK2_SUPPORT */
  12476 
  12477     return rv;
  12478 }
  12479 
  12480 #endif /* BCM_WARM_BOOT_SUPPORT */
  12481 
  12482 #ifndef BCM_SW_STATE_DUMP_DISABLE
  12483 
  12484 /*
  12485  * Function:
  12486  *     _bcm_trident_hg_dlb_sw_dump
  12487  * Purpose:
  12488  *     Displays Higig DLB information maintained by software.
  12489  * Parameters:
  12490  *     unit - Device unit number
  12491  * Returns:
  12492  *     None
  12493  */
  12494 STATIC void
  12495 _bcm_trident_hg_dlb_sw_dump(int unit)
  12496 {
  12497     int i;
  12498     soc_mem_t flowset_mem, quality_mapping_mem;
  12499     int num_entries_per_profile;
  12500     int num_profiles;
  12501     int rv;
  12502     int ref_count;
  12503 
  12504     LOG_CLI((BSL_META_U(unit,
  12505                         "Higig DLB Info -\n")));
  12506 
  12507     /* Print Higig DLB group usage */
  12508     LOG_CLI((BSL_META_U(unit,
  12509                         "    Higig DLB Groups Used:")));
  12510     for (i = 0; i < soc_mem_index_count(unit, DLB_HGT_GROUP_CONTROLm); i++) {
  12511         if (_BCM_HG_DLB_ID_USED_GET(unit, i)) {
  12512             LOG_CLI((BSL_META_U(unit,
  12513                                 " %d"), i));
  12514         }
  12515     }
  12516     LOG_CLI((BSL_META_U(unit,
  12517                         "\n")));
  12518 
  12519     /* Print Higig DLB flowset table usage */
  12520     LOG_CLI((BSL_META_U(unit,
  12521                         "    Higig DLB Flowset Table Blocks Used:")));
  12522     flowset_mem = soc_mem_is_valid(unit, DLB_HGT_FLOWSETm) ?
  12523         DLB_HGT_FLOWSETm : DLB_HGT_FLOWSET_PORTm;
  12524     for (i = 0; i < (soc_mem_index_count(unit, flowset_mem) >> 9); i++) {
  12525         if (_BCM_HG_DLB_FLOWSET_BLOCK_USED_GET(unit, i)) {
  12526             LOG_CLI((BSL_META_U(unit,
  12527                                 " %d"), i));
  12528         }
  12529     }
  12530     LOG_CLI((BSL_META_U(unit,
  12531                         "\n")));
  12532 
  12533 #ifdef BCM_TRIUMPH3_SUPPORT
  12534     if (soc_feature(unit, soc_feature_hg_dlb_member_id)) {
  12535         /* Print Higig DLB member ID usage */
  12536         LOG_CLI((BSL_META_U(unit,
  12537                             "    Higig DLB Member IDs Used:")));
  12538         for (i = 0; i < soc_mem_index_count(unit, DLB_HGT_MEMBER_ATTRIBUTEm); i++) {
  12539             if (_BCM_HG_DLB_MEMBER_ID_USED_GET(unit, i)) {
  12540                 LOG_CLI((BSL_META_U(unit,
  12541                                     " %d"), i));
  12542             }
  12543         }
  12544         LOG_CLI((BSL_META_U(unit,
  12545                             "\n")));
  12546     }
  12547 #endif /* BCM_TRIUMPH3_SUPPORT */
  12548 
  12549     /* Print sample rate and threshold parameters */
  12550     LOG_CLI((BSL_META_U(unit,
  12551                         "    Sample rate: %d per second\n"),
  12552              HG_DLB_INFO(unit)->hg_dlb_sample_rate));
  12553     LOG_CLI((BSL_META_U(unit,
  12554                         "    Tx load min threshold: %d mbps\n"),
  12555              HG_DLB_INFO(unit)->hg_dlb_tx_load_min_th));
  12556     LOG_CLI((BSL_META_U(unit,
  12557                         "    Tx load max threshold: %d mbps\n"),
  12558              HG_DLB_INFO(unit)->hg_dlb_tx_load_max_th));
  12559     LOG_CLI((BSL_META_U(unit,
  12560                         "    Queue size min threshold: %d cells\n"),
  12561              HG_DLB_INFO(unit)->hg_dlb_qsize_min_th));
  12562     LOG_CLI((BSL_META_U(unit,
  12563                         "    Queue size max threshold: %d cells\n"),
  12564              HG_DLB_INFO(unit)->hg_dlb_qsize_max_th));
  12565 
  12566     /* Print quality mapping profiles */
  12567     LOG_CLI((BSL_META_U(unit,
  12568                         "    Quality mapping profiles:\n")));
  12569     num_entries_per_profile = 64;
  12570     quality_mapping_mem = soc_mem_is_valid(unit, DLB_HGT_QUALITY_MAPPINGm) ?
  12571         DLB_HGT_QUALITY_MAPPINGm : DLB_HGT_PORT_QUALITY_MAPPINGm;
  12572     num_profiles = soc_mem_index_count(unit, quality_mapping_mem) /
  12573         num_entries_per_profile;
  12574     for (i = 0; i < num_profiles; i++) {
  12575         LOG_CLI((BSL_META_U(unit,
  12576                             "      Profile %d: load weight %d percent, "),
  12577                  i, HG_DLB_INFO(unit)->hg_dlb_load_weight[i]));
  12578         rv = soc_profile_mem_ref_count_get(unit, 
  12579                 HG_DLB_INFO(unit)->hg_dlb_quality_map_profile,
  12580                 i * num_entries_per_profile, &ref_count);
  12581         if (SOC_FAILURE(rv)) {
  12582             LOG_CLI((BSL_META_U(unit,
  12583                                 "\n")));
  12584             continue;
  12585         }
  12586         LOG_CLI((BSL_META_U(unit,
  12587                             "ref count %d\n"), ref_count));
  12588     }
  12589 
  12590     return;
  12591 }
  12592 
  12593 /*
  12594  * Function:
  12595  *     _bcm_trident_trunk_sw_dump
  12596  * Purpose:
  12597  *     Displays trunk information maintained by software.
  12598  * Parameters:
  12599  *     unit - Device unit number
  12600  * Returns:
  12601  *     None
  12602  */
  12603 void
  12604 _bcm_trident_trunk_sw_dump(int unit)
  12605 {
  12606     int rv, i, j, tid_ix, tid_min, tid_max;
  12607     bcm_trunk_chip_info_t   chip_info;
  12608     _trident_trunk_swfail_t *swf;
  12609     _trident_tinfo_t        *swft;
  12610     int num_profiles;
  12611     int ref_count;
  12612 #if (SOC_MAX_NUM_PP_PORTS > SOC_MAX_NUM_PORTS)
  12613     int soc_max_num_ports = SOC_MAX_NUM_PP_PORTS;
  12614 #else
  12615     int soc_max_num_ports = SOC_MAX_NUM_PORTS;
  12616 #endif
  12617 
  12618     rv = bcm_esw_trunk_chip_info_get(unit, &chip_info);
  12619     if (BCM_FAILURE(rv)) {
  12620         LOG_CLI((BSL_META_U(unit,
  12621                             "Unable to retrieve unit %d chip info %d\n"),
  12622                  unit, rv));
  12623         return;
  12624     }
  12625 
  12626     if (chip_info.trunk_id_min < 0) {
  12627         if (chip_info.trunk_fabric_id_min < 0) {
  12628             /* No trunks!  Abort */
  12629             LOG_CLI((BSL_META_U(unit,
  12630                                 "No trunk groups on unit %d\n"), unit));
  12631             return;
  12632         } else {
  12633             tid_min = chip_info.trunk_fabric_id_min;
  12634             tid_max = chip_info.trunk_fabric_id_max;
  12635         }
  12636     } else {
  12637         tid_min = chip_info.trunk_id_min;
  12638         if (chip_info.trunk_fabric_id_min < 0) {
  12639             tid_max = chip_info.trunk_id_max;
  12640         } else {
  12641             tid_max = chip_info.trunk_fabric_id_max;
  12642         }
  12643     }
  12644 
  12645     /* Print software trunk failover states */
  12646 
  12647     swf = _trident_trunk_swfail[unit];
  12648     if (NULL != swf) {
  12649         LOG_CLI((BSL_META_U(unit,
  12650                             "Software failover parameters:\n")));
  12651         LOG_CLI((BSL_META_U(unit,
  12652                             "   Local modid:  %d\n"), swf->mymodid));
  12653         LOG_CLI((BSL_META_U(unit,
  12654                             "   Port:  Trunk\n")));
  12655         for (j = 0; j < soc_max_num_ports; j++) {
  12656             if (0 != swf->trunk[j]) {
  12657                 LOG_CLI((BSL_META_U(unit,
  12658                                     "   %d:  %d\n"),
  12659                          j, swf->trunk[j]-1));
  12660             }
  12661         }
  12662         LOG_CLI((BSL_META_U(unit,
  12663                             "   Trunk SW failover parameters\n")));
  12664         for (i = tid_min; i <= tid_max; i++) {
  12665             if (i >= chip_info.trunk_fabric_id_min) {
  12666                 tid_ix = (i - chip_info.trunk_fabric_id_min) +
  12667                     chip_info.trunk_group_count;
  12668             } else {
  12669                 tid_ix = i;
  12670             }
  12671             swft = &swf->tinfo[tid_ix];
  12672             if (0 != swft->num_ports) {
  12673                 LOG_CLI((BSL_META_U(unit,
  12674                                     "   Trunk %d, index %d\n"), i, tid_ix));
  12675                 LOG_CLI((BSL_META_U(unit,
  12676                                     "      Flags value 0x%x\n"), swft->flags));
  12677                 LOG_CLI((BSL_META_U(unit,
  12678                                     "      RTAG value %d\n"), swft->rtag));
  12679                 LOG_CLI((BSL_META_U(unit,
  12680                                     "      Port count %d\n"), swft->num_ports));
  12681                 for (j = 0; j < swft->num_ports; j++) {
  12682                     LOG_CLI((BSL_META_U(unit,
  12683                                         "      ModPort 0x%04x\n"), swft->modport[j]));
  12684                 }
  12685             }
  12686         }
  12687     } else {
  12688         LOG_CLI((BSL_META_U(unit,
  12689                             "SW trunk failover not initialized on unit %d\n"),
  12690                  unit));
  12691     }
  12692 
  12693     /* Print hardware trunk failover states */
  12694     if (soc_feature(unit, soc_feature_port_lag_failover) ||
  12695         soc_feature(unit, soc_feature_hg_trunk_failover)) {
  12696         _trident_hw_tinfo_t *hwft;
  12697 
  12698         if (NULL == _trident_trunk_hwfail[unit]) {
  12699             LOG_CLI((BSL_META_U(unit,
  12700                                 "HW trunk failover not initialized on unit %d\n"),
  12701                      unit));
  12702             return;
  12703         }
  12704         LOG_CLI((BSL_META_U(unit,
  12705                             "Trunk HW failover parameters\n")));
  12706         for (i = tid_min; i <= tid_max; i++) {
  12707             if (i >= chip_info.trunk_fabric_id_min) {
  12708                 tid_ix = (i - chip_info.trunk_fabric_id_min) +
  12709                     chip_info.trunk_group_count;
  12710             } else {
  12711                 tid_ix = i;
  12712             }
  12713             hwft = &(_trident_trunk_hwfail[unit]->hw_tinfo[tid_ix]);
  12714             if (0 != hwft->num_ports) {
  12715                 LOG_CLI((BSL_META_U(unit,
  12716                                     "   Trunk %d, index %d\n"), i, tid_ix));
  12717                 LOG_CLI((BSL_META_U(unit,
  12718                                     "      Port count %d\n"), hwft->num_ports));
  12719                 for (j = 0; j < hwft->num_ports; j++) {
  12720                     LOG_CLI((BSL_META_U(unit,
  12721                                         "      PSC value %d\n"), hwft->psc[j]));
  12722                     LOG_CLI((BSL_META_U(unit,
  12723                                         "      Flags 0x%08x\n"), hwft->flags[j]));
  12724                     LOG_CLI((BSL_META_U(unit,
  12725                                         "      ModPort 0x%04x\n"), hwft->modport[j]));
  12726                 }
  12727             }
  12728         }
  12729     }
  12730 
  12731     /* Print Higig trunk override profile info */
  12732     LOG_CLI((BSL_META_U(unit,
  12733                         "Higig trunk override profile info\n")));
  12734     num_profiles = soc_mem_index_count(unit, ING_HIGIG_TRUNK_OVERRIDE_PROFILEm);
  12735     for (i = 0; i < num_profiles; i++) {
  12736         rv = soc_profile_mem_ref_count_get(unit,
  12737                 _trident_hg_trunk_override_profile[unit],
  12738                 i, &ref_count);
  12739         if (SOC_FAILURE(rv)) {
  12740             continue;
  12741         }
  12742         if (ref_count > 0) {
  12743             LOG_CLI((BSL_META_U(unit,
  12744                                 "   Higig trunk override profile %d ref count %d\n"),
  12745                      i, ref_count));
  12746         }
  12747     }
  12748 
  12749     /* Print trunk membership info */
  12750     if (NULL != _trident_trunk_member_info[unit]) {
  12751         LOG_CLI((BSL_META_U(unit,
  12752                             "Trunk membership info:\n")));
  12753         for (i = tid_min; i <= tid_max; i++) {
  12754             if (i >= chip_info.trunk_fabric_id_min) {
  12755                 tid_ix = (i - chip_info.trunk_fabric_id_min) +
  12756                     chip_info.trunk_group_count;
  12757             } else {
  12758                 tid_ix = i;
  12759             }
  12760 
  12761             if (0 != MEMBER_INFO(unit, tid_ix).num_ports) {
  12762                 LOG_CLI((BSL_META_U(unit,
  12763                                     "   Trunk %d, index %d\n"), i, tid_ix));
  12764                 LOG_CLI((BSL_META_U(unit,
  12765                                     "      Port count %d\n"),
  12766                          MEMBER_INFO(unit, tid_ix).num_ports));
  12767                 for (j = 0; j < MEMBER_INFO(unit, tid_ix).num_ports; j++) {
  12768                     LOG_CLI((BSL_META_U(unit,
  12769                                         "      ModPort 0x%04x\n"),
  12770                              MEMBER_INFO(unit, tid_ix).modport[j]));
  12771                     LOG_CLI((BSL_META_U(unit,
  12772                                         "      Member flags 0x%x\n"),
  12773                              MEMBER_INFO(unit, tid_ix).member_flags[j]));
  12774                 }
  12775             }
  12776         }
  12777     } else {
  12778         LOG_CLI((BSL_META_U(unit,
  12779                             "Trunk membership info not initialized on unit %d\n"),
  12780                  unit));
  12781     }
  12782 
  12783     if (soc_feature(unit, soc_feature_hg_dlb) &&
  12784         !soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) {
  12785         _bcm_trident_hg_dlb_sw_dump(unit);
  12786     }
  12787 #ifdef BCM_TRIUMPH3_SUPPORT
  12788     if (soc_feature(unit, soc_feature_lag_dlb) &&
  12789         !soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) {
  12790         bcm_tr3_lag_dlb_sw_dump(unit);
  12791     }
  12792 #endif /* BCM_TRIUMPH3_SUPPORT */
  12793 
  12794 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT)
  12795     if (soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) {
  12796         bcm_th2_hgt_lag_dlb_sw_dump(unit);
  12797     }
  12798 #endif /* BCM_TOMAHAWK2_SUPPORT */
  12799 
  12800 #ifdef BCM_TRIDENT2_SUPPORT
  12801     if (soc_feature(unit, soc_feature_hg_resilient_hash)) {
  12802         bcm_td2_hg_rh_sw_dump(unit);
  12803     }
  12804     if (soc_feature(unit, soc_feature_lag_resilient_hash)) {
  12805         bcm_td2_lag_rh_sw_dump(unit);
  12806     }
  12807 #endif /* BCM_TRIDENT2_SUPPORT */
  12808 
  12809     return;
  12810 }
  12811 #endif /* BCM_SW_STATE_DUMP_DISABLE */
  12812 
  12813 #else /* BCM_TRIDENT_SUPPORT */
  12814 
  12815 int _trident_trunk_not_empty;
  12816 
  12817 #endif /* BCM_TRIDENT_SUPPORT */