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


      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  * Triumph3 LAG dynamic load balancing
      8  */
      9 
     10 #include <soc/defs.h>
     11 #include <sal/core/libc.h>
     12 #include <shared/bsl.h>
     13 #ifdef BCM_TRIUMPH3_SUPPORT 
     14 
     15 #include <soc/mem.h>
     16 #include <soc/profile_mem.h>
     17 
     18 #include <bcm/error.h>
     19 
     20 #include <bcm_int/esw/mbcm.h>
     21 #include <bcm_int/esw/trunk.h>
     22 #include <bcm_int/esw_dispatch.h>
     23 
     24 /* ------------------------------------------------- */
     25 /* Bookkeeping info for LAG dynamic load balancing */
     26 /* ------------------------------------------------- */
     27 
     28 typedef struct _tr3_lag_dlb_bookkeeping_s {
     29     SHR_BITDCL *lag_dlb_id_used_bitmap;
     30     SHR_BITDCL *lag_dlb_flowset_block_bitmap; /* Each block corresponds to
     31                                                  512 entries */
     32     SHR_BITDCL *lag_dlb_member_id_used_bitmap;
     33     int lag_dlb_sample_rate;
     34     int lag_dlb_tx_load_min_th;
     35     int lag_dlb_tx_load_max_th;
     36     int lag_dlb_qsize_min_th;
     37     int lag_dlb_qsize_max_th;
     38     int lag_dlb_exp_load_min_th;
     39     int lag_dlb_exp_load_max_th;
     40     int lag_dlb_imbalance_min_th;
     41     int lag_dlb_imbalance_max_th;
     42     uint8 *lag_dlb_load_weight;
     43     soc_profile_mem_t *lag_dlb_quality_map_profile;
     44 #ifdef BCM_WARM_BOOT_SUPPORT
     45     uint8 recovered_from_scache; /* Indicates if the following members of this
     46                                     structure have been recovered from scached:
     47                                     lag_dlb_sample_rate,
     48                                     lag_dlb_tx_load_min_th,
     49                                     lag_dlb_tx_load_max_th,
     50                                     lag_dlb_tx_qsize_min_th,
     51                                     lag_dlb_tx_qsize_max_th,
     52                                     lag_dlb_exp_load_min_th,
     53                                     lag_dlb_exp_load_max_th,
     54                                     lag_dlb_imbalance_min_th,
     55                                     lag_dlb_imbalance_max_th,
     56                                     lag_dlb_load_weight */
     57 #endif /* BCM_WARM_BOOT_SUPPORT */
     58 } _tr3_lag_dlb_bookkeeping_t;
     59 
     60 static _tr3_lag_dlb_bookkeeping_t *_tr3_lag_dlb_bk[BCM_MAX_NUM_UNITS];
     61 
     62 #define LAG_DLB_INFO(_unit_) (_tr3_lag_dlb_bk[_unit_])
     63 
     64 #define _BCM_LAG_DLB_ID_USED_GET(_u_, _idx_) \
     65     SHR_BITGET(LAG_DLB_INFO(_u_)->lag_dlb_id_used_bitmap, _idx_)
     66 #define _BCM_LAG_DLB_ID_USED_SET(_u_, _idx_) \
     67     SHR_BITSET(LAG_DLB_INFO(_u_)->lag_dlb_id_used_bitmap, _idx_)
     68 #define _BCM_LAG_DLB_ID_USED_CLR(_u_, _idx_) \
     69     SHR_BITCLR(LAG_DLB_INFO(_u_)->lag_dlb_id_used_bitmap, _idx_)
     70 
     71 #define _BCM_LAG_DLB_FLOWSET_BLOCK_USED_GET(_u_, _idx_) \
     72     SHR_BITGET(LAG_DLB_INFO(_u_)->lag_dlb_flowset_block_bitmap, _idx_)
     73 #define _BCM_LAG_DLB_FLOWSET_BLOCK_USED_SET(_u_, _idx_) \
     74     SHR_BITSET(LAG_DLB_INFO(_u_)->lag_dlb_flowset_block_bitmap, _idx_)
     75 #define _BCM_LAG_DLB_FLOWSET_BLOCK_USED_CLR(_u_, _idx_) \
     76     SHR_BITCLR(LAG_DLB_INFO(_u_)->lag_dlb_flowset_block_bitmap, _idx_)
     77 #define _BCM_LAG_DLB_FLOWSET_BLOCK_USED_SET_RANGE(_u_, _idx_, _count_) \
     78     SHR_BITSET_RANGE(LAG_DLB_INFO(_u_)->lag_dlb_flowset_block_bitmap, _idx_, _count_)
     79 #define _BCM_LAG_DLB_FLOWSET_BLOCK_USED_CLR_RANGE(_u_, _idx_, _count_) \
     80     SHR_BITCLR_RANGE(LAG_DLB_INFO(_u_)->lag_dlb_flowset_block_bitmap, _idx_, _count_)
     81 #define _BCM_LAG_DLB_FLOWSET_BLOCK_TEST_RANGE(_u_, _idx_, _count_, _result_) \
     82     SHR_BITTEST_RANGE(LAG_DLB_INFO(_u_)->lag_dlb_flowset_block_bitmap, _idx_, _count_, _result_)
     83 
     84 #define _BCM_LAG_DLB_MEMBER_ID_USED_GET(_u_, _idx_) \
     85     SHR_BITGET(LAG_DLB_INFO(_u_)->lag_dlb_member_id_used_bitmap, _idx_)
     86 #define _BCM_LAG_DLB_MEMBER_ID_USED_SET(_u_, _idx_) \
     87     SHR_BITSET(LAG_DLB_INFO(_u_)->lag_dlb_member_id_used_bitmap, _idx_)
     88 #define _BCM_LAG_DLB_MEMBER_ID_USED_CLR(_u_, _idx_) \
     89     SHR_BITCLR(LAG_DLB_INFO(_u_)->lag_dlb_member_id_used_bitmap, _idx_)
     90 
     91 /* Function prototypes */
     92 
     93 STATIC int _bcm_tr3_lag_dlb_quality_assign(int unit, int tx_load_percent,
     94         uint32 *entry_arr);
     95 STATIC int _bcm_tr3_lag_dlb_sample_rate_pla_thresholds_set(int unit,
     96         int sample_rate, int min_th, int max_th);
     97 STATIC int _bcm_tr3_lag_dlb_sample_rate_vla_thresholds_set(int unit,
     98         int sample_rate, int exp_load_min_th, int exp_load_max_th,
     99         int imbalance_min_th, int imbalance_max_th);
    100 STATIC int _bcm_tr3_lag_dlb_qsize_thresholds_set(int unit, int min_th,
    101         int max_th);
    102 
    103 
    104 /*
    105  * Function:
    106  *      _bcm_tr3_lag_dlb_quality_map_profile_init
    107  * Purpose:
    108  *      Initialize LAG DLB quality mapping profile.
    109  * Parameters:
    110  *      unit - (IN)SOC unit number. 
    111  * Returns:
    112  *      BCM_X_XXX
    113  */
    114 STATIC int 
    115 _bcm_tr3_lag_dlb_quality_map_profile_init(int unit) 
    116 {
    117     soc_profile_mem_t *profile;
    118     soc_mem_t mem;
    119     int entry_words;
    120     int entries_per_profile;
    121     int tx_load_percent;
    122     int alloc_size;
    123     uint32 *entry_arr;
    124     int rv = BCM_E_NONE;
    125     void *entries;
    126     uint32 base_index;
    127     int i;
    128     int member_id;
    129     dlb_lag_quality_control_entry_t quality_control_entry;
    130 
    131     if (NULL == _tr3_lag_dlb_bk[unit]->lag_dlb_quality_map_profile) {
    132         _tr3_lag_dlb_bk[unit]->lag_dlb_quality_map_profile =
    133             sal_alloc(sizeof(soc_profile_mem_t),
    134                       "LAG DLB Quality Map Profile Mem");
    135         if (NULL == _tr3_lag_dlb_bk[unit]->lag_dlb_quality_map_profile) {
    136             return BCM_E_MEMORY;
    137         }
    138     } else {
    139         soc_profile_mem_destroy(unit,
    140                 _tr3_lag_dlb_bk[unit]->lag_dlb_quality_map_profile);
    141     }
    142     profile = _tr3_lag_dlb_bk[unit]->lag_dlb_quality_map_profile;
    143     soc_profile_mem_t_init(profile);
    144 
    145     mem = DLB_LAG_QUALITY_MAPPINGm;
    146     entry_words = sizeof(dlb_lag_quality_mapping_entry_t) / sizeof(uint32);
    147     SOC_IF_ERROR_RETURN
    148         (soc_profile_mem_create(unit, &mem, &entry_words, 1, profile));
    149 
    150     entries_per_profile = 64;
    151     if (!SOC_WARM_BOOT(unit)) {
    152         alloc_size = entries_per_profile * entry_words * sizeof(uint32);
    153         entry_arr = sal_alloc(alloc_size, "LAG DLB Quality Map entries");
    154         if (entry_arr == NULL) {
    155             return BCM_E_MEMORY;
    156         }
    157         sal_memset(entry_arr, 0, alloc_size);
    158 
    159         /* Assign quality in the entry array, with 100% weight for port load,
    160          * 0% for queue size.
    161          */
    162         tx_load_percent = 100;
    163         rv = _bcm_tr3_lag_dlb_quality_assign(unit, tx_load_percent,
    164                 entry_arr);
    165         if (BCM_FAILURE(rv)) {
    166             sal_free(entry_arr);
    167             return rv;
    168         }
    169 
    170         entries = entry_arr;
    171         rv = soc_profile_mem_add(unit, profile, &entries, entries_per_profile,
    172                 &base_index);
    173         sal_free(entry_arr);
    174         if (SOC_FAILURE(rv)) {
    175             return rv;
    176         }
    177 
    178         for (member_id = 0;
    179                 member_id < soc_mem_index_count(unit,
    180                     DLB_LAG_QUALITY_CONTROLm);
    181                 member_id++) {
    182             BCM_IF_ERROR_RETURN
    183                 (READ_DLB_LAG_QUALITY_CONTROLm(unit, MEM_BLOCK_ANY,
    184                                                member_id,
    185                                                &quality_control_entry));
    186             soc_DLB_LAG_QUALITY_CONTROLm_field32_set(unit,
    187                     &quality_control_entry, PROFILE_PTRf,
    188                     base_index / entries_per_profile);
    189             BCM_IF_ERROR_RETURN
    190                 (WRITE_DLB_LAG_QUALITY_CONTROLm(unit, MEM_BLOCK_ALL,
    191                                                 member_id,
    192                                                 &quality_control_entry));
    193         }  
    194 
    195         for (i = 0; i < entries_per_profile; i++) {
    196             SOC_PROFILE_MEM_REFERENCE(unit, profile, base_index + i,
    197                     member_id - 1);
    198         }
    199 
    200         LAG_DLB_INFO(unit)->
    201             lag_dlb_load_weight[base_index/entries_per_profile] = 
    202                 tx_load_percent;
    203 
    204     } else { /* Warm boot, recover reference counts and entries_per_set */
    205 
    206         for (member_id = 0;
    207                 member_id < soc_mem_index_count(unit,
    208                     DLB_LAG_QUALITY_CONTROLm);
    209                 member_id++) {
    210             BCM_IF_ERROR_RETURN
    211                 (READ_DLB_LAG_QUALITY_CONTROLm(unit, MEM_BLOCK_ANY,
    212                                                member_id,
    213                                                &quality_control_entry));
    214             base_index = soc_DLB_LAG_QUALITY_CONTROLm_field32_get(unit,
    215                     &quality_control_entry, PROFILE_PTRf);
    216             base_index *= entries_per_profile;
    217             for (i = 0; i < entries_per_profile; i++) {
    218                 SOC_PROFILE_MEM_REFERENCE(unit, profile, base_index + i, 1);
    219                 SOC_PROFILE_MEM_ENTRIES_PER_SET(unit, profile,
    220                         base_index + i, entries_per_profile);
    221             }
    222         }  
    223     }
    224 
    225     return BCM_E_NONE;
    226 }
    227 
    228 /*
    229  * Function:
    230  *      bcm_tr3_lag_dlb_deinit
    231  * Purpose:
    232  *      Deallocate _tr3_lag_dlb_bk
    233  * Parameters:
    234  *      unit - (IN)SOC unit number. 
    235  * Returns:
    236  *      None
    237  */
    238 void
    239 bcm_tr3_lag_dlb_deinit(int unit) 
    240 {
    241     int rv;
    242     uint32 rsel2_hw_control_reg;
    243 
    244     if (_tr3_lag_dlb_bk[unit]) {
    245         if (_tr3_lag_dlb_bk[unit]->lag_dlb_id_used_bitmap) {
    246             sal_free(_tr3_lag_dlb_bk[unit]->lag_dlb_id_used_bitmap);
    247             _tr3_lag_dlb_bk[unit]->lag_dlb_id_used_bitmap = NULL;
    248         }
    249         if (_tr3_lag_dlb_bk[unit]->lag_dlb_flowset_block_bitmap) {
    250             sal_free(_tr3_lag_dlb_bk[unit]->lag_dlb_flowset_block_bitmap);
    251             _tr3_lag_dlb_bk[unit]->lag_dlb_flowset_block_bitmap = NULL;
    252         }
    253         if (_tr3_lag_dlb_bk[unit]->lag_dlb_member_id_used_bitmap) {
    254             sal_free(_tr3_lag_dlb_bk[unit]->lag_dlb_member_id_used_bitmap);
    255             _tr3_lag_dlb_bk[unit]->lag_dlb_member_id_used_bitmap = NULL;
    256         }
    257         if (_tr3_lag_dlb_bk[unit]->lag_dlb_load_weight) {
    258             sal_free(_tr3_lag_dlb_bk[unit]->lag_dlb_load_weight);
    259             _tr3_lag_dlb_bk[unit]->lag_dlb_load_weight = NULL;
    260         }
    261         if (_tr3_lag_dlb_bk[unit]->lag_dlb_quality_map_profile) {
    262             soc_profile_mem_destroy(unit,
    263                     _tr3_lag_dlb_bk[unit]->lag_dlb_quality_map_profile);
    264             sal_free(_tr3_lag_dlb_bk[unit]->lag_dlb_quality_map_profile);
    265             _tr3_lag_dlb_bk[unit]->lag_dlb_quality_map_profile = NULL;
    266         }
    267 
    268         sal_free(_tr3_lag_dlb_bk[unit]);
    269         _tr3_lag_dlb_bk[unit] = NULL;
    270     }
    271 
    272     rv = READ_RSEL2_HW_CONTROLr(unit, &rsel2_hw_control_reg);
    273     if (SOC_SUCCESS(rv)) {
    274         soc_reg_field_set(unit, RSEL2_HW_CONTROLr, &rsel2_hw_control_reg,
    275                 ENABLE_LAG_DLBf, 0);
    276         (void)WRITE_RSEL2_HW_CONTROLr(unit, rsel2_hw_control_reg);
    277     }
    278 }
    279 
    280 /*
    281  * Function:
    282  *      bcm_tr3_lag_dlb_init
    283  * Purpose:
    284  *      Allocate and initialize _tr3_lag_dlb_bk
    285  * Parameters:
    286  *      unit - (IN)SOC unit number. 
    287  * Returns:
    288  *      BCM_X_XXX
    289  */
    290 int 
    291 bcm_tr3_lag_dlb_init(int unit) 
    292 {
    293     int rv = BCM_E_NONE;
    294     int num_lag_dlb_id;
    295     int lag_flowset_tbl_size;
    296     int total_num_blocks;
    297     int num_lag_dlb_member_id;
    298     int num_quality_map_profiles;
    299     int member_id;
    300     dlb_lag_quality_control_entry_t quality_control_entry;
    301     uint32 rsel2_hw_control_reg;
    302     uint32 measure_control_reg;
    303     int sample_rate;
    304 
    305     if ((SOC_IS_TRIDENT2X(unit) || SOC_IS_TITAN2PLUS(unit))) {
    306         return BCM_E_NONE;
    307     } 
    308 
    309     if (_tr3_lag_dlb_bk[unit] == NULL) {
    310         _tr3_lag_dlb_bk[unit] = sal_alloc(
    311                 sizeof(_tr3_lag_dlb_bookkeeping_t), "_tr3_lag_dlb_bk");
    312         if (_tr3_lag_dlb_bk[unit] == NULL) {
    313             return BCM_E_MEMORY;
    314         }
    315     }
    316     sal_memset(_tr3_lag_dlb_bk[unit], 0, sizeof(_tr3_lag_dlb_bookkeeping_t));
    317 
    318     num_lag_dlb_id = soc_mem_index_count(unit, DLB_LAG_GROUP_CONTROLm);
    319     if (_tr3_lag_dlb_bk[unit]->lag_dlb_id_used_bitmap == NULL) {
    320         _tr3_lag_dlb_bk[unit]->lag_dlb_id_used_bitmap = 
    321             sal_alloc(SHR_BITALLOCSIZE(num_lag_dlb_id),
    322                     "lag_dlb_id_used_bitmap");
    323         if (_tr3_lag_dlb_bk[unit]->lag_dlb_id_used_bitmap == NULL) {
    324             bcm_tr3_lag_dlb_deinit(unit);
    325             return BCM_E_MEMORY;
    326         }
    327     }
    328     sal_memset(_tr3_lag_dlb_bk[unit]->lag_dlb_id_used_bitmap, 0,
    329             SHR_BITALLOCSIZE(num_lag_dlb_id));
    330 
    331     lag_flowset_tbl_size = soc_mem_index_count(unit, DLB_LAG_FLOWSETm);
    332     /* Each bit in lag_dlb_flowset_block_bitmap corresponds to a block of 512
    333      * flow set table entries.
    334      */
    335     total_num_blocks = lag_flowset_tbl_size / 512;
    336     if (_tr3_lag_dlb_bk[unit]->lag_dlb_flowset_block_bitmap == NULL) {
    337         _tr3_lag_dlb_bk[unit]->lag_dlb_flowset_block_bitmap = 
    338             sal_alloc(SHR_BITALLOCSIZE(total_num_blocks),
    339                     "lag_dlb_flowset_block_bitmap");
    340         if (_tr3_lag_dlb_bk[unit]->lag_dlb_flowset_block_bitmap == NULL) {
    341             bcm_tr3_lag_dlb_deinit(unit);
    342             return BCM_E_MEMORY;
    343         }
    344     }
    345     sal_memset(_tr3_lag_dlb_bk[unit]->lag_dlb_flowset_block_bitmap, 0,
    346             SHR_BITALLOCSIZE(total_num_blocks));
    347 
    348     num_lag_dlb_member_id = soc_mem_index_count(unit,
    349             DLB_LAG_MEMBER_ATTRIBUTEm);
    350     if (_tr3_lag_dlb_bk[unit]->lag_dlb_member_id_used_bitmap == NULL) {
    351         _tr3_lag_dlb_bk[unit]->lag_dlb_member_id_used_bitmap = 
    352             sal_alloc(SHR_BITALLOCSIZE(num_lag_dlb_member_id),
    353                     "lag_dlb_member_id_used_bitmap");
    354         if (_tr3_lag_dlb_bk[unit]->lag_dlb_member_id_used_bitmap == NULL) {
    355             bcm_tr3_lag_dlb_deinit(unit);
    356             return BCM_E_MEMORY;
    357         }
    358     }
    359     sal_memset(_tr3_lag_dlb_bk[unit]->lag_dlb_member_id_used_bitmap, 0,
    360                 SHR_BITALLOCSIZE(num_lag_dlb_member_id));
    361 
    362     num_quality_map_profiles = 1 << soc_mem_field_length(unit,
    363             DLB_LAG_QUALITY_CONTROLm, PROFILE_PTRf);
    364     if (_tr3_lag_dlb_bk[unit]->lag_dlb_load_weight == NULL) {
    365         _tr3_lag_dlb_bk[unit]->lag_dlb_load_weight = 
    366             sal_alloc(num_quality_map_profiles * sizeof(uint8),
    367                     "lag_dlb_load_weight");
    368         if (_tr3_lag_dlb_bk[unit]->lag_dlb_load_weight == NULL) {
    369             bcm_tr3_lag_dlb_deinit(unit);
    370             return BCM_E_MEMORY;
    371         }
    372     }
    373     sal_memset(_tr3_lag_dlb_bk[unit]->lag_dlb_load_weight, 0,
    374             num_quality_map_profiles * sizeof(uint8));
    375 
    376     /* Initialize port quality mapping profile */
    377     rv = _bcm_tr3_lag_dlb_quality_map_profile_init(unit);
    378     if (BCM_FAILURE(rv)) {
    379         bcm_tr3_lag_dlb_deinit(unit);
    380         return rv;
    381     }
    382 
    383     if (!SOC_WARM_BOOT(unit)) {
    384 
    385         /* Configure accounting mode to physical link accounting */
    386         rv = bcm_tr3_lag_dlb_config_set(unit,
    387                 bcmSwitchTrunkDynamicAccountingSelect, 0);
    388         if (BCM_FAILURE(rv)) {
    389             bcm_tr3_lag_dlb_deinit(unit);
    390             return rv;
    391         }
    392 
    393         /* Set DLB sampling period and load thresholds */
    394         sample_rate = 1000;
    395         rv = _bcm_tr3_lag_dlb_sample_rate_pla_thresholds_set(unit, sample_rate,
    396                 125, 875);
    397         if (BCM_FAILURE(rv)) {
    398             bcm_tr3_lag_dlb_deinit(unit);
    399             return rv;
    400         }
    401         rv = _bcm_tr3_lag_dlb_sample_rate_vla_thresholds_set(unit, sample_rate,
    402                 125, 875, -75, 75);
    403         if (BCM_FAILURE(rv)) {
    404             bcm_tr3_lag_dlb_deinit(unit);
    405             return rv;
    406         }
    407 
    408         /* Configure LAG DLB load EWMA weight */
    409         rv = bcm_tr3_lag_dlb_config_set(unit,
    410                 bcmSwitchTrunkDynamicEgressBytesExponent, 0);
    411         if (BCM_FAILURE(rv)) {
    412             bcm_tr3_lag_dlb_deinit(unit);
    413             return rv;
    414         }
    415 
    416         /* Configure LAG DLB queue size EWMA weight */
    417         rv = bcm_tr3_lag_dlb_config_set(unit,
    418                 bcmSwitchTrunkDynamicQueuedBytesExponent, 0);
    419         if (BCM_FAILURE(rv)) {
    420             bcm_tr3_lag_dlb_deinit(unit);
    421             return rv;
    422         }
    423 
    424         /* Configure LAG DLB load cap control */
    425         rv = bcm_tr3_lag_dlb_config_set(unit,
    426                 bcmSwitchTrunkDynamicEgressBytesDecreaseReset, 0);
    427         if (BCM_FAILURE(rv)) {
    428             bcm_tr3_lag_dlb_deinit(unit);
    429             return rv;
    430         }
    431 
    432         /* Configure LAG DLB queue size cap control */
    433         rv = bcm_tr3_lag_dlb_config_set(unit,
    434                 bcmSwitchTrunkDynamicQueuedBytesDecreaseReset, 0);
    435         if (BCM_FAILURE(rv)) {
    436             bcm_tr3_lag_dlb_deinit(unit);
    437             return rv;
    438         }
    439 
    440         /* Configure LAG DLB queue size thresholds */
    441         rv = _bcm_tr3_lag_dlb_qsize_thresholds_set(unit, 0, 0);
    442         if (BCM_FAILURE(rv)) {
    443             bcm_tr3_lag_dlb_deinit(unit);
    444             return rv;
    445         }
    446 
    447         /* Disable link status override by software */
    448         rv = soc_mem_clear(unit, DLB_LAG_MEMBER_SW_STATEm, MEM_BLOCK_ALL, 0);
    449         if (BCM_FAILURE(rv)) {
    450             bcm_tr3_lag_dlb_deinit(unit);
    451             return rv;
    452         }
    453 
    454         /* Clear group membership */
    455         rv = soc_mem_clear(unit, DLB_LAG_GROUP_MEMBERSHIPm, MEM_BLOCK_ALL, 0);
    456         if (BCM_FAILURE(rv)) {
    457             bcm_tr3_lag_dlb_deinit(unit);
    458             return rv;
    459         }
    460 
    461         /* Clear port<->member mapping tables */
    462         rv = soc_mem_clear(unit, DLB_LAG_MEMBERSHIP_REVERSE_MAPm,
    463                 MEM_BLOCK_ALL, 0);
    464         if (BCM_FAILURE(rv)) {
    465             bcm_tr3_lag_dlb_deinit(unit);
    466             return rv;
    467         }
    468         rv = soc_mem_clear(unit, DLB_LAG_MEMBER_ATTRIBUTEm, MEM_BLOCK_ALL, 0);
    469         if (BCM_FAILURE(rv)) {
    470             bcm_tr3_lag_dlb_deinit(unit);
    471             return rv;
    472         }
    473 
    474         /* Configure per member threshold scaling factor and 
    475          * quality measure update control.
    476          */
    477         for (member_id = 0;
    478                 member_id < soc_mem_index_count(unit,
    479                     DLB_LAG_QUALITY_CONTROLm);
    480                 member_id++) {
    481             rv = READ_DLB_LAG_QUALITY_CONTROLm(unit, MEM_BLOCK_ANY,
    482                     member_id, &quality_control_entry);
    483             if (SOC_FAILURE(rv)) {
    484                 bcm_tr3_lag_dlb_deinit(unit);
    485                 return rv;
    486             }
    487             soc_DLB_LAG_QUALITY_CONTROLm_field32_set(unit,
    488                     &quality_control_entry, ENABLE_AVG_CALCf, 1);
    489             soc_DLB_LAG_QUALITY_CONTROLm_field32_set(unit,
    490                     &quality_control_entry, ENABLE_QUALITY_UPDATEf, 1);
    491             soc_DLB_LAG_QUALITY_CONTROLm_field32_set(unit,
    492                     &quality_control_entry, ENABLE_CREDIT_COLLECTIONf, 1);
    493             soc_DLB_LAG_QUALITY_CONTROLm_field32_set(unit,
    494                     &quality_control_entry, LOADING_SCALING_FACTORf, 1);
    495             soc_DLB_LAG_QUALITY_CONTROLm_field32_set(unit,
    496                     &quality_control_entry, QSIZE_SCALING_FACTORf, 1);
    497             rv = WRITE_DLB_LAG_QUALITY_CONTROLm(unit, MEM_BLOCK_ALL,
    498                     member_id, &quality_control_entry);
    499             if (SOC_FAILURE(rv)) {
    500                 bcm_tr3_lag_dlb_deinit(unit);
    501                 return rv;
    502             }
    503         }
    504 
    505         /* Enable DLB HGT refresh */
    506 
    507         rv = READ_RSEL2_HW_CONTROLr(unit, &rsel2_hw_control_reg);
    508         if (BCM_SUCCESS(rv)) {
    509             soc_reg_field_set(unit, RSEL2_HW_CONTROLr, &rsel2_hw_control_reg,
    510                     ENABLE_LAG_DLBf, 1);
    511             rv = WRITE_RSEL2_HW_CONTROLr(unit, rsel2_hw_control_reg);
    512         }
    513         if (BCM_FAILURE(rv)) {
    514             bcm_tr3_lag_dlb_deinit(unit);
    515             return rv;
    516         }
    517 
    518         /* Configure Ethertype eligibility */
    519 
    520         rv = soc_mem_clear(unit, DLB_LAG_ETHERTYPE_ELIGIBILITY_MAPm,
    521                 MEM_BLOCK_ALL, 0);
    522         if (BCM_FAILURE(rv)) {
    523             bcm_tr3_lag_dlb_deinit(unit);
    524             return rv;
    525         }
    526         rv = READ_DLB_LAG_QUALITY_MEASURE_CONTROLr(unit,
    527                 &measure_control_reg);
    528         if (SOC_SUCCESS(rv)) {
    529             soc_reg_field_set(unit, DLB_LAG_QUALITY_MEASURE_CONTROLr,
    530                     &measure_control_reg,
    531                     ETHERTYPE_ELIGIBILITY_CONFIGf, 0);
    532             soc_reg_field_set(unit, DLB_LAG_QUALITY_MEASURE_CONTROLr,
    533                     &measure_control_reg,
    534                     INNER_OUTER_ETHERTYPE_SELECTIONf, 0);
    535             rv = WRITE_DLB_LAG_QUALITY_MEASURE_CONTROLr(unit,
    536                     measure_control_reg);
    537         }
    538         if (BCM_FAILURE(rv)) {
    539             bcm_tr3_lag_dlb_deinit(unit);
    540             return rv;
    541         }
    542 
    543     }
    544 
    545     return rv;
    546 }
    547 
    548 /*
    549  * Function:
    550  *      _bcm_tr3_lag_dlb_accounting_set
    551  * Purpose:
    552  *      Set LAG DLB accounting mode.
    553  * Parameters:
    554  *      unit - (IN) SOC unit number.
    555  *      accounting_mode - (IN) Accounting mode.
    556  * Returns:
    557  *      BCM_E_xxx
    558  */
    559 STATIC int
    560 _bcm_tr3_lag_dlb_accounting_set(int unit, int accounting_mode)
    561 {
    562     uint32 measure_control_reg;
    563     int old_accounting_mode;
    564     SHR_BITDCL active;
    565 
    566     SOC_IF_ERROR_RETURN
    567         (READ_DLB_LAG_QUALITY_MEASURE_CONTROLr(unit, &measure_control_reg));
    568     old_accounting_mode = soc_reg_field_get(unit,
    569             DLB_LAG_QUALITY_MEASURE_CONTROLr, measure_control_reg,
    570             ACCOUNTING_SELf);
    571     if (old_accounting_mode == accounting_mode) {
    572         return BCM_E_NONE;
    573     }
    574 
    575     SHR_BITTEST_RANGE(LAG_DLB_INFO(unit)->lag_dlb_id_used_bitmap,
    576             0, soc_mem_index_count(unit, DLB_LAG_GROUP_CONTROLm), active);
    577     if (active) {
    578         /* Accounting mode cannot be changed while there are active
    579          * DLB groups.
    580          */
    581         return BCM_E_BUSY;
    582     }
    583 
    584     soc_reg_field_set(unit, DLB_LAG_QUALITY_MEASURE_CONTROLr,
    585         &measure_control_reg, ACCOUNTING_SELf, accounting_mode);
    586     if (accounting_mode) { /* virtual link accounting */
    587         soc_reg_field_set(unit, DLB_LAG_QUALITY_MEASURE_CONTROLr,
    588                 &measure_control_reg, INST_METRIC_UPDATE_INTERVALf, 1);
    589     } else { /* physical link accounting */
    590         soc_reg_field_set(unit, DLB_LAG_QUALITY_MEASURE_CONTROLr,
    591                 &measure_control_reg, INST_METRIC_UPDATE_INTERVALf, 0);
    592     }
    593     SOC_IF_ERROR_RETURN
    594         (WRITE_DLB_LAG_QUALITY_MEASURE_CONTROLr(unit, measure_control_reg));
    595     return BCM_E_NONE;
    596 }
    597 
    598 /*
    599  * Function:
    600  *      _bcm_tr3_lag_dlb_accounting_get
    601  * Purpose:
    602  *      Get LAG DLB accounting mode.
    603  * Parameters:
    604  *      unit - (IN) SOC unit number.
    605  *      accounting_mode - (OUT) Accounting mode.
    606  * Returns:
    607  *      BCM_E_xxx
    608  */
    609 STATIC int
    610 _bcm_tr3_lag_dlb_accounting_get(int unit, int *accounting_mode)
    611 {
    612     uint32 measure_control_reg;
    613 
    614     SOC_IF_ERROR_RETURN
    615         (READ_DLB_LAG_QUALITY_MEASURE_CONTROLr(unit, &measure_control_reg));
    616     *accounting_mode = soc_reg_field_get(unit, DLB_LAG_QUALITY_MEASURE_CONTROLr,
    617         measure_control_reg, ACCOUNTING_SELf);
    618 
    619     return BCM_E_NONE;
    620 }
    621 
    622 /*
    623  * Function:
    624  *      _bcm_tr3_lag_dlb_sample_rate_pla_thresholds_set
    625  * Purpose:
    626  *      Set LAG DLB sample period and physical link accounting thresholds.
    627  * Parameters:
    628  *      unit - (IN) SOC unit number.
    629  *      sample_rate - (IN) Number of samplings per second.
    630  *      min_th      - (IN) Minimum port load threshold, in mbps.
    631  *      max_th      - (IN) Maximum port load threshold, in mbps.
    632  * Returns:
    633  *      BCM_E_xxx
    634  */
    635 STATIC int
    636 _bcm_tr3_lag_dlb_sample_rate_pla_thresholds_set(int unit, int sample_rate,
    637         int min_th, int max_th)
    638 {
    639     int num_time_units;
    640     uint32 measure_control_reg;
    641     int max_th_bytes;
    642     int th_increment;
    643     dlb_lag_pla_quantize_threshold_entry_t quantize_threshold_entry;
    644     int i;
    645     int th_bytes[7];
    646 
    647     if (sample_rate <= 0 || min_th < 0 || max_th < 0) {
    648         return BCM_E_PARAM;
    649     }
    650 
    651     if (min_th > max_th) {
    652         max_th = min_th;
    653     }
    654 
    655     /* Compute sampling period in units of 1us:
    656      *     number of 1us time units = 10^6 / sample_rate
    657      */ 
    658     num_time_units = 1000000 / sample_rate;
    659     if (num_time_units < 1 || num_time_units > 0x3fff) {
    660         /* Hardware limits the sampling period to 14 bits */ 
    661         return BCM_E_PARAM;
    662     }
    663     SOC_IF_ERROR_RETURN
    664         (READ_DLB_LAG_QUALITY_MEASURE_CONTROLr(unit, &measure_control_reg));
    665     soc_reg_field_set(unit, DLB_LAG_QUALITY_MEASURE_CONTROLr,
    666             &measure_control_reg, HISTORICAL_SAMPLING_PERIODf, num_time_units);
    667     SOC_IF_ERROR_RETURN
    668         (WRITE_DLB_LAG_QUALITY_MEASURE_CONTROLr(unit, measure_control_reg));
    669     LAG_DLB_INFO(unit)->lag_dlb_sample_rate = sample_rate;
    670 
    671     /* Compute threshold in bytes per sampling period:
    672      * bytes per 1us = (million bits per sec) * 10^6 / 8 * 10^(-6),
    673      * bytes per sampling period = (bytes per 1us) * (number of 1us 
    674      *                             time units in sampling period)
    675      *                           = mbps * num_time_units / 8
    676      */
    677     max_th_bytes = max_th * num_time_units / 8;
    678 
    679     if (max_th_bytes > 0x3fffffff) {
    680         /* Hardware limits port load threshold to 30 bits */
    681         return BCM_E_PARAM;
    682     }
    683 
    684     /* Use min threshold as threshold 0, and max threshold as threshold 6.
    685      * Thresholds 1 to 5 will be evenly spread out between min and max
    686      * thresholds.
    687      */
    688     th_increment = (max_th - min_th) / 6;
    689     for (i = 0; i < 7; i++) {
    690         SOC_IF_ERROR_RETURN
    691             (READ_DLB_LAG_PLA_QUANTIZE_THRESHOLDm(unit, MEM_BLOCK_ANY, i,
    692                                               &quantize_threshold_entry));
    693         th_bytes[i] = (min_th + i * th_increment) * num_time_units / 8;
    694         soc_DLB_LAG_PLA_QUANTIZE_THRESHOLDm_field32_set
    695             (unit, &quantize_threshold_entry, THRESHOLD_HIST_LOADf,
    696              th_bytes[i]);
    697         SOC_IF_ERROR_RETURN
    698             (WRITE_DLB_LAG_PLA_QUANTIZE_THRESHOLDm(unit, MEM_BLOCK_ALL, i,
    699                                                &quantize_threshold_entry));
    700     }
    701 
    702     LAG_DLB_INFO(unit)->lag_dlb_tx_load_min_th = min_th;
    703     LAG_DLB_INFO(unit)->lag_dlb_tx_load_max_th = max_th;
    704 
    705     return BCM_E_NONE;
    706 }
    707 
    708 /*
    709  * Function:
    710  *      _bcm_tr3_lag_dlb_sample_rate_vla_thresholds_set
    711  * Purpose:
    712  *      Set LAG DLB sample period and virtual link accounting thresholds.
    713  * Parameters:
    714  *      unit - (IN) SOC unit number.
    715  *      sample_rate - (IN) Number of samplings per second.
    716  *      exp_load_min_th  - (IN) Minimum expected load threshold, in mbps.
    717  *      exp_load_max_th  - (IN) Maximum expected load threshold, in mbps.
    718  *      imbalance_min_th - (IN) Minimum member imbalance threshold,
    719  *                              in percentage.
    720  *      imbalance_max_th - (IN) Maximum member imbalance threshold.
    721  *                              in percentage.
    722  * Returns:
    723  *      BCM_E_xxx
    724  */
    725 STATIC int
    726 _bcm_tr3_lag_dlb_sample_rate_vla_thresholds_set(int unit, int sample_rate,
    727         int exp_load_min_th, int exp_load_max_th,
    728         int imbalance_min_th, int imbalance_max_th)
    729 {
    730     int num_time_units;
    731     uint32 measure_control_reg;
    732     int exp_load_max_th_kbytes;
    733     int num_exp_load_th;
    734     int exp_load_th_increment;
    735     dlb_lag_vla_expected_loading_threshold_entry_t exp_load_threshold_entry;
    736     int exp_load_th_kbytes;
    737     int num_imbalance_th;
    738     int imbalance_th_increment;
    739     int imbalance_max_th_kbytes;
    740     int imbalance_th_kbytes;
    741     dlb_lag_vla_member_imbalance_threshold_entry_t imbalance_threshold_entry;
    742     int i, j;
    743     int imbalance_th_fields[7] = {THRESHOLD_0f, THRESHOLD_1f, THRESHOLD_2f,
    744                                   THRESHOLD_3f, THRESHOLD_4f, THRESHOLD_5f,
    745                                   THRESHOLD_6f};
    746 
    747     if (sample_rate <= 0 || exp_load_min_th < 0 || exp_load_max_th < 0) {
    748         return BCM_E_PARAM;
    749     }
    750 
    751     if (exp_load_min_th > exp_load_max_th) {
    752         exp_load_max_th = exp_load_min_th;
    753     }
    754 
    755     if (imbalance_min_th > imbalance_max_th) {
    756         imbalance_max_th = imbalance_min_th;
    757     }
    758 
    759     /* Compute sampling period in units of 1us:
    760      *     number of 1us time units = 10^6 / sample_rate
    761      */ 
    762     num_time_units = 1000000 / sample_rate;
    763     if (num_time_units < 1 || num_time_units > 0x3fff) {
    764         /* Hardware limits the sampling period to 14 bits */ 
    765         return BCM_E_PARAM;
    766     }
    767     SOC_IF_ERROR_RETURN
    768         (READ_DLB_LAG_QUALITY_MEASURE_CONTROLr(unit, &measure_control_reg));
    769     soc_reg_field_set(unit, DLB_LAG_QUALITY_MEASURE_CONTROLr,
    770             &measure_control_reg, HISTORICAL_SAMPLING_PERIODf, num_time_units);
    771     SOC_IF_ERROR_RETURN
    772         (WRITE_DLB_LAG_QUALITY_MEASURE_CONTROLr(unit, measure_control_reg));
    773     LAG_DLB_INFO(unit)->lag_dlb_sample_rate = sample_rate;
    774 
    775     /* Compute expected loading threshold in kbytes per sampling period:
    776      * bytes per 1us = (million bits per sec) * 10^6 / 8 * 10^(-6)
    777      *               = mbps / 8.
    778      * bytes per sampling period = (bytes per 1us) * (number of 1us 
    779      *                             time units in sampling period)
    780      *                           = mbps * num_time_units / 8.
    781      * kbytes per sampling period =  mbps * num_times_units / 8000.
    782      */
    783     exp_load_max_th_kbytes = exp_load_max_th * num_time_units / 8000;
    784     if (exp_load_max_th_kbytes > 0xfffff) {
    785         /* Hardware limits expected loading threshold in kbytes to 20 bits */
    786         return BCM_E_PARAM;
    787     }
    788 
    789     /* Use expected load min threshold as threshold 0, and max threshold as
    790      * threshold 14. Thresholds 1 to 13 will be evenly spread out between them.
    791      */
    792     num_exp_load_th = soc_mem_index_count(unit,
    793             DLB_LAG_VLA_EXPECTED_LOADING_THRESHOLDm);
    794     exp_load_th_increment = (exp_load_max_th - exp_load_min_th) /
    795                             (num_exp_load_th - 1);
    796     for (i = 0; i < num_exp_load_th; i++) {
    797         SOC_IF_ERROR_RETURN(READ_DLB_LAG_VLA_EXPECTED_LOADING_THRESHOLDm(unit,
    798                     MEM_BLOCK_ANY, i, &exp_load_threshold_entry));
    799         exp_load_th_kbytes = (exp_load_min_th + i * exp_load_th_increment) *
    800                              num_time_units / 8000;
    801         soc_DLB_LAG_VLA_EXPECTED_LOADING_THRESHOLDm_field32_set
    802             (unit, &exp_load_threshold_entry, THRESHOLDf, exp_load_th_kbytes);
    803         SOC_IF_ERROR_RETURN(WRITE_DLB_LAG_VLA_EXPECTED_LOADING_THRESHOLDm(unit,
    804                     MEM_BLOCK_ALL, i, &exp_load_threshold_entry));
    805     }
    806 
    807     LAG_DLB_INFO(unit)->lag_dlb_exp_load_min_th = exp_load_min_th;
    808     LAG_DLB_INFO(unit)->lag_dlb_exp_load_max_th = exp_load_max_th;
    809 
    810     /* Use member imbalance min threshold as threshold 0, and max threshold as
    811      * threshold 6. Thresholds 1 to 5 will be evenly spread out between them.
    812      */
    813     num_imbalance_th = 7;
    814     imbalance_th_increment = (imbalance_max_th - imbalance_min_th) /
    815         (num_imbalance_th - 1);
    816     for (i = 0;
    817          i < soc_mem_index_count(unit,
    818              DLB_LAG_VLA_MEMBER_IMBALANCE_THRESHOLDm);
    819          i++) {
    820         /* There are 16 sets of member imbalance thresholds.
    821          * For sets 0 to 14, use expected loading thresholds 0 to 14 from
    822          * DLB_LAG_VLA_EXPECTED_LOADING_THRESHOLD table as the
    823          * expected load. For set 15, extrapolate the expected load.
    824          */
    825         if (i < num_exp_load_th) {
    826             SOC_IF_ERROR_RETURN
    827                 (READ_DLB_LAG_VLA_EXPECTED_LOADING_THRESHOLDm(unit,
    828                         MEM_BLOCK_ANY, i, &exp_load_threshold_entry));
    829             exp_load_th_kbytes =
    830                 soc_DLB_LAG_VLA_EXPECTED_LOADING_THRESHOLDm_field32_get(unit,
    831                         &exp_load_threshold_entry, THRESHOLDf);
    832         } else {
    833             exp_load_th_kbytes =
    834                 (exp_load_min_th + num_exp_load_th * exp_load_th_increment) *
    835                 num_time_units / 8000;
    836         }
    837 
    838         /* Compute member imbalance thresholds */
    839         imbalance_max_th_kbytes = exp_load_th_kbytes * imbalance_max_th / 100;
    840         if (imbalance_max_th_kbytes > 0xfffff) {
    841             /* Hardware limits imbalance threshold in kbytes to 1 sign bit
    842              * plus 20 bits.
    843              */
    844             return BCM_E_PARAM;
    845         }
    846         SOC_IF_ERROR_RETURN(READ_DLB_LAG_VLA_MEMBER_IMBALANCE_THRESHOLDm(unit,
    847                     MEM_BLOCK_ANY, i, &imbalance_threshold_entry));
    848         for (j = 0; j < num_imbalance_th; j++) {
    849             imbalance_th_kbytes = exp_load_th_kbytes *
    850                 (imbalance_min_th + j * imbalance_th_increment) / 100;
    851             if (imbalance_th_kbytes < 0) {
    852                 /* Convert to two's complement representation */
    853                 imbalance_th_kbytes = -1 * imbalance_th_kbytes;
    854                 imbalance_th_kbytes = (~imbalance_th_kbytes) + 1;
    855             } 
    856             soc_DLB_LAG_VLA_MEMBER_IMBALANCE_THRESHOLDm_field32_set(unit,
    857                     &imbalance_threshold_entry, imbalance_th_fields[j],
    858                     imbalance_th_kbytes & 0x1fffff);
    859         }
    860         SOC_IF_ERROR_RETURN(WRITE_DLB_LAG_VLA_MEMBER_IMBALANCE_THRESHOLDm(unit,
    861                     MEM_BLOCK_ALL, i, &imbalance_threshold_entry));
    862     }
    863 
    864     LAG_DLB_INFO(unit)->lag_dlb_imbalance_min_th = imbalance_min_th;
    865     LAG_DLB_INFO(unit)->lag_dlb_imbalance_max_th = imbalance_max_th;
    866 
    867     return BCM_E_NONE;
    868 }
    869 
    870 /*
    871  * Function:
    872  *      _bcm_tr3_lag_dlb_sample_rate_set
    873  * Purpose:
    874  *      Set LAG dynamic load balancing sample rate.
    875  * Parameters:
    876  *      unit - (IN) SOC unit number.
    877  *      sample_rate - (IN) Number of samplings per second.
    878  * Returns:
    879  *      BCM_E_xxx
    880  */
    881 STATIC int
    882 _bcm_tr3_lag_dlb_sample_rate_set(int unit, int sample_rate)
    883 {
    884     BCM_IF_ERROR_RETURN(_bcm_tr3_lag_dlb_sample_rate_pla_thresholds_set(unit,
    885                 sample_rate, LAG_DLB_INFO(unit)->lag_dlb_tx_load_min_th,
    886                 LAG_DLB_INFO(unit)->lag_dlb_tx_load_max_th));
    887 
    888     BCM_IF_ERROR_RETURN(_bcm_tr3_lag_dlb_sample_rate_vla_thresholds_set(unit,
    889                 sample_rate, LAG_DLB_INFO(unit)->lag_dlb_exp_load_min_th,
    890                 LAG_DLB_INFO(unit)->lag_dlb_exp_load_max_th,
    891                 LAG_DLB_INFO(unit)->lag_dlb_imbalance_min_th,
    892                 LAG_DLB_INFO(unit)->lag_dlb_imbalance_max_th));
    893     return BCM_E_NONE;
    894 }
    895 
    896 /*
    897  * Function:
    898  *      _bcm_tr3_lag_dlb_tx_load_min_th_set
    899  * Purpose:
    900  *      Set LAG DLB port load minimum threshold.
    901  * Parameters:
    902  *      unit - (IN) SOC unit number.
    903  *      min_th - (IN) Minimum port loading threshold.
    904  * Returns:
    905  *      BCM_E_xxx
    906  */
    907 STATIC int
    908 _bcm_tr3_lag_dlb_tx_load_min_th_set(int unit, int min_th)
    909 {
    910     BCM_IF_ERROR_RETURN(_bcm_tr3_lag_dlb_sample_rate_pla_thresholds_set(unit,
    911                 LAG_DLB_INFO(unit)->lag_dlb_sample_rate, min_th,
    912                 LAG_DLB_INFO(unit)->lag_dlb_tx_load_max_th));
    913     return BCM_E_NONE;
    914 }
    915 
    916 /*
    917  * Function:
    918  *      _bcm_trident_lag_dlb_tx_load_max_th_set
    919  * Purpose:
    920  *      Set LAG DLB port load maximum threshold.
    921  * Parameters:
    922  *      unit - (IN) SOC unit number.
    923  *      max_th - (IN) Maximum port loading threshold.
    924  * Returns:
    925  *      BCM_E_xxx
    926  */
    927 STATIC int
    928 _bcm_tr3_lag_dlb_tx_load_max_th_set(int unit, int max_th)
    929 {
    930     BCM_IF_ERROR_RETURN(_bcm_tr3_lag_dlb_sample_rate_pla_thresholds_set(unit,
    931                 LAG_DLB_INFO(unit)->lag_dlb_sample_rate,
    932                 LAG_DLB_INFO(unit)->lag_dlb_tx_load_min_th,
    933                 max_th));
    934     return BCM_E_NONE;
    935 }
    936 
    937 /*
    938  * Function:
    939  *      _bcm_tr3_lag_dlb_exp_load_min_th_set
    940  * Purpose:
    941  *      Set LAG DLB expected load minimum threshold.
    942  * Parameters:
    943  *      unit - (IN) SOC unit number.
    944  *      min_th - (IN) Minimum expected load threshold.
    945  * Returns:
    946  *      BCM_E_xxx
    947  */
    948 STATIC int
    949 _bcm_tr3_lag_dlb_exp_load_min_th_set(int unit, int min_th)
    950 {
    951     BCM_IF_ERROR_RETURN(_bcm_tr3_lag_dlb_sample_rate_vla_thresholds_set(unit,
    952                 LAG_DLB_INFO(unit)->lag_dlb_sample_rate,
    953                 min_th,
    954                 LAG_DLB_INFO(unit)->lag_dlb_exp_load_max_th,
    955                 LAG_DLB_INFO(unit)->lag_dlb_imbalance_min_th,
    956                 LAG_DLB_INFO(unit)->lag_dlb_imbalance_max_th));
    957     return BCM_E_NONE;
    958 }
    959 
    960 /*
    961  * Function:
    962  *      _bcm_tr3_lag_dlb_exp_load_max_th_set
    963  * Purpose:
    964  *      Set LAG DLB expected load maximum threshold.
    965  * Parameters:
    966  *      unit - (IN) SOC unit number.
    967  *      max_th - (IN) Maximum expected load threshold.
    968  * Returns:
    969  *      BCM_E_xxx
    970  */
    971 STATIC int
    972 _bcm_tr3_lag_dlb_exp_load_max_th_set(int unit, int max_th)
    973 {
    974     BCM_IF_ERROR_RETURN(_bcm_tr3_lag_dlb_sample_rate_vla_thresholds_set(unit,
    975                 LAG_DLB_INFO(unit)->lag_dlb_sample_rate,
    976                 LAG_DLB_INFO(unit)->lag_dlb_exp_load_min_th,
    977                 max_th,
    978                 LAG_DLB_INFO(unit)->lag_dlb_imbalance_min_th,
    979                 LAG_DLB_INFO(unit)->lag_dlb_imbalance_max_th));
    980     return BCM_E_NONE;
    981 }
    982 
    983 /*
    984  * Function:
    985  *      _bcm_tr3_lag_dlb_imbalance_min_th_set
    986  * Purpose:
    987  *      Set LAG DLB member imbalance minimum threshold.
    988  * Parameters:
    989  *      unit - (IN) SOC unit number.
    990  *      min_th - (IN) Minimum member imbalance threshold.
    991  * Returns:
    992  *      BCM_E_xxx
    993  */
    994 STATIC int
    995 _bcm_tr3_lag_dlb_imbalance_min_th_set(int unit, int min_th)
    996 {
    997     BCM_IF_ERROR_RETURN(_bcm_tr3_lag_dlb_sample_rate_vla_thresholds_set(unit,
    998                 LAG_DLB_INFO(unit)->lag_dlb_sample_rate,
    999                 LAG_DLB_INFO(unit)->lag_dlb_exp_load_min_th,
   1000                 LAG_DLB_INFO(unit)->lag_dlb_exp_load_max_th,
   1001                 min_th,
   1002                 LAG_DLB_INFO(unit)->lag_dlb_imbalance_max_th));
   1003     return BCM_E_NONE;
   1004 }
   1005 
   1006 /*
   1007  * Function:
   1008  *      _bcm_tr3_lag_dlb_imbalance_max_th_set
   1009  * Purpose:
   1010  *      Set LAG DLB member imbalance maximum threshold.
   1011  * Parameters:
   1012  *      unit - (IN) SOC unit number.
   1013  *      max_th - (IN) Maximum member imbalance threshold.
   1014  * Returns:
   1015  *      BCM_E_xxx
   1016  */
   1017 STATIC int
   1018 _bcm_tr3_lag_dlb_imbalance_max_th_set(int unit, int max_th)
   1019 {
   1020     BCM_IF_ERROR_RETURN(_bcm_tr3_lag_dlb_sample_rate_vla_thresholds_set(unit,
   1021                 LAG_DLB_INFO(unit)->lag_dlb_sample_rate,
   1022                 LAG_DLB_INFO(unit)->lag_dlb_exp_load_min_th,
   1023                 LAG_DLB_INFO(unit)->lag_dlb_exp_load_max_th,
   1024                 LAG_DLB_INFO(unit)->lag_dlb_imbalance_min_th,
   1025                 max_th));
   1026     return BCM_E_NONE;
   1027 }
   1028 
   1029 /*
   1030  * Function:
   1031  *      _bcm_tr3_lag_dlb_qsize_thresholds_set
   1032  * Purpose:
   1033  *      Set LAG DLB queue size thresholds.
   1034  * Parameters:
   1035  *      unit - (IN) SOC unit number.
   1036  *      min_th - (IN) Minimum queue size threshold, in bytes.
   1037  *      max_th - (IN) Maximum queue size threshold, in bytes.
   1038  * Returns:
   1039  *      BCM_E_xxx
   1040  */
   1041 STATIC int
   1042 _bcm_tr3_lag_dlb_qsize_thresholds_set(int unit, int min_th, int max_th)
   1043 {
   1044     int max_th_cells;
   1045     int th_increment;
   1046     dlb_hgt_quantize_threshold_entry_t quantize_threshold_entry;
   1047     int i;
   1048     int th_cells[7];
   1049 
   1050     if (min_th < 0 || max_th < 0) {
   1051         return BCM_E_PARAM;
   1052     }
   1053 
   1054     if (min_th > max_th) {
   1055         max_th = min_th;
   1056     }
   1057 
   1058     /* Convert threshold to number of cells */
   1059     max_th_cells = max_th / 208;
   1060     if (max_th_cells > 0xffff) {
   1061         /* Hardware limits queue size threshold to 16 bits */
   1062         return BCM_E_PARAM;
   1063     }
   1064 
   1065     /* Use min threshold as threshold 0, and max threshold as threshold 6.
   1066      * Thresholds 1 to 5 will be evenly spread out between min and max
   1067      * thresholds.
   1068      */
   1069     th_increment = (max_th - min_th) / 6;
   1070     for (i = 0; i < 7; i++) {
   1071         SOC_IF_ERROR_RETURN
   1072             (READ_DLB_LAG_PLA_QUANTIZE_THRESHOLDm(unit, MEM_BLOCK_ANY, i,
   1073                                               &quantize_threshold_entry));
   1074         th_cells[i] = (min_th + i * th_increment) / 208;
   1075         soc_DLB_LAG_PLA_QUANTIZE_THRESHOLDm_field32_set
   1076             (unit, &quantize_threshold_entry, THRESHOLD_HIST_QSIZEf,
   1077              th_cells[i]);
   1078         SOC_IF_ERROR_RETURN
   1079             (WRITE_DLB_LAG_PLA_QUANTIZE_THRESHOLDm(unit, MEM_BLOCK_ALL, i,
   1080                                                &quantize_threshold_entry));
   1081     }
   1082 
   1083     LAG_DLB_INFO(unit)->lag_dlb_qsize_min_th = min_th;
   1084     LAG_DLB_INFO(unit)->lag_dlb_qsize_max_th = max_th;
   1085 
   1086     return BCM_E_NONE;
   1087 }
   1088 
   1089 /*
   1090  * Function:
   1091  *      _bcm_tr3_lag_dlb_qsize_min_th_set
   1092  * Purpose:
   1093  *      Set LAG DLB queue size minimum threshold.
   1094  * Parameters:
   1095  *      unit - (IN) SOC unit number.
   1096  *      min_th - (IN) Minimum queue size threshold, in bytes.
   1097  * Returns:
   1098  *      BCM_E_xxx
   1099  */
   1100 STATIC int
   1101 _bcm_tr3_lag_dlb_qsize_min_th_set(int unit, int min_th)
   1102 {
   1103     BCM_IF_ERROR_RETURN(_bcm_tr3_lag_dlb_qsize_thresholds_set(unit,
   1104                 min_th, LAG_DLB_INFO(unit)->lag_dlb_qsize_max_th));
   1105 
   1106     return BCM_E_NONE;
   1107 }
   1108 
   1109 /*
   1110  * Function:
   1111  *      _bcm_tr3_lag_dlb_qsize_max_th_set
   1112  * Purpose:
   1113  *      Set LAG DLB queue size maximum threshold.
   1114  * Parameters:
   1115  *      unit - (IN) SOC unit number.
   1116  *      max_th - (IN) Maximum queue size threshold, in bytes.
   1117  * Returns:
   1118  *      BCM_E_xxx
   1119  */
   1120 STATIC int
   1121 _bcm_tr3_lag_dlb_qsize_max_th_set(int unit, int max_th)
   1122 {
   1123     BCM_IF_ERROR_RETURN(_bcm_tr3_lag_dlb_qsize_thresholds_set(unit,
   1124                 LAG_DLB_INFO(unit)->lag_dlb_qsize_min_th, max_th));
   1125 
   1126     return BCM_E_NONE;
   1127 }
   1128 
   1129 /*
   1130  * Function:
   1131  *      _bcm_tr3_lag_dlb_tx_load_weight_set
   1132  * Purpose:
   1133  *      Set LAG DLB port load weight.
   1134  * Parameters:
   1135  *      unit - (IN) SOC unit number.
   1136  *      weight - (IN) Port load weight.
   1137  * Returns:
   1138  *      BCM_E_xxx
   1139  */
   1140 STATIC int
   1141 _bcm_tr3_lag_dlb_tx_load_weight_set(int unit, int weight)
   1142 {
   1143     uint32 measure_control_reg;
   1144 
   1145     if (weight < 0 || 
   1146         weight > 0xf) {
   1147         /* Hardware limits port load weight to 4 bits */
   1148         return BCM_E_PARAM;
   1149     }
   1150 
   1151     SOC_IF_ERROR_RETURN
   1152         (READ_DLB_LAG_PLA_QUALITY_MEASURE_CONTROLr(unit, &measure_control_reg));
   1153     soc_reg_field_set(unit, DLB_LAG_PLA_QUALITY_MEASURE_CONTROLr,
   1154         &measure_control_reg, PLA_WEIGHT_LOADINGf, weight);
   1155     SOC_IF_ERROR_RETURN
   1156         (WRITE_DLB_LAG_PLA_QUALITY_MEASURE_CONTROLr(unit, measure_control_reg));
   1157     return BCM_E_NONE;
   1158 }
   1159 
   1160 /*
   1161  * Function:
   1162  *      _bcm_tr3_lag_dlb_tx_load_weight_get
   1163  * Purpose:
   1164  *      Get LAG DLB port load weight.
   1165  * Parameters:
   1166  *      unit - (IN) SOC unit number.
   1167  *      weight - (OUT) Port load weight.
   1168  * Returns:
   1169  *      BCM_E_xxx
   1170  */
   1171 STATIC int
   1172 _bcm_tr3_lag_dlb_tx_load_weight_get(int unit, int *weight)
   1173 {
   1174     uint32 measure_control_reg;
   1175 
   1176     SOC_IF_ERROR_RETURN
   1177         (READ_DLB_LAG_PLA_QUALITY_MEASURE_CONTROLr(unit, &measure_control_reg));
   1178     *weight = soc_reg_field_get(unit, DLB_LAG_PLA_QUALITY_MEASURE_CONTROLr,
   1179         measure_control_reg, PLA_WEIGHT_LOADINGf);
   1180 
   1181     return BCM_E_NONE;
   1182 }
   1183 
   1184 /*
   1185  * Function:
   1186  *      _bcm_tr3_lag_dlb_qsize_weight_set
   1187  * Purpose:
   1188  *      Set LAG DLB qsize weight.
   1189  * Parameters:
   1190  *      unit - (IN) SOC unit number.
   1191  *      weight - (IN) Qsize weight.
   1192  * Returns:
   1193  *      BCM_E_xxx
   1194  */
   1195 STATIC int
   1196 _bcm_tr3_lag_dlb_qsize_weight_set(int unit, int weight)
   1197 {
   1198     uint32 measure_control_reg;
   1199 
   1200     if (weight < 0 || 
   1201         weight > 0xf) {
   1202         /* Hardware limits qsize weight to 4 bits */
   1203         return BCM_E_PARAM;
   1204     }
   1205 
   1206     SOC_IF_ERROR_RETURN
   1207         (READ_DLB_LAG_PLA_QUALITY_MEASURE_CONTROLr(unit, &measure_control_reg));
   1208     soc_reg_field_set(unit, DLB_LAG_PLA_QUALITY_MEASURE_CONTROLr,
   1209         &measure_control_reg, PLA_WEIGHT_QSIZEf, weight);
   1210     SOC_IF_ERROR_RETURN
   1211         (WRITE_DLB_LAG_PLA_QUALITY_MEASURE_CONTROLr(unit, measure_control_reg));
   1212     return BCM_E_NONE;
   1213 }
   1214 
   1215 /*
   1216  * Function:
   1217  *      _bcm_tr3_lag_dlb_qsize_weight_get
   1218  * Purpose:
   1219  *      Get LAG DLB qsize weight.
   1220  * Parameters:
   1221  *      unit - (IN) SOC unit number.
   1222  *      weight - (OUT) Qsize weight.
   1223  * Returns:
   1224  *      BCM_E_xxx
   1225  */
   1226 STATIC int
   1227 _bcm_tr3_lag_dlb_qsize_weight_get(int unit, int *weight)
   1228 {
   1229     uint32 measure_control_reg;
   1230 
   1231     SOC_IF_ERROR_RETURN
   1232         (READ_DLB_LAG_PLA_QUALITY_MEASURE_CONTROLr(unit, &measure_control_reg));
   1233     *weight = soc_reg_field_get(unit, DLB_LAG_PLA_QUALITY_MEASURE_CONTROLr,
   1234         measure_control_reg, PLA_WEIGHT_QSIZEf);
   1235 
   1236     return BCM_E_NONE;
   1237 }
   1238 
   1239 /*
   1240  * Function:
   1241  *      _bcm_tr3_lag_dlb_tx_load_cap_set
   1242  * Purpose:
   1243  *      Set LAG DLB port load cap control.
   1244  * Parameters:
   1245  *      unit - (IN) SOC unit number.
   1246  *      cap - (IN) Port load cap control.
   1247  * Returns:
   1248  *      BCM_E_xxx
   1249  */
   1250 STATIC int
   1251 _bcm_tr3_lag_dlb_tx_load_cap_set(int unit, int cap)
   1252 {
   1253     uint32 measure_control_reg;
   1254 
   1255     if (cap < 0 || 
   1256         cap > 1) {
   1257         /* Hardware limits port load cap control to 1 bit */
   1258         return BCM_E_PARAM;
   1259     }
   1260 
   1261     SOC_IF_ERROR_RETURN
   1262         (READ_DLB_LAG_PLA_QUALITY_MEASURE_CONTROLr(unit, &measure_control_reg));
   1263     soc_reg_field_set(unit, DLB_LAG_PLA_QUALITY_MEASURE_CONTROLr,
   1264         &measure_control_reg, PLA_CAP_LOADING_AVGf, cap);
   1265     SOC_IF_ERROR_RETURN
   1266         (WRITE_DLB_LAG_PLA_QUALITY_MEASURE_CONTROLr(unit, measure_control_reg));
   1267     return BCM_E_NONE;
   1268 }
   1269 
   1270 /*
   1271  * Function:
   1272  *      _bcm_tr3_lag_dlb_tx_load_cap_get
   1273  * Purpose:
   1274  *      Get LAG DLB port load cap control.
   1275  * Parameters:
   1276  *      unit - (IN) SOC unit number.
   1277  *      cap - (OUT) Cap control.
   1278  * Returns:
   1279  *      BCM_E_xxx
   1280  */
   1281 STATIC int
   1282 _bcm_tr3_lag_dlb_tx_load_cap_get(int unit, int *cap)
   1283 {
   1284     uint32 measure_control_reg;
   1285 
   1286     SOC_IF_ERROR_RETURN
   1287         (READ_DLB_LAG_PLA_QUALITY_MEASURE_CONTROLr(unit, &measure_control_reg));
   1288     *cap= soc_reg_field_get(unit, DLB_LAG_PLA_QUALITY_MEASURE_CONTROLr,
   1289         measure_control_reg, PLA_CAP_LOADING_AVGf);
   1290 
   1291     return BCM_E_NONE;
   1292 }
   1293 /*
   1294  * Function:
   1295  *      _bcm_tr3_lag_dlb_qsize_cap_set
   1296  * Purpose:
   1297  *      Set LAG DLB queue size cap control.
   1298  * Parameters:
   1299  *      unit - (IN) SOC unit number.
   1300  *      cap - (IN) Queue size cap control.
   1301  * Returns:
   1302  *      BCM_E_xxx
   1303  */
   1304 STATIC int
   1305 _bcm_tr3_lag_dlb_qsize_cap_set(int unit, int cap)
   1306 {
   1307     uint32 measure_control_reg;
   1308 
   1309     if (cap < 0 || 
   1310         cap > 1) {
   1311         /* Hardware limits port load cap control to 1 bit */
   1312         return BCM_E_PARAM;
   1313     }
   1314 
   1315     SOC_IF_ERROR_RETURN
   1316         (READ_DLB_LAG_PLA_QUALITY_MEASURE_CONTROLr(unit, &measure_control_reg));
   1317     soc_reg_field_set(unit, DLB_LAG_PLA_QUALITY_MEASURE_CONTROLr,
   1318         &measure_control_reg, PLA_CAP_QSIZE_AVGf, cap);
   1319     SOC_IF_ERROR_RETURN
   1320         (WRITE_DLB_LAG_PLA_QUALITY_MEASURE_CONTROLr(unit, measure_control_reg));
   1321     return BCM_E_NONE;
   1322 }
   1323 
   1324 /*
   1325  * Function:
   1326  *      _bcm_tr3_lag_dlb_qsize_cap_get
   1327  * Purpose:
   1328  *      Get LAG DLB queue size cap control.
   1329  * Parameters:
   1330  *      unit - (IN) SOC unit number.
   1331  *      cap - (OUT) Cap control.
   1332  * Returns:
   1333  *      BCM_E_xxx
   1334  */
   1335 STATIC int
   1336 _bcm_tr3_lag_dlb_qsize_cap_get(int unit, int *cap)
   1337 {
   1338     uint32 measure_control_reg;
   1339 
   1340     SOC_IF_ERROR_RETURN
   1341         (READ_DLB_LAG_PLA_QUALITY_MEASURE_CONTROLr(unit, &measure_control_reg));
   1342     *cap= soc_reg_field_get(unit, DLB_LAG_PLA_QUALITY_MEASURE_CONTROLr,
   1343         measure_control_reg, PLA_CAP_QSIZE_AVGf);
   1344 
   1345     return BCM_E_NONE;
   1346 }
   1347 
   1348 /*
   1349  * Function:
   1350  *      bcm_tr3_lag_dlb_config_set
   1351  * Purpose:
   1352  *      Set per-chip LAG dynamic load balancing configuration parameters.
   1353  * Parameters:
   1354  *      unit - (IN) SOC unit number.
   1355  *      type - (IN) Configuration parameter type.
   1356  *      arg  - (IN) Configuration paramter value.
   1357  * Returns:
   1358  *      BCM_E_xxx
   1359  */
   1360 int
   1361 bcm_tr3_lag_dlb_config_set(int unit, bcm_switch_control_t type, int arg)
   1362 {
   1363     switch (type) {
   1364         case bcmSwitchTrunkDynamicSampleRate:
   1365             return _bcm_tr3_lag_dlb_sample_rate_set(unit, arg);
   1366 
   1367         case bcmSwitchTrunkDynamicAccountingSelect:
   1368             return _bcm_tr3_lag_dlb_accounting_set(unit, arg);
   1369 
   1370         case bcmSwitchTrunkDynamicEgressBytesExponent:
   1371             return _bcm_tr3_lag_dlb_tx_load_weight_set(unit, arg);
   1372 
   1373         case bcmSwitchTrunkDynamicQueuedBytesExponent:
   1374             return _bcm_tr3_lag_dlb_qsize_weight_set(unit, arg);
   1375 
   1376         case bcmSwitchTrunkDynamicEgressBytesDecreaseReset:
   1377             return _bcm_tr3_lag_dlb_tx_load_cap_set(unit, arg);
   1378 
   1379         case bcmSwitchTrunkDynamicQueuedBytesDecreaseReset:
   1380             return _bcm_tr3_lag_dlb_qsize_cap_set(unit, arg);
   1381 
   1382         case bcmSwitchTrunkDynamicEgressBytesMinThreshold:
   1383             return _bcm_tr3_lag_dlb_tx_load_min_th_set(unit, arg);
   1384 
   1385         case bcmSwitchTrunkDynamicEgressBytesMaxThreshold:
   1386             return _bcm_tr3_lag_dlb_tx_load_max_th_set(unit, arg);
   1387 
   1388         case bcmSwitchTrunkDynamicQueuedBytesMinThreshold:
   1389             return _bcm_tr3_lag_dlb_qsize_min_th_set(unit, arg);
   1390 
   1391         case bcmSwitchTrunkDynamicQueuedBytesMaxThreshold:
   1392             return _bcm_tr3_lag_dlb_qsize_max_th_set(unit, arg);
   1393 
   1394         case bcmSwitchTrunkDynamicExpectedLoadMinThreshold:
   1395             return _bcm_tr3_lag_dlb_exp_load_min_th_set(unit, arg);
   1396 
   1397         case bcmSwitchTrunkDynamicExpectedLoadMaxThreshold:
   1398             return _bcm_tr3_lag_dlb_exp_load_max_th_set(unit, arg);
   1399 
   1400         case bcmSwitchTrunkDynamicImbalanceMinThreshold:
   1401             return _bcm_tr3_lag_dlb_imbalance_min_th_set(unit, arg);
   1402 
   1403         case bcmSwitchTrunkDynamicImbalanceMaxThreshold:
   1404             return _bcm_tr3_lag_dlb_imbalance_max_th_set(unit, arg);
   1405 
   1406         default:
   1407             return BCM_E_PARAM;
   1408     }
   1409 }
   1410 
   1411 /*
   1412  * Function:
   1413  *      bcm_tr3_lag_dlb_config_get
   1414  * Purpose:
   1415  *      Get per-chip LAG dynamic load balancing configuration parameters.
   1416  * Parameters:
   1417  *      unit - (IN) SOC unit number.
   1418  *      type - (IN) Configuration parameter type.
   1419  *      arg  - (OUT) Configuration paramter value.
   1420  * Returns:
   1421  *      BCM_E_xxx
   1422  */
   1423 int
   1424 bcm_tr3_lag_dlb_config_get(int unit, bcm_switch_control_t type, int *arg)
   1425 {
   1426     switch (type) {
   1427         case bcmSwitchTrunkDynamicSampleRate:
   1428             *arg = LAG_DLB_INFO(unit)->lag_dlb_sample_rate;
   1429             break;
   1430 
   1431         case bcmSwitchTrunkDynamicAccountingSelect:
   1432             return _bcm_tr3_lag_dlb_accounting_get(unit, arg);
   1433             break;
   1434 
   1435         case bcmSwitchTrunkDynamicEgressBytesExponent:
   1436             return _bcm_tr3_lag_dlb_tx_load_weight_get(unit, arg);
   1437 
   1438         case bcmSwitchTrunkDynamicQueuedBytesExponent:
   1439             return _bcm_tr3_lag_dlb_qsize_weight_get(unit, arg);
   1440 
   1441         case bcmSwitchTrunkDynamicEgressBytesDecreaseReset:
   1442             return _bcm_tr3_lag_dlb_tx_load_cap_get(unit, arg);
   1443 
   1444         case bcmSwitchTrunkDynamicQueuedBytesDecreaseReset:
   1445             return _bcm_tr3_lag_dlb_qsize_cap_get(unit, arg);
   1446 
   1447         case bcmSwitchTrunkDynamicEgressBytesMinThreshold:
   1448             *arg = LAG_DLB_INFO(unit)->lag_dlb_tx_load_min_th;
   1449             break;
   1450 
   1451         case bcmSwitchTrunkDynamicEgressBytesMaxThreshold:
   1452             *arg = LAG_DLB_INFO(unit)->lag_dlb_tx_load_max_th;
   1453             break;
   1454 
   1455         case bcmSwitchTrunkDynamicQueuedBytesMinThreshold:
   1456             *arg = LAG_DLB_INFO(unit)->lag_dlb_qsize_min_th;
   1457             break;
   1458 
   1459         case bcmSwitchTrunkDynamicQueuedBytesMaxThreshold:
   1460             *arg = LAG_DLB_INFO(unit)->lag_dlb_qsize_max_th;
   1461             break;
   1462 
   1463         case bcmSwitchTrunkDynamicExpectedLoadMinThreshold:
   1464             *arg = LAG_DLB_INFO(unit)->lag_dlb_exp_load_min_th;
   1465             break;
   1466 
   1467         case bcmSwitchTrunkDynamicExpectedLoadMaxThreshold:
   1468             *arg = LAG_DLB_INFO(unit)->lag_dlb_exp_load_max_th;
   1469             break;
   1470 
   1471         case bcmSwitchTrunkDynamicImbalanceMinThreshold:
   1472             *arg = LAG_DLB_INFO(unit)->lag_dlb_imbalance_min_th;
   1473             break;
   1474 
   1475         case bcmSwitchTrunkDynamicImbalanceMaxThreshold:
   1476             *arg = LAG_DLB_INFO(unit)->lag_dlb_imbalance_max_th;
   1477             break;
   1478 
   1479         default:
   1480             return BCM_E_PARAM;
   1481     }
   1482 
   1483     return BCM_E_NONE;
   1484 }
   1485 
   1486 /*
   1487  * Function:
   1488  *      _bcm_tr3_lag_dlb_dynamic_size_encode
   1489  * Purpose:
   1490  *      Encode LAG dynamic load balancing flow set size.
   1491  * Parameters:
   1492  *      dynamic_size - (IN) Number of flow sets.
   1493  *      encoded_value - (OUT) Encoded value.
   1494  * Returns:
   1495  *      BCM_E_xxx
   1496  */
   1497 int
   1498 bcm_tr3_lag_dlb_dynamic_size_encode(int dynamic_size,
   1499         int *encoded_value)
   1500 {   
   1501     switch (dynamic_size) {
   1502         case 512:
   1503             *encoded_value = 1;
   1504             break;
   1505         case 1024:
   1506             *encoded_value = 2;
   1507             break;
   1508         case 2048:
   1509             *encoded_value = 3;
   1510             break;
   1511         case 4096:
   1512             *encoded_value = 4;
   1513             break;
   1514         case 8192:
   1515             *encoded_value = 5;
   1516             break;
   1517         case 16384:
   1518             *encoded_value = 6;
   1519             break;
   1520         case 32768:
   1521             *encoded_value = 7;
   1522             break;
   1523         default:
   1524             return BCM_E_PARAM;
   1525     }
   1526 
   1527     return BCM_E_NONE;
   1528 }
   1529 
   1530 /*
   1531  * Function:
   1532  *      _bcm_tr3_lag_dlb_dynamic_size_decode
   1533  * Purpose:
   1534  *      Decode LAG trunk dynamic load balancing flow set size.
   1535  * Parameters:
   1536  *      encoded_value - (IN) Encoded value.
   1537  *      dynamic_size - (OUT) Number of flow sets.
   1538  * Returns:
   1539  *      BCM_E_xxx
   1540  */
   1541 STATIC int
   1542 _bcm_tr3_lag_dlb_dynamic_size_decode(int encoded_value,
   1543         int *dynamic_size)
   1544 {   
   1545     switch (encoded_value) {
   1546         case 1:
   1547             *dynamic_size = 512;
   1548             break;
   1549         case 2:
   1550             *dynamic_size = 1024;
   1551             break;
   1552         case 3:
   1553             *dynamic_size = 2048;
   1554             break;
   1555         case 4:
   1556             *dynamic_size = 4096;
   1557             break;
   1558         case 5:
   1559             *dynamic_size = 8192;
   1560             break;
   1561         case 6:
   1562             *dynamic_size = 16384;
   1563             break;
   1564         case 7:
   1565             *dynamic_size = 32768;
   1566             break;
   1567         default:
   1568             return BCM_E_INTERNAL;
   1569     }
   1570 
   1571     return BCM_E_NONE;
   1572 }
   1573 
   1574 /*
   1575  * Function:
   1576  *      _bcm_tr3_lag_dlb_id_alloc
   1577  * Purpose:
   1578  *      Get a free LAG DLB ID and mark it used.
   1579  * Parameters:
   1580  *      unit - (IN) SOC unit number.
   1581  *      dlb_id - (OUT) Allocated DLB ID.
   1582  * Returns:
   1583  *      BCM_E_xxx
   1584  */
   1585 STATIC int
   1586 _bcm_tr3_lag_dlb_id_alloc(int unit, int *dlb_id)
   1587 {
   1588     int i;
   1589 
   1590     for (i = 0; i < soc_mem_index_count(unit, DLB_LAG_GROUP_CONTROLm); i++) {
   1591         if (!_BCM_LAG_DLB_ID_USED_GET(unit, i)) {
   1592             _BCM_LAG_DLB_ID_USED_SET(unit, i);
   1593             *dlb_id = i;
   1594             return BCM_E_NONE;
   1595         }
   1596     }
   1597 
   1598     return BCM_E_RESOURCE;
   1599 }
   1600 
   1601 /*
   1602  * Function:
   1603  *      _bcm_tr3_lag_dlb_id_free
   1604  * Purpose:
   1605  *      Free a LAG DLB ID.
   1606  * Parameters:
   1607  *      unit - (IN) SOC unit number.
   1608  *      dlb_id - (IN) DLB ID to be freed.
   1609  * Returns:
   1610  *      BCM_E_xxx
   1611  */
   1612 STATIC int
   1613 _bcm_tr3_lag_dlb_id_free(int unit, int dlb_id)
   1614 {
   1615     if (dlb_id < 0 ||
   1616             dlb_id > soc_mem_index_max(unit, DLB_LAG_GROUP_CONTROLm)) {
   1617         return BCM_E_PARAM;
   1618     }
   1619 
   1620     _BCM_LAG_DLB_ID_USED_CLR(unit, dlb_id);
   1621 
   1622     return BCM_E_NONE;
   1623 }
   1624 
   1625 /*
   1626  * Function:
   1627  *      _bcm_tr3_lag_dlb_member_id_alloc
   1628  * Purpose:
   1629  *      Get a free LAG DLB Member ID and mark it used.
   1630  * Parameters:
   1631  *      unit - (IN) SOC unit number.
   1632  *      member_id - (OUT) Allocated Member ID.
   1633  * Returns:
   1634  *      BCM_E_xxx
   1635  */
   1636 STATIC int
   1637 _bcm_tr3_lag_dlb_member_id_alloc(int unit, int *member_id)
   1638 {
   1639     int vla;
   1640     int i;
   1641     int max_members;
   1642 
   1643     BCM_IF_ERROR_RETURN(bcm_esw_switch_control_get(unit,
   1644                         bcmSwitchTrunkDynamicAccountingSelect, &vla));
   1645     if (vla) {
   1646         max_members = soc_mem_index_count(unit, DLB_LAG_MEMBER_ATTRIBUTEm);
   1647     } else {
   1648         /* In physical link accounting, the number of members is limited to
   1649          * the number of physical ports.
   1650          */
   1651         max_members = soc_reg_field_length(unit, DLB_LAG_MEMBER_HW_STATE_64r,
   1652                 BITMAPf);
   1653     }
   1654 
   1655     for (i = 0; i < max_members; i++) {
   1656         if (!_BCM_LAG_DLB_MEMBER_ID_USED_GET(unit, i)) {
   1657             _BCM_LAG_DLB_MEMBER_ID_USED_SET(unit, i);
   1658             *member_id = i;
   1659             return BCM_E_NONE;
   1660         }
   1661     }
   1662 
   1663     return BCM_E_RESOURCE;
   1664 }
   1665 
   1666 /*
   1667  * Function:
   1668  *      _bcm_tr3_lag_dlb_member_id_free
   1669  * Purpose:
   1670  *      Free a LAG DLB Member ID.
   1671  * Parameters:
   1672  *      unit - (IN) SOC unit number.
   1673  *      member_id - (IN) Member ID to be freed.
   1674  * Returns:
   1675  *      BCM_E_xxx
   1676  */
   1677 STATIC int
   1678 _bcm_tr3_lag_dlb_member_id_free(int unit, int member_id)
   1679 {
   1680     if (member_id < 0 || member_id > soc_mem_index_max(unit,
   1681                 DLB_LAG_MEMBER_ATTRIBUTEm)) {
   1682         return BCM_E_PARAM;
   1683     }
   1684 
   1685     _BCM_LAG_DLB_MEMBER_ID_USED_CLR(unit, member_id);
   1686 
   1687     return BCM_E_NONE;
   1688 }
   1689 
   1690 /*
   1691  * Function:
   1692  *      _bcm_tr3_lag_dlb_quality_assign
   1693  * Purpose:
   1694  *      Assign quality based on port loading and queue size.
   1695  * Parameters:
   1696  *      unit - (IN)SOC unit number. 
   1697  *      tx_load_percent - (IN) Percent weight of port loading in determing
   1698  *                             port quality. The remaining percentage is
   1699  *                             the weight of queue size.
   1700  *      entry_arr - (IN) Array of 64 quality map table entries.
   1701  * Returns:
   1702  *      BCM_X_XXX
   1703  */
   1704 STATIC int 
   1705 _bcm_tr3_lag_dlb_quality_assign(int unit, int tx_load_percent,
   1706         uint32 *entry_arr)
   1707 {
   1708     int quantized_tx_load;
   1709     int quantized_qsize;
   1710     int quality;
   1711     int entry_index;
   1712 
   1713     if (entry_arr == NULL) {
   1714         return BCM_E_PARAM;
   1715     }
   1716 
   1717     for (quantized_tx_load = 0; quantized_tx_load < 8; quantized_tx_load++) {
   1718         for (quantized_qsize = 0; quantized_qsize < 8; quantized_qsize++) {
   1719             quality = (quantized_tx_load * tx_load_percent +
   1720                     quantized_qsize * (100 - tx_load_percent)) / 100;
   1721             entry_index = (quantized_tx_load << 3) + quantized_qsize;
   1722             soc_DLB_LAG_QUALITY_MAPPINGm_field32_set(unit,
   1723                     &entry_arr[entry_index], QUALITYf, quality);
   1724         }
   1725     }
   1726 
   1727     return BCM_E_NONE;
   1728 }
   1729 
   1730 /*
   1731  * Function:
   1732  *      _bcm_tr3_lag_dlb_member_quality_map_set
   1733  * Purpose:
   1734  *      Set per-member LAG DLB quality mapping table.
   1735  * Parameters:
   1736  *      unit - (IN) SOC unit number.
   1737  *      member_id - (IN) Member ID.
   1738  *      tx_load_percent - (IN) Percent weight of port loading in determing
   1739  *                             port quality. The remaining percentage is
   1740  *                             the weight of queue size.
   1741  * Returns:
   1742  *      BCM_E_xxx
   1743  */
   1744 STATIC int
   1745 _bcm_tr3_lag_dlb_member_quality_map_set(int unit, int member_id,
   1746         int tx_load_percent)
   1747 {
   1748     soc_profile_mem_t *profile;
   1749     soc_mem_t mem;
   1750     int entry_bytes;
   1751     int entries_per_profile;
   1752     int alloc_size;
   1753     uint32 *entry_arr;
   1754     int rv = BCM_E_NONE;
   1755     void *entries;
   1756     uint32 base_index;
   1757     uint32 old_base_index;
   1758     dlb_lag_quality_control_entry_t quality_control_entry;
   1759 
   1760     profile = _tr3_lag_dlb_bk[unit]->lag_dlb_quality_map_profile;
   1761 
   1762     entries_per_profile = 64;
   1763     entry_bytes = sizeof(dlb_lag_quality_mapping_entry_t);
   1764     alloc_size = entries_per_profile * entry_bytes;
   1765     entry_arr = sal_alloc(alloc_size, "LAG DLB Quality Map entries");
   1766     if (entry_arr == NULL) {
   1767         return BCM_E_MEMORY;
   1768     }
   1769     sal_memset(entry_arr, 0, alloc_size);
   1770 
   1771     /* Assign quality in the entry array */
   1772     rv = _bcm_tr3_lag_dlb_quality_assign(unit, tx_load_percent, entry_arr);
   1773     if (BCM_FAILURE(rv)) {
   1774         sal_free(entry_arr);
   1775         return rv;
   1776     }
   1777 
   1778     mem = DLB_LAG_QUALITY_MAPPINGm;
   1779     soc_mem_lock(unit, mem);
   1780 
   1781     /* Add profile */
   1782     entries = entry_arr;
   1783     rv = soc_profile_mem_add(unit, profile, &entries, entries_per_profile,
   1784             &base_index);
   1785     sal_free(entry_arr);
   1786     if (SOC_FAILURE(rv)) {
   1787         soc_mem_unlock(unit, mem);
   1788         return rv;
   1789     }
   1790 
   1791     /* Update member profile pointer */
   1792     rv = READ_DLB_LAG_QUALITY_CONTROLm(unit, MEM_BLOCK_ANY, member_id,
   1793             &quality_control_entry);
   1794     if (SOC_FAILURE(rv)) {
   1795         soc_mem_unlock(unit, mem);
   1796         return rv;
   1797     }
   1798     old_base_index = entries_per_profile * soc_mem_field32_get(unit,
   1799             DLB_LAG_QUALITY_CONTROLm, &quality_control_entry,
   1800             PROFILE_PTRf);
   1801     soc_DLB_LAG_QUALITY_CONTROLm_field32_set(unit, &quality_control_entry, 
   1802             PROFILE_PTRf, base_index / entries_per_profile);
   1803     rv = WRITE_DLB_LAG_QUALITY_CONTROLm(unit, MEM_BLOCK_ALL, member_id,
   1804             &quality_control_entry);
   1805     if (SOC_FAILURE(rv)) {
   1806         soc_mem_unlock(unit, mem);
   1807         return rv;
   1808     }
   1809 
   1810     /* Delete old profile */
   1811     rv = soc_profile_mem_delete(unit, profile, old_base_index);
   1812     soc_mem_unlock(unit, mem);
   1813 
   1814     LAG_DLB_INFO(unit)->lag_dlb_load_weight[base_index/entries_per_profile] =
   1815         tx_load_percent;
   1816 
   1817     return rv;
   1818 }
   1819 
   1820 /*
   1821  * Function:
   1822  *      bcm_tr3_lag_dlb_free_resource
   1823  * Purpose:
   1824  *      Free resources for a LAG dynamic load balancing group.
   1825  * Parameters:
   1826  *      unit   - (IN) SOC unit number. 
   1827  *      dlb_id - (IN) LAG DLB group ID.
   1828  *      member_info - (IN) Trunk member info.
   1829  * Returns:
   1830  *      BCM_E_xxx
   1831  */
   1832 int
   1833 bcm_tr3_lag_dlb_free_resource(int unit, int tid)
   1834 {
   1835     int rv = BCM_E_NONE;
   1836     trunk_group_entry_t tg_entry;
   1837     int dlb_enable;
   1838     int dlb_id;
   1839     dlb_lag_group_control_entry_t dlb_lag_group_control_entry;
   1840     int entry_base_ptr;
   1841     int flow_set_size;
   1842     int num_entries;
   1843     int block_base_ptr;
   1844     int num_blocks;
   1845     int vla;
   1846     dlb_lag_group_membership_entry_t dlb_lag_group_membership_entry;
   1847     int member_bitmap_width;
   1848     int alloc_size;
   1849     SHR_BITDCL *member_bitmap = NULL;
   1850     SHR_BITDCL *status_bitmap = NULL;
   1851     SHR_BITDCL *override_bitmap = NULL;
   1852     int i;
   1853     int reverse_map_index;
   1854     dlb_lag_member_attribute_entry_t dlb_lag_member_attribute_entry;
   1855     bcm_module_t mod;
   1856     bcm_port_t port;
   1857     int is_local;
   1858     dlb_lag_quality_control_entry_t dlb_lag_quality_control_entry;
   1859     dlb_lag_member_sw_state_entry_t dlb_lag_member_sw_state_entry;
   1860 
   1861     SOC_IF_ERROR_RETURN
   1862         (READ_TRUNK_GROUPm(unit, MEM_BLOCK_ANY, tid, &tg_entry));
   1863     dlb_enable = soc_TRUNK_GROUPm_field32_get(unit, &tg_entry,
   1864             GROUP_ENABLEf);
   1865     dlb_id = soc_TRUNK_GROUPm_field32_get(unit, &tg_entry,
   1866             DLB_IDf);
   1867 
   1868     if (!dlb_enable) {
   1869         return BCM_E_NONE;
   1870     }
   1871 
   1872     /* Clear DLB fields in TRUNK_GROUP table */
   1873 
   1874     soc_TRUNK_GROUPm_field32_set(unit, &tg_entry, GROUP_ENABLEf, 0);
   1875     soc_TRUNK_GROUPm_field32_set(unit, &tg_entry, DLB_IDf, 0);
   1876     SOC_IF_ERROR_RETURN
   1877         (WRITE_TRUNK_GROUPm(unit, MEM_BLOCK_ALL, tid, &tg_entry));
   1878 
   1879     /* Clear VLA quality measure control */
   1880 
   1881     SOC_IF_ERROR_RETURN(WRITE_DLB_LAG_VLA_QUALITY_MEASURE_CONTROLm(unit,
   1882                 MEM_BLOCK_ALL, dlb_id,
   1883                 soc_mem_entry_null(unit,
   1884                     DLB_LAG_VLA_QUALITY_MEASURE_CONTROLm)));
   1885 
   1886     /* Free flow set table resources */
   1887 
   1888     SOC_IF_ERROR_RETURN
   1889         (READ_DLB_LAG_GROUP_CONTROLm(unit, MEM_BLOCK_ANY, dlb_id,
   1890                                      &dlb_lag_group_control_entry));
   1891     entry_base_ptr = soc_DLB_LAG_GROUP_CONTROLm_field32_get(unit,
   1892             &dlb_lag_group_control_entry, FLOW_SET_BASEf);
   1893     flow_set_size = soc_DLB_LAG_GROUP_CONTROLm_field32_get(unit,
   1894             &dlb_lag_group_control_entry, FLOW_SET_SIZEf);
   1895     BCM_IF_ERROR_RETURN
   1896         (_bcm_tr3_lag_dlb_dynamic_size_decode(flow_set_size, &num_entries));
   1897     block_base_ptr = entry_base_ptr >> 9;
   1898     num_blocks = num_entries >> 9; 
   1899     _BCM_LAG_DLB_FLOWSET_BLOCK_USED_CLR_RANGE(unit, block_base_ptr, num_blocks);
   1900 
   1901     /* Clear LAG DLB group control */
   1902 
   1903     SOC_IF_ERROR_RETURN(WRITE_DLB_LAG_GROUP_CONTROLm(unit,
   1904                 MEM_BLOCK_ALL, dlb_id,
   1905                 soc_mem_entry_null(unit, DLB_LAG_GROUP_CONTROLm)));
   1906 
   1907     /* Free Member IDs */
   1908 
   1909     BCM_IF_ERROR_RETURN(bcm_esw_switch_control_get(unit,
   1910                 bcmSwitchTrunkDynamicAccountingSelect, &vla));
   1911 
   1912     SOC_IF_ERROR_RETURN(READ_DLB_LAG_GROUP_MEMBERSHIPm(unit, MEM_BLOCK_ANY,
   1913                 dlb_id, &dlb_lag_group_membership_entry));
   1914     member_bitmap_width = soc_mem_field_length(unit,
   1915             DLB_LAG_GROUP_MEMBERSHIPm, MEMBER_BITMAPf);
   1916     alloc_size = SHR_BITALLOCSIZE(member_bitmap_width);
   1917     member_bitmap = sal_alloc(alloc_size, "DLB LAG member bitmap"); 
   1918     if (NULL == member_bitmap) {
   1919         return BCM_E_MEMORY;
   1920     }
   1921     sal_memset(member_bitmap, 0, alloc_size);
   1922     soc_DLB_LAG_GROUP_MEMBERSHIPm_field_get(unit,
   1923             &dlb_lag_group_membership_entry, MEMBER_BITMAPf, member_bitmap);
   1924 
   1925     for (i = 0; i < member_bitmap_width; i++) {
   1926         if (SHR_BITGET(member_bitmap, i)) {
   1927 
   1928             /* Clear membership reverse map */
   1929 
   1930             if (vla) {
   1931                 reverse_map_index = i;
   1932             } else {
   1933                 rv = READ_DLB_LAG_MEMBER_ATTRIBUTEm(unit, MEM_BLOCK_ANY, i,
   1934                         &dlb_lag_member_attribute_entry); 
   1935                 if (BCM_FAILURE(rv)) {
   1936                     goto error;
   1937                 }
   1938                 mod = soc_DLB_LAG_MEMBER_ATTRIBUTEm_field32_get(unit,
   1939                         &dlb_lag_member_attribute_entry, MODULE_IDf);
   1940                 port = soc_DLB_LAG_MEMBER_ATTRIBUTEm_field32_get(unit,
   1941                         &dlb_lag_member_attribute_entry, PORT_NUMf);
   1942                 rv = _bcm_esw_modid_is_local(unit, mod, &is_local);
   1943                 if (BCM_FAILURE(rv)) {
   1944                     goto error;
   1945                 }
   1946                 if (!is_local) {
   1947                     rv = BCM_E_INTERNAL;
   1948                     goto error;
   1949                 }
   1950                 reverse_map_index = port;
   1951             }
   1952             rv = WRITE_DLB_LAG_MEMBERSHIP_REVERSE_MAPm(unit, MEM_BLOCK_ALL,
   1953                     reverse_map_index, soc_mem_entry_null(unit,
   1954                         DLB_LAG_MEMBERSHIP_REVERSE_MAPm));
   1955             if (BCM_FAILURE(rv)) {
   1956                 goto error;
   1957             }
   1958 
   1959             /* Clear member attribute */
   1960 
   1961             rv = WRITE_DLB_LAG_MEMBER_ATTRIBUTEm(unit, MEM_BLOCK_ALL, i,
   1962                     soc_mem_entry_null(unit, DLB_LAG_MEMBER_ATTRIBUTEm));
   1963             if (BCM_FAILURE(rv)) {
   1964                 goto error;
   1965             }
   1966 
   1967             /* Revert member quality mapping profile to default */
   1968 
   1969             rv = _bcm_tr3_lag_dlb_member_quality_map_set(unit, i, 100);
   1970             if (BCM_FAILURE(rv)) {
   1971                 goto error;
   1972             }
   1973 
   1974             /* Clear threshold scaling factors */
   1975 
   1976             rv = READ_DLB_LAG_QUALITY_CONTROLm(unit, MEM_BLOCK_ANY, i,
   1977                     &dlb_lag_quality_control_entry);
   1978             if (BCM_FAILURE(rv)) {
   1979                 goto error;
   1980             }
   1981             soc_DLB_LAG_QUALITY_CONTROLm_field32_set(unit,
   1982                     &dlb_lag_quality_control_entry, LOADING_SCALING_FACTORf, 0);
   1983             soc_DLB_LAG_QUALITY_CONTROLm_field32_set(unit,
   1984                     &dlb_lag_quality_control_entry, QSIZE_SCALING_FACTORf, 0);
   1985             rv = WRITE_DLB_LAG_QUALITY_CONTROLm(unit, MEM_BLOCK_ALL, i,
   1986                     &dlb_lag_quality_control_entry);
   1987             if (BCM_FAILURE(rv)) {
   1988                 goto error;
   1989             }
   1990 
   1991             /* Free member ID */
   1992 
   1993             rv = _bcm_tr3_lag_dlb_member_id_free(unit, i);
   1994             if (BCM_FAILURE(rv)) {
   1995                 goto error;
   1996             }
   1997         }
   1998     }
   1999 
   2000     /* Clear member software state */
   2001 
   2002     rv = READ_DLB_LAG_MEMBER_SW_STATEm(unit, MEM_BLOCK_ANY, 0,
   2003                 &dlb_lag_member_sw_state_entry);
   2004     if (BCM_FAILURE(rv)) {
   2005         goto error;
   2006     }
   2007 
   2008     status_bitmap = sal_alloc(alloc_size, "DLB LAG member status bitmap"); 
   2009     if (NULL == status_bitmap) {
   2010         rv = BCM_E_MEMORY;
   2011         goto error;
   2012     }
   2013     soc_DLB_LAG_MEMBER_SW_STATEm_field_get(unit,
   2014             &dlb_lag_member_sw_state_entry, MEMBER_BITMAPf, status_bitmap);
   2015     SHR_BITREMOVE_RANGE(status_bitmap, member_bitmap, 0, member_bitmap_width,
   2016             status_bitmap);
   2017     soc_DLB_LAG_MEMBER_SW_STATEm_field_set(unit,
   2018             &dlb_lag_member_sw_state_entry, MEMBER_BITMAPf, status_bitmap);
   2019 
   2020     override_bitmap = sal_alloc(alloc_size, "DLB LAG member override bitmap"); 
   2021     if (NULL == override_bitmap) {
   2022         rv = BCM_E_MEMORY;
   2023         goto error;
   2024     }
   2025     soc_DLB_LAG_MEMBER_SW_STATEm_field_get(unit,
   2026             &dlb_lag_member_sw_state_entry, OVERRIDE_MEMBER_BITMAPf, override_bitmap);
   2027     SHR_BITREMOVE_RANGE(override_bitmap, member_bitmap, 0, member_bitmap_width,
   2028             override_bitmap);
   2029     soc_DLB_LAG_MEMBER_SW_STATEm_field_set(unit,
   2030             &dlb_lag_member_sw_state_entry, OVERRIDE_MEMBER_BITMAPf, override_bitmap);
   2031 
   2032     rv = WRITE_DLB_LAG_MEMBER_SW_STATEm(unit, MEM_BLOCK_ALL, 0,
   2033                 &dlb_lag_member_sw_state_entry);
   2034     if (BCM_FAILURE(rv)) {
   2035         goto error;
   2036     }
   2037 
   2038     sal_free(member_bitmap);
   2039     sal_free(status_bitmap);
   2040     sal_free(override_bitmap);
   2041 
   2042     /* Clear group membership */
   2043 
   2044     SOC_IF_ERROR_RETURN(WRITE_DLB_LAG_GROUP_MEMBERSHIPm(unit,
   2045                 MEM_BLOCK_ALL, dlb_id,
   2046                 soc_mem_entry_null(unit, DLB_LAG_GROUP_MEMBERSHIPm)));
   2047 
   2048     /* Free DLB ID */
   2049 
   2050     BCM_IF_ERROR_RETURN(_bcm_tr3_lag_dlb_id_free(unit, dlb_id));
   2051 
   2052     return rv;
   2053 
   2054 error:
   2055     if (NULL != member_bitmap) {
   2056         sal_free(member_bitmap);
   2057     }
   2058     if (NULL != status_bitmap) {
   2059         sal_free(status_bitmap);
   2060     }
   2061     if (NULL != override_bitmap) {
   2062         sal_free(override_bitmap);
   2063     }
   2064     return rv;
   2065 }
   2066 
   2067 /*
   2068  * Function:
   2069  *      _bcm_tr3_lag_dlb_member_id_array_get
   2070  * Purpose:
   2071  *      Get member IDs for each LAG member.
   2072  * Parameters:
   2073  *      unit   - (IN) SOC unit number. 
   2074  *      dlb_id - (IN) DLB group ID.
   2075  *      num_dlb_ports  - (IN) Number of DLB ports.
   2076  *      mod_array  - (IN) Array of module IDs.
   2077  *      port_array - (IN) Array of port numbers.
   2078  *      scaling_factor_array - (IN) Array of scaling factors.
   2079  *      load_weight_array    - (IN) Array of load weights.
   2080  *      member_id_array - (OUT) Array of member IDs.
   2081  * Returns:
   2082  *      BCM_E_xxx
   2083  */
   2084 STATIC int
   2085 _bcm_tr3_lag_dlb_member_id_array_get(int unit, int dlb_id, int num_dlb_ports,
   2086         bcm_module_t *mod_array, bcm_port_t *port_array,
   2087         int *scaling_factor_array, int *load_weight_array,
   2088         int *member_id_array)
   2089 {
   2090     int rv = BCM_E_NONE;
   2091     int vla;
   2092     int i;
   2093     dlb_lag_membership_reverse_map_entry_t member_reverse_map_entry;
   2094     dlb_lag_member_attribute_entry_t member_attribute_entry;
   2095     int is_local;
   2096     dlb_lag_quality_control_entry_t dlb_lag_quality_control_entry;
   2097     port_tab_entry_t ptab;
   2098     int hw_mask;
   2099 
   2100     BCM_IF_ERROR_RETURN(bcm_esw_switch_control_get(unit,
   2101                         bcmSwitchTrunkDynamicAccountingSelect, &vla));
   2102 
   2103     for (i = 0; i < num_dlb_ports; i++) {
   2104         BCM_IF_ERROR_RETURN
   2105             (_bcm_tr3_lag_dlb_member_id_alloc(unit, &member_id_array[i]));
   2106 
   2107         /* Set member reverse map */
   2108 
   2109         sal_memset(&member_reverse_map_entry, 0,
   2110                 sizeof(dlb_lag_membership_reverse_map_entry_t));
   2111         if (vla) { /* Virtual link accounting */
   2112             soc_DLB_LAG_MEMBERSHIP_REVERSE_MAPm_field32_set(unit,
   2113                     &member_reverse_map_entry, VALIDf, 1);
   2114             soc_DLB_LAG_MEMBERSHIP_REVERSE_MAPm_field32_set(unit,
   2115                     &member_reverse_map_entry, GROUP_IDf, dlb_id);
   2116             soc_DLB_LAG_MEMBERSHIP_REVERSE_MAPm_field32_set(unit,
   2117                     &member_reverse_map_entry, MEMBER_COUNTf,
   2118                     num_dlb_ports - 1);
   2119             SOC_IF_ERROR_RETURN(WRITE_DLB_LAG_MEMBERSHIP_REVERSE_MAPm(unit,
   2120                     MEM_BLOCK_ALL, member_id_array[i],
   2121                     &member_reverse_map_entry));
   2122         } else { /* Physical link accounting */
   2123             BCM_IF_ERROR_RETURN
   2124                 (_bcm_esw_modid_is_local(unit, mod_array[i], &is_local));
   2125             if (!is_local) {
   2126                 /* In physical link accounting mode, LAG members should be
   2127                  * local.
   2128                  */
   2129                 return BCM_E_PARAM;
   2130             }
   2131             soc_DLB_LAG_MEMBERSHIP_REVERSE_MAPm_field32_set(unit,
   2132                     &member_reverse_map_entry, VALIDf, 1);
   2133             soc_DLB_LAG_MEMBERSHIP_REVERSE_MAPm_field32_set(unit,
   2134                     &member_reverse_map_entry,
   2135                     MEMBER_IDf, member_id_array[i]);
   2136             SOC_IF_ERROR_RETURN
   2137                 (READ_PORT_TABm(unit, MEM_BLOCK_ANY, port_array[i], &ptab));
   2138             if (soc_PORT_TABm_field32_get(unit, &ptab, PORT_TYPEf) == 3) {
   2139                 /* Port is an embedded Higig port */
   2140                 soc_DLB_LAG_MEMBERSHIP_REVERSE_MAPm_field32_set(unit,
   2141                         &member_reverse_map_entry, EMBEDDED_HGf, 1);
   2142             }
   2143             SOC_IF_ERROR_RETURN(WRITE_DLB_LAG_MEMBERSHIP_REVERSE_MAPm(unit,
   2144                     MEM_BLOCK_ALL, port_array[i],
   2145                     &member_reverse_map_entry));
   2146         }
   2147 
   2148         /* Set member attribute */
   2149 
   2150         sal_memset(&member_attribute_entry, 0,
   2151                 sizeof(dlb_lag_member_attribute_entry_t));
   2152         soc_DLB_LAG_MEMBER_ATTRIBUTEm_field32_set(unit,
   2153                 &member_attribute_entry, MODULE_IDf, mod_array[i]);
   2154         soc_DLB_LAG_MEMBER_ATTRIBUTEm_field32_set(unit,
   2155                 &member_attribute_entry, PORT_NUMf, port_array[i]);
   2156         SOC_IF_ERROR_RETURN(WRITE_DLB_LAG_MEMBER_ATTRIBUTEm(unit,
   2157                     MEM_BLOCK_ALL, member_id_array[i],
   2158                     &member_attribute_entry));
   2159 
   2160         /* Set member quality mapping profile */
   2161 
   2162         BCM_IF_ERROR_RETURN(_bcm_tr3_lag_dlb_member_quality_map_set(unit,
   2163                     member_id_array[i], load_weight_array[i]));
   2164 
   2165         /* Set threshold scaling factors */
   2166 
   2167         SOC_IF_ERROR_RETURN(READ_DLB_LAG_QUALITY_CONTROLm(unit, MEM_BLOCK_ANY,
   2168                     member_id_array[i], &dlb_lag_quality_control_entry));
   2169         hw_mask = (1 << soc_mem_field_length(unit, DLB_LAG_QUALITY_CONTROLm,
   2170                                       LOADING_SCALING_FACTORf)) - 1;
   2171         soc_DLB_LAG_QUALITY_CONTROLm_field32_set(unit,
   2172                 &dlb_lag_quality_control_entry, LOADING_SCALING_FACTORf,
   2173                 scaling_factor_array[i] & hw_mask);
   2174         hw_mask = (1 << soc_mem_field_length(unit, DLB_LAG_QUALITY_CONTROLm,
   2175                                       QSIZE_SCALING_FACTORf)) - 1;
   2176         soc_DLB_LAG_QUALITY_CONTROLm_field32_set(unit,
   2177                 &dlb_lag_quality_control_entry, QSIZE_SCALING_FACTORf,
   2178                 scaling_factor_array[i] & hw_mask);
   2179         SOC_IF_ERROR_RETURN(WRITE_DLB_LAG_QUALITY_CONTROLm(unit, MEM_BLOCK_ALL,
   2180                     member_id_array[i], &dlb_lag_quality_control_entry));
   2181     }
   2182 
   2183     return rv;
   2184 }
   2185 
   2186 /*
   2187  * Function:
   2188  *      bcm_tr3_lag_dlb_set
   2189  * Purpose:
   2190  *      Configure a LAG dynamic load balancing group.
   2191  * Parameters:
   2192  *      unit       - (IN) SOC unit number. 
   2193  *      tid        - (IN) Trunk group ID.
   2194  *      add_info   - (IN) Pointer to trunk add info structure.
   2195  *      num_dlb_ports  - (IN) Number of trunk member ports eligible for
   2196  *                        LAG DLB
   2197  *      mod_array  - (IN) Array of module IDs
   2198  *      port_array - (IN) Array of port IDs
   2199  *      scaling_factor_array - (IN) Array of scaling factors.
   2200  *      load_weight_array    - (IN) Array of load weights.
   2201  * Returns:
   2202  *      BCM_E_xxx
   2203  */
   2204 int
   2205 bcm_tr3_lag_dlb_set(int unit, int tid, _esw_trunk_add_info_t *add_info,
   2206         int num_dlb_ports, int *mod_array, int *port_array,
   2207         int *scaling_factor_array, int *load_weight_array)
   2208 {
   2209     int rv = BCM_E_NONE;
   2210     int dlb_enable;
   2211     int dlb_id;
   2212     int *member_id_array = NULL;
   2213     soc_mem_t flowset_mem;
   2214     int flowset_entry_size;
   2215     dlb_lag_flowset_entry_t *flowset_entry;
   2216     int num_blocks;
   2217     int total_blocks;
   2218     int max_block_base_ptr;
   2219     int block_base_ptr;
   2220     SHR_BITDCL occupied;
   2221     int entry_base_ptr;
   2222     int num_entries_per_block;
   2223     int alloc_size;
   2224     uint32 *block_ptr = NULL;
   2225     int i, k;
   2226     int index_min, index_max;
   2227     dlb_lag_group_control_entry_t dlb_lag_group_control_entry;
   2228     int flow_set_size;
   2229     int dlb_mode;
   2230     dlb_lag_group_membership_entry_t dlb_lag_group_membership_entry;
   2231     SHR_BITDCL *member_bitmap = NULL;
   2232     SHR_BITDCL *status_bitmap = NULL;
   2233     SHR_BITDCL *override_bitmap = NULL;
   2234     dlb_lag_member_sw_state_entry_t dlb_lag_member_sw_state_entry;
   2235     int vla;
   2236     dlb_lag_vla_quality_measure_control_entry_t vla_quality_measure_control_entry;
   2237     trunk_group_entry_t tg_entry;
   2238     int member_bitmap_width;
   2239 
   2240     dlb_enable = (add_info->psc == BCM_TRUNK_PSC_DYNAMIC) ||
   2241         (add_info->psc == BCM_TRUNK_PSC_DYNAMIC_ASSIGNED) ||
   2242         (add_info->psc == BCM_TRUNK_PSC_DYNAMIC_OPTIMAL);
   2243 
   2244     if (!dlb_enable) {
   2245         return BCM_E_NONE;
   2246     }
   2247 
   2248     /* Allocate a DLB ID */
   2249 
   2250     BCM_IF_ERROR_RETURN(_bcm_tr3_lag_dlb_id_alloc(unit, &dlb_id));
   2251 
   2252     /* Allocate member IDs */
   2253 
   2254     member_id_array = sal_alloc(sizeof(int) * num_dlb_ports,
   2255             "LAG DLB Member IDs");
   2256     if (NULL == member_id_array) {
   2257         rv = BCM_E_MEMORY;
   2258         goto error;
   2259     }
   2260     rv = _bcm_tr3_lag_dlb_member_id_array_get(unit, dlb_id, num_dlb_ports,
   2261             mod_array, port_array, scaling_factor_array, load_weight_array,
   2262             member_id_array);
   2263     if (BCM_FAILURE(rv)) {
   2264         goto error;
   2265     }
   2266 
   2267     /* Set group membership table */
   2268 
   2269     member_bitmap_width = soc_mem_field_length(unit,
   2270             DLB_LAG_GROUP_MEMBERSHIPm, MEMBER_BITMAPf);
   2271     alloc_size = SHR_BITALLOCSIZE(member_bitmap_width);
   2272     member_bitmap = sal_alloc(alloc_size, "DLB LAG member bitmap"); 
   2273     if (NULL == member_bitmap) {
   2274         rv = BCM_E_MEMORY;
   2275         goto error;
   2276     }
   2277     sal_memset(member_bitmap, 0, alloc_size);
   2278     for (i = 0; i < num_dlb_ports; i++) {
   2279         SHR_BITSET(member_bitmap, member_id_array[i]);
   2280     }
   2281 
   2282     sal_memset(&dlb_lag_group_membership_entry, 0,
   2283             sizeof(dlb_lag_group_membership_entry_t));
   2284     soc_DLB_LAG_GROUP_MEMBERSHIPm_field_set(unit,
   2285             &dlb_lag_group_membership_entry, MEMBER_BITMAPf, member_bitmap);
   2286     rv = WRITE_DLB_LAG_GROUP_MEMBERSHIPm(unit, MEM_BLOCK_ALL, dlb_id,
   2287             &dlb_lag_group_membership_entry);
   2288     if (SOC_FAILURE(rv)) {
   2289         goto error;
   2290     }
   2291 
   2292     /* Set member software state */
   2293 
   2294     rv = bcm_esw_switch_control_get(unit,
   2295             bcmSwitchTrunkDynamicAccountingSelect, &vla);
   2296     if (SOC_FAILURE(rv)) {
   2297         goto error;
   2298     }
   2299 
   2300     rv = READ_DLB_LAG_MEMBER_SW_STATEm(unit, MEM_BLOCK_ANY, 0,
   2301                 &dlb_lag_member_sw_state_entry);
   2302     if (BCM_FAILURE(rv)) {
   2303         goto error;
   2304     }
   2305 
   2306     status_bitmap = sal_alloc(alloc_size, "DLB LAG member status bitmap"); 
   2307     if (NULL == status_bitmap) {
   2308         rv = BCM_E_MEMORY;
   2309         goto error;
   2310     }
   2311     soc_DLB_LAG_MEMBER_SW_STATEm_field_get(unit,
   2312             &dlb_lag_member_sw_state_entry, MEMBER_BITMAPf, status_bitmap);
   2313 
   2314     if (vla) {
   2315         SHR_BITOR_RANGE(status_bitmap, member_bitmap, 0, member_bitmap_width,
   2316                 status_bitmap);
   2317     } else {
   2318         SHR_BITREMOVE_RANGE(status_bitmap, member_bitmap, 0, member_bitmap_width,
   2319                 status_bitmap);
   2320     }
   2321     soc_DLB_LAG_MEMBER_SW_STATEm_field_set(unit,
   2322             &dlb_lag_member_sw_state_entry, MEMBER_BITMAPf, status_bitmap);
   2323 
   2324     override_bitmap = sal_alloc(alloc_size, "DLB LAG member override bitmap"); 
   2325     if (NULL == override_bitmap) {
   2326         rv = BCM_E_MEMORY;
   2327         goto error;
   2328     }
   2329     soc_DLB_LAG_MEMBER_SW_STATEm_field_get(unit,
   2330             &dlb_lag_member_sw_state_entry, OVERRIDE_MEMBER_BITMAPf,
   2331             override_bitmap);
   2332 
   2333     if (vla) {
   2334         SHR_BITOR_RANGE(override_bitmap, member_bitmap, 0, member_bitmap_width,
   2335                 override_bitmap);
   2336     } else {
   2337         SHR_BITREMOVE_RANGE(override_bitmap, member_bitmap, 0, member_bitmap_width,
   2338                 override_bitmap);
   2339     }
   2340     soc_DLB_LAG_MEMBER_SW_STATEm_field_set(unit,
   2341             &dlb_lag_member_sw_state_entry, OVERRIDE_MEMBER_BITMAPf, override_bitmap);
   2342 
   2343     rv = WRITE_DLB_LAG_MEMBER_SW_STATEm(unit, MEM_BLOCK_ALL, 0,
   2344                 &dlb_lag_member_sw_state_entry);
   2345     if (BCM_FAILURE(rv)) {
   2346         goto error;
   2347     }
   2348 
   2349     /* Set DLB flow set table */
   2350 
   2351     flowset_mem = DLB_LAG_FLOWSETm;
   2352     flowset_entry_size = sizeof(dlb_lag_flowset_entry_t);
   2353     num_blocks = add_info->dynamic_size >> 9;
   2354     total_blocks = soc_mem_index_count(unit, flowset_mem) >> 9;
   2355     max_block_base_ptr = total_blocks - num_blocks;
   2356     for (block_base_ptr = 0;
   2357             block_base_ptr <= max_block_base_ptr;
   2358             block_base_ptr++) {
   2359         /* Check if the contiguous region of flow set table from
   2360          * block_base_ptr to (block_base_ptr + num_blocks - 1) is free. 
   2361          */
   2362         _BCM_LAG_DLB_FLOWSET_BLOCK_TEST_RANGE(unit, block_base_ptr, num_blocks,
   2363                 occupied); 
   2364         if (!occupied) {
   2365             break;
   2366         }
   2367     }
   2368     if (block_base_ptr > max_block_base_ptr) {
   2369         /* A contiguous region of the desired size could not be found in
   2370          * flow set table.
   2371          */
   2372         rv = BCM_E_RESOURCE;
   2373         goto error;
   2374     }
   2375 
   2376     entry_base_ptr = block_base_ptr << 9;
   2377     num_entries_per_block = 512;
   2378     alloc_size = num_entries_per_block * flowset_entry_size;
   2379     block_ptr = soc_cm_salloc(unit, alloc_size,
   2380             "Block of DLB_LAG_FLOWSET entries");
   2381     if (NULL == block_ptr) {
   2382         rv = BCM_E_MEMORY;
   2383         goto error;
   2384     }
   2385     sal_memset(block_ptr, 0, alloc_size);
   2386     for (i = 0; i < num_blocks; i++) {
   2387         for (k = 0; k < num_entries_per_block; k++) {
   2388             flowset_entry = soc_mem_table_idx_to_pointer(unit,
   2389                     DLB_LAG_FLOWSETm, dlb_lag_flowset_entry_t *,
   2390                     block_ptr, k);
   2391             soc_DLB_LAG_FLOWSETm_field32_set(unit, flowset_entry,
   2392                     VALIDf, 1);
   2393             soc_DLB_LAG_FLOWSETm_field32_set(unit, flowset_entry,
   2394                     MEMBER_IDf,
   2395                     member_id_array[(i * num_entries_per_block + k)
   2396                     % num_dlb_ports]);
   2397         }
   2398         index_min = entry_base_ptr + i * num_entries_per_block;
   2399         index_max = index_min + num_entries_per_block - 1;
   2400         rv = soc_mem_write_range(unit, flowset_mem, MEM_BLOCK_ALL,
   2401                 index_min, index_max, block_ptr);
   2402         if (SOC_FAILURE(rv)) {
   2403             goto error;
   2404         }
   2405     }
   2406 
   2407     _BCM_LAG_DLB_FLOWSET_BLOCK_USED_SET_RANGE(unit, block_base_ptr, num_blocks);
   2408 
   2409     /* Set LAG DLB group control table */
   2410 
   2411     sal_memset(&dlb_lag_group_control_entry, 0,
   2412             sizeof(dlb_lag_group_control_entry_t));
   2413     soc_DLB_LAG_GROUP_CONTROLm_field32_set(unit, &dlb_lag_group_control_entry,
   2414             ENABLE_OPTIMAL_CANDIDATE_UPDATEf, 1);
   2415     soc_DLB_LAG_GROUP_CONTROLm_field32_set(unit, &dlb_lag_group_control_entry,
   2416             FLOW_SET_BASEf, entry_base_ptr);
   2417 
   2418     rv = bcm_tr3_lag_dlb_dynamic_size_encode(add_info->dynamic_size,
   2419             &flow_set_size);
   2420     if (SOC_FAILURE(rv)) {
   2421         goto error;
   2422     }
   2423     soc_DLB_LAG_GROUP_CONTROLm_field32_set(unit, &dlb_lag_group_control_entry,
   2424             FLOW_SET_SIZEf, flow_set_size);
   2425 
   2426     switch (add_info->psc) {
   2427         case BCM_TRUNK_PSC_DYNAMIC:
   2428             dlb_mode = 0;
   2429             break;
   2430         case BCM_TRUNK_PSC_DYNAMIC_ASSIGNED:
   2431             dlb_mode = 1;
   2432             break;
   2433         case BCM_TRUNK_PSC_DYNAMIC_OPTIMAL:
   2434             dlb_mode = 2;
   2435             break;
   2436         default:
   2437             rv = BCM_E_PARAM;
   2438             goto error;
   2439     }
   2440     soc_DLB_LAG_GROUP_CONTROLm_field32_set(unit, &dlb_lag_group_control_entry,
   2441             MEMBER_ASSIGNMENT_MODEf, dlb_mode);
   2442 
   2443     soc_DLB_LAG_GROUP_CONTROLm_field32_set(unit, &dlb_lag_group_control_entry,
   2444             INACTIVITY_DURATIONf, add_info->dynamic_age);
   2445 
   2446     rv = WRITE_DLB_LAG_GROUP_CONTROLm(unit, MEM_BLOCK_ALL, dlb_id,
   2447             &dlb_lag_group_control_entry);
   2448     if (SOC_FAILURE(rv)) {
   2449         goto error;
   2450     }
   2451 
   2452     /* Set VLA quality measure control */
   2453 
   2454     if (vla) {
   2455         sal_memset(&vla_quality_measure_control_entry, 0,
   2456                 sizeof(dlb_lag_vla_quality_measure_control_entry_t));
   2457         soc_DLB_LAG_VLA_QUALITY_MEASURE_CONTROLm_field32_set(unit,
   2458                 &vla_quality_measure_control_entry,
   2459                 ENABLE_GROUP_AVG_CALCf, 1);
   2460         soc_DLB_LAG_VLA_QUALITY_MEASURE_CONTROLm_field32_set(unit,
   2461                 &vla_quality_measure_control_entry,
   2462                 VLA_WEIGHT_LOADINGf, add_info->dynamic_load_exponent);
   2463         soc_DLB_LAG_VLA_QUALITY_MEASURE_CONTROLm_field32_set(unit,
   2464                 &vla_quality_measure_control_entry,
   2465                 VLA_WEIGHT_EXPECTED_LOADINGf,
   2466                 add_info->dynamic_expected_load_exponent);
   2467         soc_DLB_LAG_VLA_QUALITY_MEASURE_CONTROLm_field32_set(unit,
   2468                 &vla_quality_measure_control_entry,
   2469                 VLA_CAP_LOADING_AVGf, (add_info->flags &
   2470                     BCM_TRUNK_FLAG_DYNAMIC_LOAD_DECREASE_RESET) ? 1 : 0);
   2471         soc_DLB_LAG_VLA_QUALITY_MEASURE_CONTROLm_field32_set(unit,
   2472                 &vla_quality_measure_control_entry,
   2473                 VLA_CAP_EXPECTED_LOADINGf, (add_info->flags &
   2474                     BCM_TRUNK_FLAG_DYNAMIC_EXPECTED_LOAD_DECREASE_RESET) ?
   2475                 1 : 0);
   2476         rv = WRITE_DLB_LAG_VLA_QUALITY_MEASURE_CONTROLm(unit, MEM_BLOCK_ALL,
   2477                 dlb_id, &vla_quality_measure_control_entry);
   2478         if (SOC_FAILURE(rv)) {
   2479             goto error;
   2480         }
   2481     }
   2482 
   2483     /* Update trunk group table */
   2484 
   2485     rv = READ_TRUNK_GROUPm(unit, MEM_BLOCK_ANY, tid, &tg_entry);
   2486     if (SOC_FAILURE(rv)) {
   2487         goto error;
   2488     }
   2489     soc_TRUNK_GROUPm_field32_set(unit, &tg_entry, GROUP_ENABLEf, 1);
   2490     soc_TRUNK_GROUPm_field32_set(unit, &tg_entry, DLB_IDf, dlb_id);
   2491     rv = WRITE_TRUNK_GROUPm(unit, MEM_BLOCK_ALL, tid, &tg_entry);
   2492     if (SOC_FAILURE(rv)) {
   2493         goto error;
   2494     }
   2495 
   2496     sal_free(member_id_array);
   2497     soc_cm_sfree(unit, block_ptr);
   2498     sal_free(member_bitmap);
   2499     sal_free(status_bitmap);
   2500     sal_free(override_bitmap);
   2501 
   2502     return rv;
   2503 
   2504 error:
   2505     if (NULL != member_id_array) { 
   2506         sal_free(member_id_array);
   2507     }
   2508     if (NULL != block_ptr) { 
   2509         soc_cm_sfree(unit, block_ptr);
   2510     }
   2511     if (NULL != member_bitmap) { 
   2512         sal_free(member_bitmap);
   2513     }
   2514     if (NULL != status_bitmap) {
   2515         sal_free(status_bitmap);
   2516     }
   2517     if (NULL != override_bitmap) {
   2518         sal_free(override_bitmap);
   2519     }
   2520     return rv;
   2521 }
   2522 
   2523 /*
   2524  * Function:
   2525  *      _bcm_tr3_lag_dlb_member_id_get
   2526  * Purpose:
   2527  *      Get LAG DLB member ID based on module ID and port.
   2528  * Parameters:
   2529  *      unit - (IN) SOC unit number. 
   2530  *      mod  - (IN) Module ID of the member.
   2531  *      port - (IN) Port number of the member.
   2532  *      member_id - (OUT) Member ID.
   2533  * Returns:
   2534  *      BCM_E_xxx
   2535  */
   2536 STATIC int
   2537 _bcm_tr3_lag_dlb_member_id_get(int unit, bcm_module_t mod, bcm_port_t port,
   2538         int *member_id)
   2539 {
   2540     int match;
   2541     int i;
   2542     dlb_lag_member_attribute_entry_t member_attr_entry;
   2543 
   2544     match = FALSE;
   2545     for (i = 0; i < soc_mem_index_count(unit, DLB_LAG_MEMBER_ATTRIBUTEm); i++) {
   2546         SOC_IF_ERROR_RETURN(READ_DLB_LAG_MEMBER_ATTRIBUTEm(unit, MEM_BLOCK_ANY,
   2547                     i, &member_attr_entry));
   2548         if ((mod == soc_DLB_LAG_MEMBER_ATTRIBUTEm_field32_get(unit,
   2549                         &member_attr_entry, MODULE_IDf)) &&
   2550             (port == soc_DLB_LAG_MEMBER_ATTRIBUTEm_field32_get(unit,
   2551                         &member_attr_entry, PORT_NUMf))) {
   2552             match = TRUE;
   2553             *member_id = i;
   2554             break;
   2555         }
   2556     }
   2557     if (!match) {
   2558         return BCM_E_NOT_FOUND;
   2559     }
   2560 
   2561     return BCM_E_NONE;
   2562 }
   2563 
   2564 
   2565 /*
   2566  * Function:
   2567  *      bcm_tr3_lag_dlb_member_attr_get
   2568  * Purpose:
   2569  *      Get attributes of a LAG DLB member.
   2570  * Parameters:
   2571  *      unit - (IN) SOC unit number. 
   2572  *      mod  - (IN) Module ID of the member.
   2573  *      port - (IN) Port number of the member.
   2574  *      scaling_factor - (OUT) Member's scaling factor.
   2575  *      load_weight    - (OUT) Member's load weight.
   2576  * Returns:
   2577  *      BCM_E_xxx
   2578  */
   2579 int
   2580 bcm_tr3_lag_dlb_member_attr_get(int unit, bcm_module_t mod, bcm_port_t port,
   2581         int *scaling_factor, int *load_weight)
   2582 {
   2583     int member_id;
   2584     dlb_lag_quality_control_entry_t quality_control_entry;
   2585     int profile_ptr;
   2586 
   2587     /* Find member ID of the given module and port */
   2588     BCM_IF_ERROR_RETURN
   2589         (_bcm_tr3_lag_dlb_member_id_get(unit, mod, port, &member_id));
   2590 
   2591     /* Get member's scaling factor and load weight */
   2592     SOC_IF_ERROR_RETURN(READ_DLB_LAG_QUALITY_CONTROLm(unit, MEM_BLOCK_ANY,
   2593                 member_id, &quality_control_entry));
   2594     *scaling_factor = soc_DLB_LAG_QUALITY_CONTROLm_field32_get(unit,
   2595             &quality_control_entry, LOADING_SCALING_FACTORf);
   2596     profile_ptr = soc_DLB_LAG_QUALITY_CONTROLm_field32_get(unit,
   2597             &quality_control_entry, PROFILE_PTRf);
   2598     *load_weight = LAG_DLB_INFO(unit)->lag_dlb_load_weight[profile_ptr];
   2599 
   2600     return BCM_E_NONE;
   2601 }
   2602 
   2603 /*
   2604  * Function:
   2605  *      bcm_tr3_lag_dlb_member_status_set
   2606  * Purpose:
   2607  *      Set LAG DLB member status.
   2608  * Parameters:
   2609  *      unit   - (IN) SOC unit number.
   2610  *      mod    - (IN) Member module ID.
   2611  *      port   - (IN) Member port number.
   2612  *      status - (IN) Member status.
   2613  * Returns:
   2614  *      BCM_E_xxx
   2615  */
   2616 int
   2617 bcm_tr3_lag_dlb_member_status_set(int unit, bcm_module_t mod, bcm_port_t port,
   2618         int status)
   2619 {
   2620     int member_id;
   2621     dlb_lag_member_sw_state_entry_t sw_state_entry;
   2622     int member_bitmap_width, alloc_size;
   2623     SHR_BITDCL *status_bitmap = NULL;
   2624     SHR_BITDCL *override_bitmap = NULL;
   2625 
   2626     BCM_IF_ERROR_RETURN
   2627         (_bcm_tr3_lag_dlb_member_id_get(unit, mod, port, &member_id));
   2628 
   2629     /* Get status bitmap */
   2630     SOC_IF_ERROR_RETURN(READ_DLB_LAG_MEMBER_SW_STATEm(unit, MEM_BLOCK_ANY, 0,
   2631                 &sw_state_entry));
   2632     member_bitmap_width = soc_mem_field_length(unit, DLB_LAG_MEMBER_SW_STATEm,
   2633             MEMBER_BITMAPf);
   2634     alloc_size = SHR_BITALLOCSIZE(member_bitmap_width);
   2635     status_bitmap = sal_alloc(alloc_size, "DLB LAG member status bitmap"); 
   2636     if (NULL == status_bitmap) {
   2637         return BCM_E_MEMORY;
   2638     }
   2639     soc_DLB_LAG_MEMBER_SW_STATEm_field_get(unit, &sw_state_entry,
   2640             MEMBER_BITMAPf, status_bitmap);
   2641 
   2642     /* Get override bitmap */
   2643     override_bitmap = sal_alloc(alloc_size, "DLB LAG member override bitmap"); 
   2644     if (NULL == override_bitmap) {
   2645         sal_free(status_bitmap);
   2646         return BCM_E_MEMORY;
   2647     }
   2648     soc_DLB_LAG_MEMBER_SW_STATEm_field_get(unit, &sw_state_entry,
   2649             OVERRIDE_MEMBER_BITMAPf, override_bitmap);
   2650 
   2651     /* Update status and override bitmaps */
   2652     switch (status) {
   2653         case BCM_TRUNK_DYNAMIC_MEMBER_FORCE_DOWN:
   2654             SHR_BITSET(override_bitmap, member_id);
   2655             SHR_BITCLR(status_bitmap, member_id);
   2656             break;
   2657         case BCM_TRUNK_DYNAMIC_MEMBER_FORCE_UP:
   2658             SHR_BITSET(override_bitmap, member_id);
   2659             SHR_BITSET(status_bitmap, member_id);
   2660             break;
   2661         case BCM_TRUNK_DYNAMIC_MEMBER_HW:
   2662             SHR_BITCLR(override_bitmap, member_id);
   2663             SHR_BITCLR(status_bitmap, member_id);
   2664             break;
   2665         default:
   2666             sal_free(status_bitmap);
   2667             sal_free(override_bitmap);
   2668             return BCM_E_PARAM;
   2669     }
   2670 
   2671     /* Write status and override bitmaps to hardware */
   2672     soc_DLB_LAG_MEMBER_SW_STATEm_field_set(unit, &sw_state_entry,
   2673             MEMBER_BITMAPf, status_bitmap);
   2674     soc_DLB_LAG_MEMBER_SW_STATEm_field_set(unit, &sw_state_entry,
   2675             OVERRIDE_MEMBER_BITMAPf, override_bitmap);
   2676     sal_free(status_bitmap);
   2677     sal_free(override_bitmap);
   2678     SOC_IF_ERROR_RETURN(WRITE_DLB_LAG_MEMBER_SW_STATEm(unit, MEM_BLOCK_ALL, 0,
   2679                 &sw_state_entry));
   2680 
   2681     return BCM_E_NONE;
   2682 }
   2683 
   2684 /*
   2685  * Function:
   2686  *      bcm_tr3_lag_dlb_member_status_get
   2687  * Purpose:
   2688  *      Get LAG DLB member status.
   2689  * Parameters:
   2690  *      unit - (IN) SOC unit number.
   2691  *      mod    - (IN) Member module ID.
   2692  *      port   - (IN) Member port number.
   2693  *      status - (OUT) Member status.
   2694  * Returns:
   2695  *      BCM_E_xxx
   2696  */
   2697 int
   2698 bcm_tr3_lag_dlb_member_status_get(int unit, bcm_module_t mod, bcm_port_t port,
   2699         int *status)
   2700 {
   2701     int member_id;
   2702     dlb_lag_member_sw_state_entry_t sw_state_entry;
   2703     int member_bitmap_width, alloc_size;
   2704     SHR_BITDCL *status_bitmap = NULL;
   2705     SHR_BITDCL *override_bitmap = NULL;
   2706     uint64 hw_state, hw_status_bitmap;
   2707     uint32 bitmap32;
   2708     int rv = BCM_E_NONE;
   2709 
   2710     BCM_IF_ERROR_RETURN
   2711         (_bcm_tr3_lag_dlb_member_id_get(unit, mod, port, &member_id));
   2712 
   2713     /* Get status bitmap */
   2714     SOC_IF_ERROR_RETURN(READ_DLB_LAG_MEMBER_SW_STATEm(unit, MEM_BLOCK_ANY, 0,
   2715                 &sw_state_entry));
   2716     member_bitmap_width = soc_mem_field_length(unit, DLB_LAG_MEMBER_SW_STATEm,
   2717             MEMBER_BITMAPf);
   2718     alloc_size = SHR_BITALLOCSIZE(member_bitmap_width);
   2719     status_bitmap = sal_alloc(alloc_size, "DLB LAG member status bitmap"); 
   2720     if (NULL == status_bitmap) {
   2721         return BCM_E_MEMORY;
   2722     }
   2723     soc_DLB_LAG_MEMBER_SW_STATEm_field_get(unit, &sw_state_entry,
   2724             MEMBER_BITMAPf, status_bitmap);
   2725 
   2726     /* Get override bitmap */
   2727     override_bitmap = sal_alloc(alloc_size, "DLB LAG member override bitmap"); 
   2728     if (NULL == override_bitmap) {
   2729         sal_free(status_bitmap);
   2730         return BCM_E_MEMORY;
   2731     }
   2732     soc_DLB_LAG_MEMBER_SW_STATEm_field_get(unit, &sw_state_entry,
   2733             OVERRIDE_MEMBER_BITMAPf, override_bitmap);
   2734 
   2735     /* Derive status from software override and status bitmaps or
   2736      * hardware state bitmap.
   2737      */
   2738     if (SHR_BITGET(override_bitmap, member_id)) {
   2739         if (SHR_BITGET(status_bitmap, member_id)) {
   2740             *status = BCM_TRUNK_DYNAMIC_MEMBER_FORCE_UP;
   2741         } else {
   2742             *status = BCM_TRUNK_DYNAMIC_MEMBER_FORCE_DOWN;
   2743         }
   2744     } else {
   2745         rv = READ_DLB_LAG_MEMBER_HW_STATE_64r(unit, &hw_state); 
   2746         if (SOC_FAILURE(rv)) {
   2747             sal_free(status_bitmap);
   2748             sal_free(override_bitmap);
   2749             return rv;
   2750         }
   2751         hw_status_bitmap = soc_reg64_field_get(unit,
   2752                 DLB_LAG_MEMBER_HW_STATE_64r, hw_state, BITMAPf);
   2753         if (member_id < 32) {
   2754             bitmap32 = COMPILER_64_LO(hw_status_bitmap);
   2755         } else {
   2756             bitmap32 = COMPILER_64_HI(hw_status_bitmap);
   2757             member_id -= 32;
   2758         }
   2759         if ((1 << member_id) & bitmap32) {
   2760             *status = BCM_TRUNK_DYNAMIC_MEMBER_HW_UP;
   2761         } else {
   2762             *status = BCM_TRUNK_DYNAMIC_MEMBER_HW_DOWN;
   2763         }
   2764     }
   2765 
   2766     sal_free(status_bitmap);
   2767     sal_free(override_bitmap);
   2768     return rv;
   2769 }
   2770 
   2771 /*
   2772  * Function:
   2773  *      bcm_tr3_lag_dlb_ethertype_set
   2774  * Purpose:
   2775  *      Set the Ethertypes that are eligible or ineligible for
   2776  *      LAG dynamic load balancing.
   2777  * Parameters:
   2778  *      unit - (IN) Unit number.
   2779  *      flags - (IN) BCM_TRUNK_DYNAMIC_ETHERTYPE_xxx flags.
   2780  *      ethertype_count - (IN) Number of elements in ethertype_array.
   2781  *      ethertype_array - (IN) Array of Ethertypes.
   2782  * Returns:
   2783  *      BCM_E_XXX
   2784  */
   2785 int 
   2786 bcm_tr3_lag_dlb_ethertype_set(
   2787     int unit, 
   2788     uint32 flags, 
   2789     int ethertype_count, 
   2790     int *ethertype_array)
   2791 {
   2792     uint32 measure_control_reg;
   2793     int i, j;
   2794     dlb_lag_ethertype_eligibility_map_entry_t ethertype_entry;
   2795 
   2796     /* Input check */
   2797     if (ethertype_count > soc_mem_index_count(unit,
   2798                 DLB_LAG_ETHERTYPE_ELIGIBILITY_MAPm)) {
   2799         return BCM_E_RESOURCE;
   2800     }
   2801 
   2802     /* Update quality measure control register */
   2803     SOC_IF_ERROR_RETURN
   2804         (READ_DLB_LAG_QUALITY_MEASURE_CONTROLr(unit, &measure_control_reg));
   2805     soc_reg_field_set(unit, DLB_LAG_QUALITY_MEASURE_CONTROLr,
   2806             &measure_control_reg, ETHERTYPE_ELIGIBILITY_CONFIGf,
   2807             flags & BCM_TRUNK_DYNAMIC_ETHERTYPE_ELIGIBLE ? 1 : 0);
   2808     soc_reg_field_set(unit, DLB_LAG_QUALITY_MEASURE_CONTROLr,
   2809             &measure_control_reg, INNER_OUTER_ETHERTYPE_SELECTIONf,
   2810             flags & BCM_TRUNK_DYNAMIC_ETHERTYPE_INNER ? 1 : 0);
   2811     SOC_IF_ERROR_RETURN
   2812         (WRITE_DLB_LAG_QUALITY_MEASURE_CONTROLr(unit, measure_control_reg));
   2813 
   2814     /* Update Ethertype eligibility map table */
   2815     for (i = 0; i < ethertype_count; i++) {
   2816         sal_memset(&ethertype_entry, 0,
   2817                 sizeof(dlb_lag_ethertype_eligibility_map_entry_t));
   2818         soc_DLB_LAG_ETHERTYPE_ELIGIBILITY_MAPm_field32_set(unit,
   2819                 &ethertype_entry, VALIDf, 1);
   2820         soc_DLB_LAG_ETHERTYPE_ELIGIBILITY_MAPm_field32_set(unit,
   2821                 &ethertype_entry, ETHERTYPEf, ethertype_array[i]);
   2822         SOC_IF_ERROR_RETURN(WRITE_DLB_LAG_ETHERTYPE_ELIGIBILITY_MAPm(unit,
   2823                     MEM_BLOCK_ALL, i, &ethertype_entry));
   2824     }
   2825 
   2826     /* Zero out remaining entries of Ethertype eligibility map table */
   2827     for (j = i; j < soc_mem_index_count(unit,
   2828                 DLB_LAG_ETHERTYPE_ELIGIBILITY_MAPm); j++) {
   2829         SOC_IF_ERROR_RETURN(WRITE_DLB_LAG_ETHERTYPE_ELIGIBILITY_MAPm(unit,
   2830                     MEM_BLOCK_ALL, j, soc_mem_entry_null(unit,
   2831                         DLB_LAG_ETHERTYPE_ELIGIBILITY_MAPm)));
   2832     }
   2833 
   2834     return BCM_E_NONE;
   2835 }
   2836 
   2837 /*
   2838  * Function:
   2839  *      bcm_tr3_lag_dlb_ethertype_get
   2840  * Purpose:
   2841  *      Get the Ethertypes that are eligible or ineligible for
   2842  *      LAG dynamic load balancing.
   2843  * Parameters:
   2844  *      unit - (IN) Unit number.
   2845  *      flags - (INOUT) BCM_TRUNK_DYNAMIC_ETHERTYPE_xxx flags.
   2846  *      ethertype_max - (IN) Number of elements in ethertype_array.
   2847  *      ethertype_array - (OUT) Array of Ethertypes.
   2848  *      ethertype_count - (OUT) Number of elements returned in ethertype_array.
   2849  * Returns:
   2850  *      BCM_E_XXX
   2851  */
   2852 int 
   2853 bcm_tr3_lag_dlb_ethertype_get(
   2854     int unit, 
   2855     uint32 *flags, 
   2856     int ethertype_max, 
   2857     int *ethertype_array, 
   2858     int *ethertype_count)
   2859 {
   2860     uint32 measure_control_reg;
   2861     int i;
   2862     int ethertype;
   2863     dlb_lag_ethertype_eligibility_map_entry_t ethertype_entry;
   2864 
   2865     *ethertype_count = 0;
   2866 
   2867     /* Get flags */
   2868     SOC_IF_ERROR_RETURN
   2869         (READ_DLB_LAG_QUALITY_MEASURE_CONTROLr(unit, &measure_control_reg));
   2870     if (soc_reg_field_get(unit, DLB_LAG_QUALITY_MEASURE_CONTROLr,
   2871                 measure_control_reg, ETHERTYPE_ELIGIBILITY_CONFIGf)) {
   2872         *flags |= BCM_TRUNK_DYNAMIC_ETHERTYPE_ELIGIBLE;
   2873     }
   2874     if (soc_reg_field_get(unit, DLB_LAG_QUALITY_MEASURE_CONTROLr,
   2875                 measure_control_reg, INNER_OUTER_ETHERTYPE_SELECTIONf)) {
   2876         *flags |= BCM_TRUNK_DYNAMIC_ETHERTYPE_INNER;
   2877     }
   2878 
   2879     /* Get Ethertypes */
   2880     for (i = 0; i < soc_mem_index_count(unit,
   2881                 DLB_LAG_ETHERTYPE_ELIGIBILITY_MAPm); i++) {
   2882         SOC_IF_ERROR_RETURN(READ_DLB_LAG_ETHERTYPE_ELIGIBILITY_MAPm(unit,
   2883                     MEM_BLOCK_ANY, i, &ethertype_entry));
   2884         if (soc_DLB_LAG_ETHERTYPE_ELIGIBILITY_MAPm_field32_get(unit,
   2885                     &ethertype_entry, VALIDf)) {
   2886             ethertype = soc_DLB_LAG_ETHERTYPE_ELIGIBILITY_MAPm_field32_get(unit,
   2887                     &ethertype_entry, ETHERTYPEf);
   2888             if (NULL != ethertype_array) {
   2889                 ethertype_array[*ethertype_count] = ethertype;
   2890             }
   2891             (*ethertype_count)++;
   2892             if ((ethertype_max > 0) && (*ethertype_count == ethertype_max)) {
   2893                 break;
   2894             }
   2895         }
   2896     }
   2897 
   2898     return BCM_E_NONE;
   2899 }
   2900 
   2901 #ifdef BCM_WARM_BOOT_SUPPORT
   2902 
   2903 /*
   2904  * Function:
   2905  *      bcm_tr3_lag_dlb_wb_alloc_size_get
   2906  * Purpose:
   2907  *      Get level 2 warm boot scache size for LAG DLB.
   2908  * Parameters:
   2909  *      unit - (IN) SOC unit number.
   2910  *      size - (OUT) Allocation size.
   2911  * Returns:
   2912  *      BCM_E_XXX
   2913  */
   2914 int
   2915 bcm_tr3_lag_dlb_wb_alloc_size_get(int unit, int *size) 
   2916 {
   2917     int alloc_size = 0;
   2918     int num_elements;
   2919 
   2920     /* Allocate size for the following LAG DLB parameters: 
   2921      * int lag_dlb_sample_rate;
   2922      * int lag_dlb_tx_load_min_th;
   2923      * int lag_dlb_tx_load_max_th;
   2924      * int lag_dlb_qsize_min_th;
   2925      * int lag_dlb_qsize_max_th;
   2926      * int lag_dlb_exp_load_min_th;
   2927      * int lag_dlb_exp_load_max_th;
   2928      * int lag_dlb_imbalance_min_th;
   2929      * int lag_dlb_imbalance_max_th;
   2930      */
   2931     alloc_size += sizeof(int) * 9;
   2932 
   2933     /* Allocate size of lag_dlb_load_weight array */
   2934     num_elements = 1 << soc_mem_field_length(unit,
   2935             DLB_LAG_QUALITY_CONTROLm, PROFILE_PTRf);
   2936     alloc_size += sizeof(uint8) * num_elements;
   2937 
   2938     *size = alloc_size;
   2939 
   2940     return BCM_E_NONE;
   2941 }
   2942 
   2943 /*
   2944  * Function:
   2945  *      bcm_tr3_lag_dlb_sync
   2946  * Purpose:
   2947  *      Store LAG DLB parameters into scache.
   2948  * Parameters:
   2949  *      unit - (IN) SOC unit number.
   2950  *      scache_ptr - (IN/OUT) Scache pointer
   2951  * Returns:
   2952  *      BCM_E_XXX
   2953  */
   2954 int
   2955 bcm_tr3_lag_dlb_sync(int unit, uint8 **scache_ptr) 
   2956 {
   2957     int value;
   2958     int num_elements;
   2959     int i;
   2960     uint8 load_weight;
   2961 
   2962     /* Store the following LAG DLB parameters: 
   2963      * int lag_dlb_sample_rate;
   2964      * int lag_dlb_tx_load_min_th;
   2965      * int lag_dlb_tx_load_max_th;
   2966      * int lag_dlb_qsize_min_th;
   2967      * int lag_dlb_qsize_max_th;
   2968      * int lag_dlb_exp_load_min_th;
   2969      * int lag_dlb_exp_load_max_th;
   2970      * int lag_dlb_imbalance_min_th;
   2971      * int lag_dlb_imbalance_max_th;
   2972      */
   2973     value = LAG_DLB_INFO(unit)->lag_dlb_sample_rate;
   2974     sal_memcpy((*scache_ptr), &value, sizeof(int));
   2975     (*scache_ptr) += sizeof(int);
   2976 
   2977     value = LAG_DLB_INFO(unit)->lag_dlb_tx_load_min_th;
   2978     sal_memcpy((*scache_ptr), &value, sizeof(int));
   2979     (*scache_ptr) += sizeof(int);
   2980 
   2981     value = LAG_DLB_INFO(unit)->lag_dlb_tx_load_max_th;
   2982     sal_memcpy((*scache_ptr), &value, sizeof(int));
   2983     (*scache_ptr) += sizeof(int);
   2984 
   2985     value = LAG_DLB_INFO(unit)->lag_dlb_qsize_min_th;
   2986     sal_memcpy((*scache_ptr), &value, sizeof(int));
   2987     (*scache_ptr) += sizeof(int);
   2988 
   2989     value = LAG_DLB_INFO(unit)->lag_dlb_qsize_max_th;
   2990     sal_memcpy((*scache_ptr), &value, sizeof(int));
   2991     (*scache_ptr) += sizeof(int);
   2992 
   2993     value = LAG_DLB_INFO(unit)->lag_dlb_exp_load_min_th;
   2994     sal_memcpy((*scache_ptr), &value, sizeof(int));
   2995     (*scache_ptr) += sizeof(int);
   2996 
   2997     value = LAG_DLB_INFO(unit)->lag_dlb_exp_load_max_th;
   2998     sal_memcpy((*scache_ptr), &value, sizeof(int));
   2999     (*scache_ptr) += sizeof(int);
   3000 
   3001     value = LAG_DLB_INFO(unit)->lag_dlb_imbalance_min_th;
   3002     sal_memcpy((*scache_ptr), &value, sizeof(int));
   3003     (*scache_ptr) += sizeof(int);
   3004 
   3005     value = LAG_DLB_INFO(unit)->lag_dlb_imbalance_max_th;
   3006     sal_memcpy((*scache_ptr), &value, sizeof(int));
   3007     (*scache_ptr) += sizeof(int);
   3008 
   3009     /* Store lag_dlb_load_weight array */
   3010     num_elements = 1 << soc_mem_field_length(unit,
   3011             DLB_LAG_QUALITY_CONTROLm, PROFILE_PTRf);
   3012     for (i = 0; i < num_elements; i++) {
   3013         load_weight = LAG_DLB_INFO(unit)->lag_dlb_load_weight[i];
   3014         sal_memcpy((*scache_ptr), &load_weight, sizeof(uint8));
   3015         (*scache_ptr) += sizeof(uint8);
   3016     }
   3017         
   3018     return BCM_E_NONE;
   3019 }
   3020 
   3021 /*
   3022  * Function:
   3023  *      bcm_tr3_lag_dlb_scache_recover
   3024  * Purpose:
   3025  *      Recover LAG DLB parameters from scache.
   3026  * Parameters:
   3027  *      unit - (IN) SOC unit number.
   3028  *      scache_ptr - (IN/OUT) Scache pointer
   3029  * Returns:
   3030  *      BCM_E_XXX
   3031  */
   3032 int
   3033 bcm_tr3_lag_dlb_scache_recover(int unit, uint8 **scache_ptr) 
   3034 {
   3035     int value;
   3036     int num_elements;
   3037     int i;
   3038     uint8 load_weight;
   3039 
   3040     /* Recover the following LAG DLB parameters: 
   3041      * int lag_dlb_sample_rate;
   3042      * int lag_dlb_tx_load_min_th;
   3043      * int lag_dlb_tx_load_max_th;
   3044      * int lag_dlb_qsize_min_th;
   3045      * int lag_dlb_qsize_max_th;
   3046      * int lag_dlb_exp_load_min_th;
   3047      * int lag_dlb_exp_load_max_th;
   3048      * int lag_dlb_imbalance_min_th;
   3049      * int lag_dlb_imbalance_max_th;
   3050      */
   3051     sal_memcpy(&value, (*scache_ptr), sizeof(int));
   3052     LAG_DLB_INFO(unit)->lag_dlb_sample_rate = value;
   3053     (*scache_ptr) += sizeof(int);
   3054 
   3055     sal_memcpy(&value, (*scache_ptr), sizeof(int));
   3056     LAG_DLB_INFO(unit)->lag_dlb_tx_load_min_th = value;
   3057     (*scache_ptr) += sizeof(int);
   3058 
   3059     sal_memcpy(&value, (*scache_ptr), sizeof(int));
   3060     LAG_DLB_INFO(unit)->lag_dlb_tx_load_max_th = value;
   3061     (*scache_ptr) += sizeof(int);
   3062 
   3063     sal_memcpy(&value, (*scache_ptr), sizeof(int));
   3064     LAG_DLB_INFO(unit)->lag_dlb_qsize_min_th = value;
   3065     (*scache_ptr) += sizeof(int);
   3066 
   3067     sal_memcpy(&value, (*scache_ptr), sizeof(int));
   3068     LAG_DLB_INFO(unit)->lag_dlb_qsize_max_th = value;
   3069     (*scache_ptr) += sizeof(int);
   3070 
   3071     sal_memcpy(&value, (*scache_ptr), sizeof(int));
   3072     LAG_DLB_INFO(unit)->lag_dlb_exp_load_min_th = value;
   3073     (*scache_ptr) += sizeof(int);
   3074 
   3075     sal_memcpy(&value, (*scache_ptr), sizeof(int));
   3076     LAG_DLB_INFO(unit)->lag_dlb_exp_load_max_th = value;
   3077     (*scache_ptr) += sizeof(int);
   3078 
   3079     sal_memcpy(&value, (*scache_ptr), sizeof(int));
   3080     LAG_DLB_INFO(unit)->lag_dlb_imbalance_min_th = value;
   3081     (*scache_ptr) += sizeof(int);
   3082 
   3083     sal_memcpy(&value, (*scache_ptr), sizeof(int));
   3084     LAG_DLB_INFO(unit)->lag_dlb_imbalance_max_th = value;
   3085     (*scache_ptr) += sizeof(int);
   3086 
   3087     /* Recover lag_dlb_load_weight array */
   3088     num_elements = 1 << soc_mem_field_length(unit,
   3089             DLB_LAG_QUALITY_CONTROLm, PROFILE_PTRf);
   3090     for (i = 0; i < num_elements; i++) {
   3091         sal_memcpy(&load_weight, (*scache_ptr), sizeof(uint8));
   3092         LAG_DLB_INFO(unit)->lag_dlb_load_weight[i] = load_weight;
   3093         (*scache_ptr) += sizeof(uint8);
   3094     }
   3095         
   3096     LAG_DLB_INFO(unit)->recovered_from_scache = TRUE;
   3097 
   3098     return BCM_E_NONE;
   3099 }
   3100 
   3101 /*
   3102  * Function:
   3103  *      bcm_tr3_lag_dlb_member_recover
   3104  * Purpose:
   3105  *      Recover LAG DLB member ID usage.
   3106  * Parameters:
   3107  *      unit - (IN) SOC unit number.
   3108  * Returns:
   3109  *      BCM_E_XXX
   3110  */
   3111 int
   3112 bcm_tr3_lag_dlb_member_recover(int unit) 
   3113 {
   3114     int rv = BCM_E_NONE;
   3115     int member_bitmap_width;
   3116     int alloc_size;
   3117     SHR_BITDCL *member_bitmap = NULL;
   3118     int dlb_id;
   3119     int i;
   3120     dlb_lag_group_membership_entry_t group_membership_entry;
   3121 
   3122     member_bitmap_width = soc_mem_field_length(unit,
   3123             DLB_LAG_GROUP_MEMBERSHIPm, MEMBER_BITMAPf);
   3124     alloc_size = SHR_BITALLOCSIZE(member_bitmap_width);
   3125     member_bitmap = sal_alloc(alloc_size, "DLB LAG member bitmap"); 
   3126     if (NULL == member_bitmap) {
   3127         return BCM_E_MEMORY;
   3128     }
   3129 
   3130     for (dlb_id = 0;
   3131             dlb_id < soc_mem_index_count(unit, DLB_LAG_GROUP_MEMBERSHIPm);
   3132             dlb_id++) {
   3133         rv = READ_DLB_LAG_GROUP_MEMBERSHIPm(unit, MEM_BLOCK_ANY,
   3134                 dlb_id, &group_membership_entry);
   3135         if (SOC_FAILURE(rv)) {
   3136             sal_free(member_bitmap);
   3137             return rv;
   3138         }
   3139         sal_memset(member_bitmap, 0, alloc_size);
   3140         soc_DLB_LAG_GROUP_MEMBERSHIPm_field_get(unit,
   3141                 &group_membership_entry, MEMBER_BITMAPf, member_bitmap);
   3142         for (i = 0; i < member_bitmap_width; i++) {
   3143             if (SHR_BITGET(member_bitmap, i)) {
   3144                 _BCM_LAG_DLB_MEMBER_ID_USED_SET(unit, i);
   3145             }
   3146         }
   3147     }
   3148 
   3149     sal_free(member_bitmap);
   3150 
   3151     return BCM_E_NONE;
   3152 }
   3153 
   3154 /*
   3155  * Function:
   3156  *      bcm_tr3_lag_dlb_group_recover
   3157  * Purpose:
   3158  *      Recover LAG DLB group usage and flowset table usage.
   3159  * Parameters:
   3160  *      unit - (IN) SOC unit number.
   3161  *      tid  - (IN) Trunk group ID.
   3162  *      trunk_info - (OUT) Per trunk group DLB info.
   3163  * Returns:
   3164  *      BCM_E_XXX
   3165  */
   3166 int
   3167 bcm_tr3_lag_dlb_group_recover(int unit, bcm_trunk_t tid,
   3168         trunk_private_t *trunk_info) 
   3169 {
   3170     trunk_group_entry_t tg_entry;
   3171     int group_enable, dlb_id;
   3172     dlb_lag_group_control_entry_t group_control_entry;
   3173     int dlb_mode;
   3174     int dynamic_size_encode, dynamic_size;
   3175     int entry_base_ptr;
   3176     int block_base_ptr, num_blocks;
   3177     dlb_lag_vla_quality_measure_control_entry_t vla_quality_measure_control_entry;
   3178 
   3179     SOC_IF_ERROR_RETURN
   3180         (READ_TRUNK_GROUPm(unit, MEM_BLOCK_ANY, tid, &tg_entry));
   3181     group_enable = soc_TRUNK_GROUPm_field32_get(unit, &tg_entry,
   3182             GROUP_ENABLEf);
   3183     if (0 == group_enable) {
   3184         /* DLB not enabled */
   3185         return BCM_E_NONE;
   3186     }
   3187 
   3188     /* Get DLB group ID and marked it as used */
   3189     dlb_id = soc_TRUNK_GROUPm_field32_get(unit, &tg_entry, DLB_IDf);
   3190     _BCM_LAG_DLB_ID_USED_SET(unit, dlb_id);
   3191 
   3192     SOC_IF_ERROR_RETURN(READ_DLB_LAG_GROUP_CONTROLm(unit,
   3193                 MEM_BLOCK_ANY, dlb_id, &group_control_entry));
   3194 
   3195     /* Recover DLB mode */
   3196     dlb_mode = soc_DLB_LAG_GROUP_CONTROLm_field32_get(unit,
   3197             &group_control_entry, MEMBER_ASSIGNMENT_MODEf);
   3198     switch (dlb_mode) {
   3199         case 0:
   3200             trunk_info->psc = BCM_TRUNK_PSC_DYNAMIC;
   3201             break;
   3202         case 1:
   3203             trunk_info->psc = BCM_TRUNK_PSC_DYNAMIC_ASSIGNED;
   3204             break;
   3205         case 2:
   3206             trunk_info->psc = BCM_TRUNK_PSC_DYNAMIC_OPTIMAL;
   3207             break;
   3208         default:
   3209             return BCM_E_INTERNAL;
   3210     }
   3211 
   3212     /* Recover dynamic_size */
   3213     dynamic_size_encode = soc_DLB_LAG_GROUP_CONTROLm_field32_get(unit,
   3214             &group_control_entry, FLOW_SET_SIZEf);
   3215     BCM_IF_ERROR_RETURN
   3216         (_bcm_tr3_lag_dlb_dynamic_size_decode(dynamic_size_encode,
   3217                                               &dynamic_size));
   3218     trunk_info->dynamic_size = dynamic_size;
   3219 
   3220     /* Recover dynamic_age */
   3221     trunk_info->dynamic_age = soc_DLB_LAG_GROUP_CONTROLm_field32_get(unit,
   3222             &group_control_entry, INACTIVITY_DURATIONf);
   3223 
   3224     /* Recover flow set table usage */
   3225     entry_base_ptr = soc_DLB_LAG_GROUP_CONTROLm_field32_get(unit,
   3226             &group_control_entry, FLOW_SET_BASEf);
   3227     block_base_ptr = entry_base_ptr >> 9;
   3228     num_blocks = dynamic_size >> 9; 
   3229     _BCM_LAG_DLB_FLOWSET_BLOCK_USED_SET_RANGE(unit, block_base_ptr,
   3230             num_blocks);
   3231 
   3232     SOC_IF_ERROR_RETURN(READ_DLB_LAG_VLA_QUALITY_MEASURE_CONTROLm(unit,
   3233                 MEM_BLOCK_ANY, dlb_id, &vla_quality_measure_control_entry));
   3234 
   3235     /* Recover BCM_TRUNK_FLAG_DYNAMIC_LOAD_DECREASE_RESET flag */
   3236     if (soc_DLB_LAG_VLA_QUALITY_MEASURE_CONTROLm_field32_get(unit,
   3237         &vla_quality_measure_control_entry, VLA_CAP_LOADING_AVGf)) {
   3238         trunk_info->flags |= BCM_TRUNK_FLAG_DYNAMIC_LOAD_DECREASE_RESET;
   3239     }
   3240     
   3241     /* Recover BCM_TRUNK_FLAG_DYNAMIC_EXPECTED_LOAD_DECREASE_RESET flag */
   3242     if (soc_DLB_LAG_VLA_QUALITY_MEASURE_CONTROLm_field32_get(unit,
   3243         &vla_quality_measure_control_entry, VLA_CAP_EXPECTED_LOADINGf)) {
   3244         trunk_info->flags |= BCM_TRUNK_FLAG_DYNAMIC_EXPECTED_LOAD_DECREASE_RESET;
   3245     }
   3246 
   3247     /* Recover dynamic_load_exponent */
   3248     trunk_info->dynamic_load_exponent =
   3249         soc_DLB_LAG_VLA_QUALITY_MEASURE_CONTROLm_field32_get(unit,
   3250                 &vla_quality_measure_control_entry, VLA_WEIGHT_LOADINGf);
   3251 
   3252     /* Recover dynamic_expected_load_exponent */
   3253     trunk_info->dynamic_expected_load_exponent =
   3254         soc_DLB_LAG_VLA_QUALITY_MEASURE_CONTROLm_field32_get(unit,
   3255                 &vla_quality_measure_control_entry, VLA_WEIGHT_EXPECTED_LOADINGf);
   3256 
   3257     return BCM_E_NONE;
   3258 }
   3259 
   3260 /*
   3261  * Function:
   3262  *      bcm_tr3_lag_dlb_quality_parameters_recover
   3263  * Purpose:
   3264  *      Recover LAG DLB parameters used to derive a member's quality.
   3265  * Parameters:
   3266  *      unit - (IN) SOC unit number.
   3267  * Returns:
   3268  *      BCM_E_XXX
   3269  */
   3270 int
   3271 bcm_tr3_lag_dlb_quality_parameters_recover(int unit) 
   3272 {
   3273     uint32 measure_control_reg;
   3274     int num_time_units;
   3275     dlb_lag_pla_quantize_threshold_entry_t quantize_threshold_entry;
   3276     int min_th_bytes, min_th_cells;
   3277     int max_th_bytes, max_th_cells;
   3278     dlb_lag_vla_expected_loading_threshold_entry_t expected_loading_threshold_entry;
   3279     int exp_load_min_th_kbytes, exp_load_max_th_kbytes;
   3280     dlb_lag_vla_member_imbalance_threshold_entry_t imbalance_threshold_entry;
   3281     int imbalance_min_th_kbytes, imbalance_max_th_kbytes;
   3282     int entries_per_profile;
   3283     int profile_ptr, base_index;
   3284     dlb_lag_quality_mapping_entry_t quality_mapping_entry;
   3285     int quality;
   3286 
   3287     if (LAG_DLB_INFO(unit)->recovered_from_scache) {
   3288         /* If already recovered from scache, do nothing. */ 
   3289         return BCM_E_NONE;
   3290     }
   3291 
   3292     /* Recover sampling rate */
   3293     SOC_IF_ERROR_RETURN(READ_DLB_LAG_QUALITY_MEASURE_CONTROLr(unit,
   3294                 &measure_control_reg));
   3295     num_time_units = soc_reg_field_get(unit, DLB_LAG_QUALITY_MEASURE_CONTROLr,
   3296             measure_control_reg, HISTORICAL_SAMPLING_PERIODf);
   3297     if (num_time_units > 0) {
   3298         LAG_DLB_INFO(unit)->lag_dlb_sample_rate = 1000000 / num_time_units;
   3299     }
   3300 
   3301     /* Recover min and max load and queue size thresholds: 
   3302      * Load threshold (in mbps)
   3303      *     = (bytes per sampling period) * 8 bits per byte /
   3304      *       (sampling period in seconds) / 10^6
   3305      *     = (bytes per sampling period) * 8 bits per byte /
   3306      *       (num_time_units * 1 us per time unit * 10^-6) / 10^6
   3307      *     = (bytes per sampling period) * 8 / num_time_units 
   3308      */ 
   3309     SOC_IF_ERROR_RETURN(READ_DLB_LAG_PLA_QUANTIZE_THRESHOLDm(unit,
   3310                 MEM_BLOCK_ANY, 0, &quantize_threshold_entry));
   3311     min_th_bytes = soc_DLB_LAG_PLA_QUANTIZE_THRESHOLDm_field32_get
   3312         (unit, &quantize_threshold_entry, THRESHOLD_HIST_LOADf); 
   3313     LAG_DLB_INFO(unit)->lag_dlb_tx_load_min_th = (min_th_bytes << 3) /
   3314         num_time_units;
   3315     min_th_cells = soc_DLB_LAG_PLA_QUANTIZE_THRESHOLDm_field32_get
   3316         (unit, &quantize_threshold_entry, THRESHOLD_HIST_QSIZEf); 
   3317     LAG_DLB_INFO(unit)->lag_dlb_qsize_min_th = min_th_cells * 208;
   3318 
   3319     SOC_IF_ERROR_RETURN(READ_DLB_LAG_PLA_QUANTIZE_THRESHOLDm(unit,
   3320                 MEM_BLOCK_ANY, soc_mem_index_max(unit,
   3321                     DLB_LAG_PLA_QUANTIZE_THRESHOLDm),
   3322                 &quantize_threshold_entry));
   3323     max_th_bytes = soc_DLB_LAG_PLA_QUANTIZE_THRESHOLDm_field32_get
   3324         (unit, &quantize_threshold_entry, THRESHOLD_HIST_LOADf); 
   3325     LAG_DLB_INFO(unit)->lag_dlb_tx_load_max_th = (max_th_bytes << 3) /
   3326         num_time_units;
   3327     max_th_cells = soc_DLB_LAG_PLA_QUANTIZE_THRESHOLDm_field32_get
   3328         (unit, &quantize_threshold_entry, THRESHOLD_HIST_QSIZEf); 
   3329     LAG_DLB_INFO(unit)->lag_dlb_qsize_max_th = max_th_cells * 208;
   3330 
   3331     /* Recover min and max expected load thresholds: 
   3332      * Load threshold (in mbps)
   3333      *     = (bytes per sampling period) * 8 bits per byte /
   3334      *       (sampling period in seconds) / 10^6
   3335      *     = (bytes per sampling period) * 8 bits per byte /
   3336      *       (num_time_units * 1 us per time unit * 10^-6) / 10^6
   3337      *     = (bytes per sampling period) * 8 / num_time_units 
   3338      *     = (kilobytes per sampling period) * 8000 / num_time_units 
   3339      */ 
   3340     SOC_IF_ERROR_RETURN(READ_DLB_LAG_VLA_EXPECTED_LOADING_THRESHOLDm(unit,
   3341                 MEM_BLOCK_ANY, 0, &expected_loading_threshold_entry));
   3342     exp_load_min_th_kbytes =
   3343         soc_DLB_LAG_VLA_EXPECTED_LOADING_THRESHOLDm_field32_get
   3344         (unit, &expected_loading_threshold_entry, THRESHOLDf); 
   3345     LAG_DLB_INFO(unit)->lag_dlb_exp_load_min_th =
   3346         (exp_load_min_th_kbytes << 3) * 1000 / num_time_units;
   3347 
   3348     SOC_IF_ERROR_RETURN(READ_DLB_LAG_VLA_EXPECTED_LOADING_THRESHOLDm(unit,
   3349                 MEM_BLOCK_ANY, 14, &expected_loading_threshold_entry));
   3350     exp_load_max_th_kbytes =
   3351         soc_DLB_LAG_VLA_EXPECTED_LOADING_THRESHOLDm_field32_get
   3352         (unit, &expected_loading_threshold_entry, THRESHOLDf); 
   3353     LAG_DLB_INFO(unit)->lag_dlb_exp_load_max_th =
   3354         (exp_load_max_th_kbytes << 3) * 1000 / num_time_units;
   3355 
   3356     /* Recover min and max imbalance thresholds: 
   3357      * Imbalance threshold (in percentage)
   3358      *     = (imbalance threshold in kbytes) / 
   3359      *       (expected load threshold in kbytes) * 100
   3360      */
   3361     SOC_IF_ERROR_RETURN(READ_DLB_LAG_VLA_MEMBER_IMBALANCE_THRESHOLDm(unit,
   3362                 MEM_BLOCK_ANY, 14, &imbalance_threshold_entry));
   3363     imbalance_min_th_kbytes =
   3364         soc_DLB_LAG_VLA_MEMBER_IMBALANCE_THRESHOLDm_field32_get
   3365         (unit, &imbalance_threshold_entry, THRESHOLD_0f); 
   3366     if ((imbalance_min_th_kbytes >> 20) & 0x1) {
   3367         /* Imbalance threshold is negative. Take absolute value. */
   3368         imbalance_min_th_kbytes = ((~imbalance_min_th_kbytes) + 1) & 0x1fffff; 
   3369         LAG_DLB_INFO(unit)->lag_dlb_imbalance_min_th =
   3370             imbalance_min_th_kbytes * 100 / (exp_load_max_th_kbytes) * -1;
   3371     } else {
   3372         LAG_DLB_INFO(unit)->lag_dlb_imbalance_min_th =
   3373             imbalance_min_th_kbytes * 100 / (exp_load_max_th_kbytes);
   3374     }
   3375 
   3376     imbalance_max_th_kbytes =
   3377         soc_DLB_LAG_VLA_MEMBER_IMBALANCE_THRESHOLDm_field32_get
   3378         (unit, &imbalance_threshold_entry, THRESHOLD_6f); 
   3379     if ((imbalance_max_th_kbytes >> 20) & 0x1) {
   3380         /* Imbalance threshold is negative. Take absolute value. */
   3381         imbalance_max_th_kbytes = ((~imbalance_max_th_kbytes) + 1) & 0x1fffff; 
   3382         LAG_DLB_INFO(unit)->lag_dlb_imbalance_max_th =
   3383             imbalance_max_th_kbytes * 100 / (exp_load_max_th_kbytes) * -1;
   3384     } else {
   3385         LAG_DLB_INFO(unit)->lag_dlb_imbalance_max_th =
   3386             imbalance_max_th_kbytes * 100 / (exp_load_max_th_kbytes);
   3387     }
   3388 
   3389     /* Recover load weights */
   3390     entries_per_profile = 64;
   3391     for (profile_ptr = 0; profile_ptr < (1 << soc_mem_field_length(unit,
   3392                     DLB_LAG_QUALITY_CONTROLm, PROFILE_PTRf)); profile_ptr++) {
   3393         base_index = profile_ptr * entries_per_profile;
   3394         /* quality = (quantized_tx_load * tx_load_percent +
   3395          *            quantized_qsize * (100 - tx_load_percent)) /
   3396          *           100;
   3397          * quality = ((quantized_tx_load - quantized_qsize) *
   3398          *            tx_load_percent + quantized_qsize * 100) /
   3399          *           100;
   3400          * quality = (quantized_tx_load - quantized_qsize) *
   3401          *           tx_load_percent / 100 + quantized_qsize;
   3402          * tx_load_percent = (quality - quantized_qsize) * 100 /
   3403          *                   (quantized_tx_load - quantized_qsize); 
   3404          *
   3405          * The index to DLB_LAG_QUALITY_MAPPING table consists of
   3406          * base_index + quantized_tx_load * 8 + quantized_qsize,
   3407          * where quantized_tx_load and quantized_qsize range from
   3408          * 0 to 7.
   3409          *
   3410          * With quantized_tx_load = 7 and quantized_qsize = 0, the 
   3411          * index to DLB_LAG_QUALITY_MAPPING table is
   3412          * base_index + 56, and the tx_load_percent expression
   3413          * simplifies to quality * 100 / 7;
   3414          */
   3415         BCM_IF_ERROR_RETURN(READ_DLB_LAG_QUALITY_MAPPINGm(unit,
   3416                     MEM_BLOCK_ANY, base_index + 56,
   3417                     &quality_mapping_entry));
   3418         quality = soc_DLB_LAG_QUALITY_MAPPINGm_field32_get(unit,
   3419                 &quality_mapping_entry, QUALITYf);
   3420         LAG_DLB_INFO(unit)->lag_dlb_load_weight[profile_ptr] =
   3421             quality * 100 / 7;
   3422     }
   3423 
   3424     return BCM_E_NONE;
   3425 }
   3426 
   3427 #endif /* BCM_WARM_BOOT_SUPPORT */
   3428 
   3429 #ifndef BCM_SW_STATE_DUMP_DISABLE
   3430 
   3431 /*
   3432  * Function:
   3433  *     bcm_tr3_lag_dlb_sw_dump
   3434  * Purpose:
   3435  *     Displays LAG DLB information maintained by software.
   3436  * Parameters:
   3437  *     unit - Device unit number
   3438  * Returns:
   3439  *     None
   3440  */
   3441 void
   3442 bcm_tr3_lag_dlb_sw_dump(int unit)
   3443 {
   3444     int i;
   3445     int num_entries_per_profile;
   3446     int num_profiles;
   3447     int rv;
   3448     int ref_count;
   3449 
   3450     LOG_CLI((BSL_META_U(unit,
   3451                         "LAG DLB Info -\n")));
   3452 
   3453     /* Print LAG DLB group usage */
   3454     LOG_CLI((BSL_META_U(unit,
   3455                         "    LAG DLB Groups Used:")));
   3456     for (i = 0; i < soc_mem_index_count(unit, DLB_LAG_GROUP_CONTROLm); i++) {
   3457         if (_BCM_LAG_DLB_ID_USED_GET(unit, i)) {
   3458             LOG_CLI((BSL_META_U(unit,
   3459                                 " %d"), i));
   3460         }
   3461     }
   3462     LOG_CLI((BSL_META_U(unit,
   3463                         "\n")));
   3464 
   3465     /* Print LAG DLB flowset table usage */
   3466     LOG_CLI((BSL_META_U(unit,
   3467                         "    LAG DLB Flowset Table Blocks Used:")));
   3468     for (i = 0; i < soc_mem_index_count(unit, DLB_LAG_FLOWSETm) >> 9; i++) {
   3469         if (_BCM_LAG_DLB_FLOWSET_BLOCK_USED_GET(unit, i)) {
   3470             LOG_CLI((BSL_META_U(unit,
   3471                                 " %d"), i));
   3472         }
   3473     }
   3474     LOG_CLI((BSL_META_U(unit,
   3475                         "\n")));
   3476 
   3477     /* Print LAG DLB member ID usage */
   3478     LOG_CLI((BSL_META_U(unit,
   3479                         "    LAG DLB Member IDs Used:")));
   3480     for (i = 0; i < soc_mem_index_count(unit, DLB_LAG_MEMBER_ATTRIBUTEm); i++) {
   3481         if (_BCM_LAG_DLB_MEMBER_ID_USED_GET(unit, i)) {
   3482             LOG_CLI((BSL_META_U(unit,
   3483                                 " %d"), i));
   3484         }
   3485     }
   3486     LOG_CLI((BSL_META_U(unit,
   3487                         "\n")));
   3488 
   3489     /* Print sample rate and threshold parameters */
   3490     LOG_CLI((BSL_META_U(unit,
   3491                         "    Sample rate: %d per second\n"),
   3492              LAG_DLB_INFO(unit)->lag_dlb_sample_rate));
   3493     LOG_CLI((BSL_META_U(unit,
   3494                         "    Tx load min threshold: %d mbps\n"),
   3495              LAG_DLB_INFO(unit)->lag_dlb_tx_load_min_th));
   3496     LOG_CLI((BSL_META_U(unit,
   3497                         "    Tx load max threshold: %d mbps\n"),
   3498              LAG_DLB_INFO(unit)->lag_dlb_tx_load_max_th));
   3499     LOG_CLI((BSL_META_U(unit,
   3500                         "    Queue size min threshold: %d cells\n"),
   3501              LAG_DLB_INFO(unit)->lag_dlb_qsize_min_th));
   3502     LOG_CLI((BSL_META_U(unit,
   3503                         "    Queue size max threshold: %d cells\n"),
   3504              LAG_DLB_INFO(unit)->lag_dlb_qsize_max_th));
   3505     LOG_CLI((BSL_META_U(unit,
   3506                         "    Expected load min threshold: %d mbps\n"),
   3507              LAG_DLB_INFO(unit)->lag_dlb_exp_load_min_th));
   3508     LOG_CLI((BSL_META_U(unit,
   3509                         "    Expected load max threshold: %d mbps\n"),
   3510              LAG_DLB_INFO(unit)->lag_dlb_exp_load_max_th));
   3511     LOG_CLI((BSL_META_U(unit,
   3512                         "    Imbalance min threshold: %d percent\n"),
   3513              LAG_DLB_INFO(unit)->lag_dlb_imbalance_min_th));
   3514     LOG_CLI((BSL_META_U(unit,
   3515                         "    Imbalance max threshold: %d percent\n"),
   3516              LAG_DLB_INFO(unit)->lag_dlb_imbalance_max_th));
   3517 
   3518     /* Print quality mapping profiles */
   3519     LOG_CLI((BSL_META_U(unit,
   3520                         "    Quality mapping profiles:\n")));
   3521     num_entries_per_profile = 64;
   3522     num_profiles = soc_mem_index_count(unit, DLB_LAG_QUALITY_MAPPINGm) /
   3523         num_entries_per_profile;
   3524     for (i = 0; i < num_profiles; i++) {
   3525         LOG_CLI((BSL_META_U(unit,
   3526                             "      Profile %d: load weight %d percent, "),
   3527                  i, LAG_DLB_INFO(unit)->lag_dlb_load_weight[i]));
   3528         rv = soc_profile_mem_ref_count_get(unit, 
   3529                 LAG_DLB_INFO(unit)->lag_dlb_quality_map_profile,
   3530                 i * num_entries_per_profile, &ref_count);
   3531         if (SOC_FAILURE(rv)) {
   3532             LOG_CLI((BSL_META_U(unit,
   3533                                 "\n")));
   3534             continue;
   3535         }
   3536         LOG_CLI((BSL_META_U(unit,
   3537                             "ref count %d\n"), ref_count));
   3538     }
   3539 
   3540     return;
   3541 }
   3542 
   3543 #endif /* BCM_SW_STATE_DUMP_DISABLE */
   3544 
   3545 
   3546 #endif /* BCM_TRIUMPH3_SUPPORT */