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

l2x.c (78760B)


      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  * XGS TR3 L2 Table Manipulation API routines.
      8  *
      9  * A low-level L2 shadow table is optionally kept in soc->arlShadow by
     10  * using a callback to get all inserts/deletes from the l2xmsg task.  It
     11  * can be disabled by setting the l2xmsg_avl property to 0.
     12  */
     13 
     14 #include <sal/core/libc.h>
     15 #include <shared/bsl.h>
     16 #include <soc/drv.h>
     17 #include <soc/l2x.h>
     18 #include <soc/ptable.h>
     19 #include <soc/debug.h>
     20 #include <soc/util.h>
     21 #include <soc/mem.h>
     22 #include <soc/ism_hash.h>
     23 #include <soc/triumph3.h>
     24 #include <soc/tcam/tcamtype1.h>
     25 #include <soc/er_tcam.h>
     26 
     27 #ifdef BCM_XGS_SWITCH_SUPPORT
     28 
     29 #define _SOC_ALL_L2X_MEM_LOCK(unit) \
     30         SOC_L2X_MEM_LOCK(unit); \
     31         if (soc_feature(unit, soc_feature_esm_support)) { \
     32             SOC_EXT_L2X_MEM_LOCK(unit); \
     33         }
     34 
     35 #define _SOC_ALL_L2X_MEM_UNLOCK(unit) \
     36         SOC_L2X_MEM_UNLOCK(unit); \
     37         if (soc_feature(unit, soc_feature_esm_support)) { \
     38             SOC_EXT_L2X_MEM_UNLOCK(unit); \
     39         }
     40 
     41 #define _SOC_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv) \
     42         if (!SOC_SUCCESS(rv)) { \
     43             SOC_L2X_MEM_UNLOCK(unit); \
     44             if (soc_feature(unit, soc_feature_esm_support)) { \
     45                 SOC_EXT_L2X_MEM_UNLOCK(unit); \
     46             } \
     47             LOG_ERROR(BSL_LS_SOC_L2, \
     48                       (BSL_META_U(unit, \
     49                                   "rv: %d\n"), rv)); \
     50             return rv; \
     51         }
     52 
     53 #define _SOC_IF_ERROR_ALL_L2X_UNLOCK_JUMP(rv, label) \
     54         if (!SOC_SUCCESS(rv)) { \
     55             SOC_L2X_MEM_UNLOCK(unit); \
     56             if (soc_feature(unit, soc_feature_esm_support)) { \
     57                 SOC_EXT_L2X_MEM_UNLOCK(unit); \
     58             } \
     59             LOG_ERROR(BSL_LS_SOC_L2, \
     60                       (BSL_META_U(unit, \
     61                                   "rv: %d\n"), rv)); \
     62             goto label; \
     63         }
     64 
     65 /*
     66  * While the L2 table is frozen, the L2Xm lock is held.
     67  *
     68  * All tasks must obtain the L2Xm lock before modifying the CML bits or
     69  * age timer registers.
     70  */
     71 
     72 typedef struct l2_freeze_s {
     73     int frozen;
     74     int save_age_sec;
     75     int save_age_ena;
     76 } l2_freeze_t;
     77 
     78 typedef enum {
     79     _SOC_AGE_DEFAULT,
     80     _SOC_AGE_ON_HITSA_ONLY
     81 } _soc_age_criteria_t;
     82 
     83 typedef enum {
     84     RETRY_DEFAULT,
     85     RETRY_DELETE,
     86     RETRY_AGE
     87 } retry_action;
     88 
     89 
     90 l2_freeze_t tr3_l2_freeze_state[SOC_MAX_NUM_DEVICES];
     91 
     92 #define _SOC_TR3_L2_TABLE_DMA_CHUNK_SIZE 1024
     93 #define _SOC_TR3_VALID_MAX_AGE_INTERVAL  (2147)
     94 #define _SOC_TR3_L2AGE_USEC_IN_ONESEC    (1000000)
     95 
     96 /*
     97  * Function:
     98  *	soc_tr3_l2_entry_compare_key
     99  * Purpose:
    100  *	Comparison function for AVL shadow table operations.  Compares
    101  *	key portion of entry only.
    102  * Parameters:
    103  *	user_data - used to pass StrataSwitch unit #
    104  *	datum1 - first L2X entry to compare
    105  *	datum2 - second L2X entry to compare
    106  * Returns:
    107  *	datum1 <=> datum2
    108  */
    109 
    110 int
    111 soc_tr3_l2_entry_compare_key(void *user_data,
    112                              shr_avl_datum_t *datum1,
    113                              shr_avl_datum_t *datum2)
    114 {
    115     int		unit = PTR_TO_INT(user_data);
    116 
    117     return _soc_mem_cmp_tr3_l2x(unit, (void *)datum1, (void *)datum2);
    118 }
    119 
    120 int
    121 soc_tr3_ext_l2_entry_compare_key(void *user_data,
    122                                  shr_avl_datum_t *datum1,
    123                                  shr_avl_datum_t *datum2)
    124 {
    125     int		unit = PTR_TO_INT(user_data);
    126 
    127     return _soc_mem_cmp_tr3_ext_l2x(unit, (void *)datum1, (void *)datum2);
    128 }
    129 
    130 /*
    131  * Function:
    132  *	soc_tr3_l2_entry_dump
    133  * Purpose:
    134  *	Debug dump function for AVL shadow table operations.
    135  * Parameters:
    136  *	user_data - used to pass StrataSwitch unit #
    137  *	datum - L2X entry to dump
    138  *	extra_data - unused
    139  * Returns:
    140  *	SOC_E_XXX
    141  */
    142 
    143 int
    144 soc_tr3_l2_entry_dump(void *user_data, shr_avl_datum_t *datum, void *extra_data)
    145 {
    146     uint32 val;
    147     int	unit = PTR_TO_INT(user_data);
    148     soc_mem_t mem_type = L2_ENTRY_1m;
    149 
    150     COMPILER_REFERENCE(extra_data);
    151 
    152     val = soc_mem_field32_get(unit, L2_ENTRY_1m, (l2_entry_1_entry_t *)datum, KEY_TYPEf);
    153     if ((val == SOC_MEM_KEY_L2_ENTRY_2_L2_BRIDGE) || 
    154         (val == SOC_MEM_KEY_L2_ENTRY_2_L2_VFI) ||
    155         (val == SOC_MEM_KEY_L2_ENTRY_2_L2_TRILL_NONUC_ACCESS)) {
    156         mem_type = L2_ENTRY_2m;
    157     }
    158     
    159     if (mem_type == L2_ENTRY_1m) {
    160         soc_mem_entry_dump(unit, L2_ENTRY_1m, (l2x_entry_t *)datum, BSL_LSS_CLI);
    161     } else {
    162         soc_mem_entry_dump(unit, L2_ENTRY_2m, (l2x_entry_t *)datum, BSL_LSS_CLI);
    163     }
    164     LOG_CLI((BSL_META_U(unit,
    165                         "\n")));
    166 
    167     return SOC_E_NONE;
    168 }
    169 
    170 int
    171 soc_tr3_ext_l2_1_entry_dump(void *user_data, shr_avl_datum_t *datum, void *extra_data)
    172 {
    173     int	unit = PTR_TO_INT(user_data);
    174 
    175     COMPILER_REFERENCE(extra_data);
    176 
    177     soc_mem_entry_dump(unit, EXT_L2_ENTRY_1m, (l2x_entry_t *)datum, BSL_LSS_CLI);
    178     LOG_CLI((BSL_META_U(unit,
    179                         "\n")));
    180 
    181     return SOC_E_NONE;
    182 }
    183 
    184 int
    185 soc_tr3_ext_l2_2_entry_dump(void *user_data, shr_avl_datum_t *datum, void *extra_data)
    186 {
    187     int	unit = PTR_TO_INT(user_data);
    188 
    189     COMPILER_REFERENCE(extra_data);
    190 
    191     soc_mem_entry_dump(unit, EXT_L2_ENTRY_2m, (l2x_entry_t *)datum, BSL_LSS_CLI);
    192     LOG_CLI((BSL_META_U(unit,
    193                         "\n")));
    194 
    195     return SOC_E_NONE;
    196 }
    197 
    198 /*
    199  * Function:
    200  *	soc_tr3_l2_shadow_callback
    201  * Purpose:
    202  *	Internal callback routine for updating an AVL tree shadow table
    203  * Parameters:
    204  *	unit - StrataSwitch unit number.
    205  *	entry_del - Entry to be deleted or updated, NULL if none.
    206  *	entry_add - Entry to be inserted or updated, NULL if none.
    207  *	fn_data - unused.
    208  * Notes:
    209  *	Used only if L2X shadow table is enabled.
    210  */
    211 
    212 STATIC void
    213 soc_tr3_l2_shadow_callback(int unit, uint32 flags, soc_mem_t mem,
    214                            l2_combo_entry_t *entry_del,
    215                            l2_combo_entry_t *entry_add,
    216                            void *fn_data)
    217 {
    218     soc_control_t	*soc = SOC_CONTROL(unit);
    219 
    220     sal_mutex_take(soc->arlShadowMutex, sal_mutex_FOREVER);
    221     if ((mem == L2_ENTRY_1m) || (mem == L2_ENTRY_2m)) {
    222         if (entry_del != NULL) {
    223             shr_avl_delete(soc->arlShadow, soc_tr3_l2_entry_compare_key,
    224                            (shr_avl_datum_t *)entry_del);
    225         }
    226         if (entry_add != NULL) {
    227             shr_avl_insert(soc->arlShadow, soc_tr3_l2_entry_compare_key,
    228                            (shr_avl_datum_t *)entry_add);
    229         }
    230     } else if (soc_feature(unit, soc_feature_esm_support)) {
    231         if (mem == EXT_L2_ENTRY_1m) {
    232             if (entry_del != NULL) {
    233                 shr_avl_delete(soc->arlShadow_ext1, soc_tr3_ext_l2_entry_compare_key,
    234                                (shr_avl_datum_t *)entry_del);
    235             }
    236             if (entry_add != NULL) {
    237                 shr_avl_insert(soc->arlShadow_ext1, soc_tr3_ext_l2_entry_compare_key,
    238                                (shr_avl_datum_t *)entry_add);
    239             }
    240         } else if (mem == EXT_L2_ENTRY_2m) {
    241             if (entry_del != NULL) {
    242                 shr_avl_delete(soc->arlShadow_ext2, soc_tr3_ext_l2_entry_compare_key,
    243                                (shr_avl_datum_t *)entry_del);
    244             }
    245             if (entry_add != NULL) {
    246                 shr_avl_insert(soc->arlShadow_ext2, soc_tr3_ext_l2_entry_compare_key,
    247                                (shr_avl_datum_t *)entry_add);
    248             }
    249         }
    250     }
    251     sal_mutex_give(soc->arlShadowMutex);
    252 }
    253 
    254 /*
    255  * Function:
    256  *	soc_tr3_l2_detach
    257  * Purpose:
    258  *	Deallocate L2X subsystem resources
    259  * Parameters:
    260  *	unit - StrataSwitch unit number.
    261  * Returns:
    262  *	SOC_E_XXX
    263  */
    264 
    265 int
    266 soc_tr3_l2_detach(int unit)
    267 {
    268     soc_control_t *soc = SOC_CONTROL(unit);
    269 
    270     soc_l2_entry_unregister(unit, soc_tr3_l2_shadow_callback, NULL);
    271 
    272     /* Free cml_freeze structure  */
    273     _soc_l2x_cml_struct_free(unit);
    274 
    275     if (soc->arlShadow != NULL) {
    276         shr_avl_destroy(soc->arlShadow);
    277         soc->arlShadow = NULL;
    278     }    
    279     if (soc_feature(unit, soc_feature_esm_support)) {
    280         if (soc->arlShadow_ext1 != NULL) {
    281             shr_avl_destroy(soc->arlShadow_ext1);
    282             soc->arlShadow_ext1 = NULL;
    283         }
    284         if (soc->arlShadow_ext2 != NULL) {
    285             shr_avl_destroy(soc->arlShadow_ext2);
    286             soc->arlShadow_ext2 = NULL;
    287         }
    288     }
    289 
    290     if (soc->arlShadowMutex != NULL) {
    291         sal_mutex_destroy(soc->arlShadowMutex);
    292         soc->arlShadowMutex = NULL;
    293     }
    294 
    295     return SOC_E_NONE;
    296 }
    297 
    298 /*
    299  * Function:
    300  *	soc_tr3_l2_attach
    301  * Purpose:
    302  *	Allocate L2X subsystem resources
    303  * Parameters:
    304  *	unit - StrataSwitch unit number.
    305  * Returns:
    306  *	SOC_E_XXX
    307  * Notes:
    308  *	The L2X tree shadow table is optional and its allocation
    309  *	is controlled using a property.
    310  */
    311 
    312 int
    313 soc_tr3_l2_attach(int unit)
    314 {
    315     soc_control_t	*soc = SOC_CONTROL(unit);
    316     soc_tcam_info_t *tcam_info;
    317     soc_tcam_partition_t *partitions = NULL;
    318     
    319     (void)soc_tr3_l2_detach(unit);
    320 
    321     tcam_info = soc->tcam_info;
    322     if (tcam_info) {
    323         partitions = tcam_info->partitions;
    324     }
    325     if (soc_property_get(unit, spn_L2XMSG_AVL, TRUE)) {
    326         int datum_bytes, datum_max;
    327         
    328         datum_bytes = sizeof(l2_entry_1_entry_t);
    329         datum_max = tcam_info ? partitions[TCAM_PARTITION_FWD_L2].num_entries :
    330                     soc_mem_index_count(unit, L2_ENTRY_1m);
    331         if (shr_avl_create(&soc->arlShadow,
    332                            INT_TO_PTR(unit),
    333                            datum_bytes,
    334                            datum_max) < 0) {
    335             return SOC_E_MEMORY;
    336         }
    337         if (soc_feature(unit, soc_feature_esm_support)) {
    338             datum_bytes = sizeof(ext_l2_entry_1_entry_t);
    339             datum_max = tcam_info ? 
    340                             partitions[TCAM_PARTITION_FWD_L2].num_entries : 
    341                             soc_mem_index_count(unit, EXT_L2_ENTRY_1m);
    342             if (shr_avl_create(&soc->arlShadow_ext1,
    343                                INT_TO_PTR(unit),
    344                                datum_bytes,
    345                                datum_max) < 0) {
    346                 (void)soc_tr3_l2_detach(unit);
    347                 return SOC_E_MEMORY;
    348             }
    349             datum_bytes = sizeof(ext_l2_entry_2_entry_t);
    350             datum_max = tcam_info ? 
    351                         partitions[TCAM_PARTITION_FWD_L2_WIDE].num_entries : 
    352                         soc_mem_index_count(unit, EXT_L2_ENTRY_2m);
    353             if (shr_avl_create(&soc->arlShadow_ext2,
    354                                INT_TO_PTR(unit),
    355                                datum_bytes,
    356                                datum_max) < 0) {
    357                 (void)soc_tr3_l2_detach(unit);
    358                 return SOC_E_MEMORY;
    359             }
    360         }
    361         if ((soc->arlShadowMutex = sal_mutex_create("asMutex")) == NULL) {
    362             (void)soc_tr3_l2_detach(unit);
    363             return SOC_E_MEMORY;
    364         }
    365 
    366         soc_l2_entry_register(unit, soc_tr3_l2_shadow_callback, NULL);
    367     }
    368 
    369     /* Reset l2 freeze structure. */
    370     sal_memset(&tr3_l2_freeze_state[unit], 0, sizeof(l2_freeze_t));
    371 
    372     /* Init cml state */
    373     SOC_IF_ERROR_RETURN(_soc_l2x_cml_struct_alloc(unit));
    374 	
    375     return SOC_E_NONE;
    376 }
    377 
    378 /*
    379  * Function:
    380  *	_soc_tr3_l2_port_age
    381  * Purpose:
    382  *	Use HW port/VLAN "aging" to delete selected L2 entries.
    383  * Parameters:
    384  *	unit	     - StrataSwitch unit #
    385  *      age_reg0     - port aging register.
    386  *	age_reg1     - optioanl 2nd port aging register.
    387  * Returns:
    388  *	SOC_E_XXX
    389  * Notes:
    390  *	Hardware deletion is used.
    391  *	The chip requires that ARL aging be disabled during this
    392  *	operation.  An unavoidable side effect is that the hardware
    393  *	aging timer gets restarted whenever this routine is called.
    394  */
    395 int
    396 soc_tr3_l2_port_age(int unit, soc_reg_t reg0, soc_reg_t reg1)
    397 {
    398     static soc_field_t fields[2] = { STARTf, COMPLETEf };
    399     static uint32      values[2] = { 1, 0 };
    400     soc_timeout_t      to;
    401     int                rv;
    402     int                timeout_usec;
    403     int                reg0_complete, reg1_complete;
    404     uint32             rval;
    405     int                mode;
    406 
    407     if (reg0 == INVALIDr && reg1 == INVALIDr) {
    408         return SOC_E_NONE;
    409     }
    410 
    411     timeout_usec = SOC_CONTROL(unit)->l2x_age_timeout;
    412     mode = SOC_CONTROL(unit)->l2x_mode;
    413 
    414     if (mode != L2MODE_FIFO) {
    415         /* Disable learning etc. */ 
    416         SOC_IF_ERROR_RETURN(_soc_l2x_frozen_cml_save(unit));
    417     }
    418 
    419     reg0_complete = TRUE;
    420     if (reg0 != INVALIDr) {
    421         rv = soc_reg_fields32_modify(unit, reg0, REG_PORT_ANY, 2, fields,
    422                                      values);
    423         if (SOC_FAILURE(rv)) {
    424             goto done;
    425         }
    426         reg0_complete = FALSE;
    427     }
    428 
    429     reg1_complete = TRUE;
    430     if (reg1 != INVALIDr) {
    431         rv = soc_reg_fields32_modify(unit, reg1, REG_PORT_ANY, 2, fields,
    432                                      values);
    433         if (SOC_FAILURE(rv)) {
    434             goto done;
    435         }
    436         reg1_complete = FALSE;
    437     }
    438 
    439     SOC_CONTROL(unit)->l2x_ppa_in_progress = TRUE;
    440     soc_timeout_init(&to, timeout_usec, 0);
    441     for (;;) {
    442         if (!reg0_complete) {
    443             rv = soc_reg32_get(unit, reg0, REG_PORT_ANY, 0, &rval);
    444             if (SOC_SUCCESS(rv)) {
    445                 reg0_complete = soc_reg_field_get(unit, reg0, rval, COMPLETEf);
    446             }
    447         }
    448         if (!reg1_complete) {
    449             rv = soc_reg32_get(unit, reg1, REG_PORT_ANY, 0, &rval);
    450             if (SOC_SUCCESS(rv)) {
    451                 reg1_complete = soc_reg_field_get(unit, reg1, rval, COMPLETEf);
    452             }
    453         }
    454 
    455         if (reg0_complete && reg1_complete) {
    456             rv = SOC_E_NONE;
    457             break;
    458         }
    459 
    460         if (soc_timeout_check(&to)) {
    461             rv = SOC_E_TIMEOUT;
    462             break;
    463         }
    464         sal_usleep(SAL_BOOT_QUICKTURN ? 10000 : 1000);
    465     }
    466 
    467  done:
    468     SOC_CONTROL(unit)->l2x_ppa_in_progress = FALSE;
    469     if (mode != L2MODE_FIFO) {
    470         SOC_IF_ERROR_RETURN(_soc_l2x_frozen_cml_restore(unit));
    471     }
    472     return rv;
    473 }
    474 
    475 /*
    476  * Function:
    477  *	    soc_tr3_l2_is_frozen
    478  * Purpose:
    479  *   	Provides indication if L3 table is in frozen state
    480  * Parameters:
    481  *	   unit - (IN) BCM device number. 
    482  *     frozen - (OUT) TRUE if L2x is frozen, FLASE otherwise 
    483  * Returns:
    484  *	   SOC_E_NONE
    485  * Notes:
    486  *	Does not change the frozen status of L2x table only reads it.
    487  */
    488 
    489 int
    490 soc_tr3_l2_is_frozen(int unit, int *frozen)
    491 {
    492     l2_freeze_t	*f_l2 = &tr3_l2_freeze_state[unit];
    493 
    494     *frozen = (f_l2->frozen > 0) ? TRUE : FALSE ;
    495 
    496     return (SOC_E_NONE);
    497 }
    498 
    499 /*
    500  * Function:
    501  *	    soc_tr3_l2_freeze
    502  * Purpose:
    503  *   	Temporarily quiesce L2 table from all activity (learning, aging)
    504  * Parameters:
    505  *	   unit - (IN) BCM device number. 
    506  * Returns:
    507  *	   SOC_E_XXX
    508  * Notes:
    509  *	Leaves L2Xm locked until corresponding thaw.
    510  *	PORT_TABm is locked in order to lockout bcm_port calls
    511  *	bcm_port calls will callout to soc_arl_frozen_cml_set/get
    512  */
    513 
    514 int
    515 soc_tr3_l2_freeze(int unit)
    516 {
    517     l2_freeze_t *f_l2 = &tr3_l2_freeze_state[unit];
    518     int         rv = SOC_E_NONE;
    519 
    520     /* Check if already frozen. */
    521     SOC_L2X_MEM_LOCK(unit);
    522     if (f_l2->frozen > 0) {
    523         /* Keep count - do nothing. */
    524         f_l2->frozen++;
    525         SOC_L2X_MEM_UNLOCK(unit);
    526         return (SOC_E_NONE);
    527     }
    528     SOC_L2X_MEM_UNLOCK(unit);
    529     /* Disable learning etc. */ 
    530     SOC_IF_ERROR_RETURN(_soc_l2x_frozen_cml_save(unit));
    531 
    532     /*
    533      * Disable learning and aging.
    534      */
    535     /* Read l2 aging interval. */
    536     rv = SOC_FUNCTIONS(unit)->soc_age_timer_get(unit, &f_l2->save_age_sec,
    537                                                 &f_l2->save_age_ena);
    538     if (SOC_FAILURE(rv)) {
    539         _soc_l2x_frozen_cml_restore(unit);
    540         return rv;
    541     }
    542     /* If l2 aging is on - disable it. */
    543     if (f_l2->save_age_ena) {
    544         rv = SOC_FUNCTIONS(unit)->soc_age_timer_set(unit, 
    545                                                     f_l2->save_age_sec, 0);
    546         if (SOC_FAILURE(rv)) {
    547             _soc_l2x_frozen_cml_restore(unit);
    548             return rv;
    549         }
    550     }
    551     SOC_L2X_MEM_LOCK(unit);
    552     /* Increment  l2 frozen indicator. */
    553     f_l2->frozen++;
    554     return (SOC_E_NONE);
    555 }
    556 
    557 
    558 /*
    559  * Function:
    560  *   	soc_tr3_l2_thaw
    561  * Purpose:
    562  *	    Restore normal L2 activity.
    563  * Parameters:
    564  *	    unit - (IN) BCM device number.
    565  * Returns:
    566  *	    SOC_E_XXX
    567  */
    568 
    569 int
    570 soc_tr3_l2_thaw(int unit)
    571 {
    572     l2_freeze_t *f_l2 = &tr3_l2_freeze_state[unit];
    573     int         l2rv, cmlrv;
    574 
    575     /* Sanity check to protect from thaw without freeze. */
    576     if (f_l2->frozen == 0 ) {
    577         assert(0);
    578     }
    579 
    580     /* In case of nested freeze/thaw just decrement reference counter. */
    581     SOC_L2X_MEM_LOCK(unit);
    582     if (f_l2->frozen > 1) {
    583         f_l2->frozen--;
    584         SOC_L2X_MEM_UNLOCK(unit);
    585         return (SOC_E_NONE);
    586     }
    587     SOC_L2X_MEM_UNLOCK(unit);
    588     /*
    589      * Last thaw restore L2 learning and aging.
    590      */
    591     l2rv = SOC_E_NONE;
    592     if (f_l2->save_age_ena) {
    593         l2rv = SOC_FUNCTIONS(unit)->soc_age_timer_set(unit, f_l2->save_age_sec,
    594                                                       1);
    595     }
    596     /* L2 freeze reference counter decrement. */
    597     f_l2->frozen--;
    598     SOC_L2X_MEM_UNLOCK(unit);
    599 
    600     /* Restore port learning mode. */
    601     cmlrv = _soc_l2x_frozen_cml_restore(unit);
    602     if (SOC_FAILURE(l2rv)) {
    603         return l2rv;
    604     }
    605     return cmlrv;
    606 }
    607 
    608 static int _soc_tr3_l2_bulk_age_iter[SOC_MAX_NUM_DEVICES] = {0};
    609 
    610 /*
    611  * Function:
    612  *  _soc_tr3_l2_do_age
    613  * Purpose:
    614  *      set up match criteria and execute bulk
    615  *      operations on l2 table
    616  * Parameters:
    617  *  unit - unit number.
    618  *  flags- to specify match criteria
    619  *  retry_loc-to store the memory if it returns a time_out
    620  * Returns:
    621  *  none
    622  */
    623 
    624 STATIC void
    625 _soc_tr3_l2_do_age(int unit, uint32 flags, int8 *retry_loc) {
    626     uint32 rval;
    627     int field_len, rv;
    628     soc_control_t *soc = SOC_CONTROL(unit);
    629     sal_usecs_t stime, etime;
    630     l2_bulk_entry_t l2_bulk;
    631     l2_entry_1_entry_t l2_entry_1;
    632     l2_entry_2_entry_t l2_entry_2;
    633     ext_l2_entry_1_entry_t ext_l2_entry_1;
    634     ext_l2_entry_2_entry_t ext_l2_entry_2;
    635     int age_on_hitsa_only = flags & _SOC_AGE_ON_HITSA_ONLY;
    636 
    637     stime = sal_time_usecs();
    638 
    639     _SOC_ALL_L2X_MEM_LOCK(unit);
    640     if (soc_mem_index_count(unit, L2_ENTRY_1m) == 0) {
    641         goto skip_age_int_l2;
    642     }
    643     if (*retry_loc > 0) {
    644         goto skip_age_int_l2_1;
    645     }
    646     *retry_loc = 0;
    647     sal_memset(&l2_bulk, 0, sizeof(l2_bulk));
    648     sal_memset(&l2_entry_1, 0, sizeof(l2_entry_1));
    649 
    650     /* First work on L2_ENTRY_1 */
    651     soc_mem_field32_set(unit, L2_ENTRY_1m, &l2_entry_1, VALIDf, 1);
    652     soc_mem_field32_set(unit, L2_ENTRY_1m, &l2_entry_1, WIDEf, 1);
    653 
    654     field_len = soc_mem_field_length(unit, L2_ENTRY_1m, KEY_TYPEf);
    655     soc_mem_field32_set(unit, L2_ENTRY_1m, &l2_entry_1, KEY_TYPEf,
    656                         (1 << field_len) - 1);
    657     soc_mem_field32_set(unit, L2_ENTRY_1m, &l2_entry_1, STATIC_BITf, 1);
    658     if (age_on_hitsa_only) {
    659         soc_mem_field32_set(unit, L2_ENTRY_1m, &l2_entry_1, HITSAf, 1);
    660     }
    661     sal_memcpy(&l2_bulk, &l2_entry_1, sizeof(l2_entry_1));
    662     /* Set match mask */
    663     rv = WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 1, &l2_bulk);
    664     _SOC_IF_ERROR_ALL_L2X_UNLOCK_JUMP(rv, cleanup_exit);
    665     soc_mem_field32_set(unit, L2_ENTRY_1m, &l2_entry_1, WIDEf, 0);
    666     soc_mem_field32_set(unit, L2_ENTRY_1m, &l2_entry_1, KEY_TYPEf,
    667                         SOC_MEM_KEY_L2_ENTRY_1_L2_BRIDGE);
    668     soc_mem_field32_set(unit, L2_ENTRY_1m, &l2_entry_1, STATIC_BITf, 0);
    669     if (age_on_hitsa_only) {
    670         soc_mem_field32_set(unit, L2_ENTRY_1m, &l2_entry_1, HITSAf, 0);
    671     }
    672     sal_memcpy(&l2_bulk, &l2_entry_1, sizeof(l2_entry_1));
    673     /* Set match data */
    674     rv = WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 0, &l2_bulk);
    675     _SOC_IF_ERROR_ALL_L2X_UNLOCK_JUMP(rv, cleanup_exit);
    676     rv = READ_L2_BULK_CONTROLr(unit, &rval);
    677     _SOC_IF_ERROR_ALL_L2X_UNLOCK_JUMP(rv, cleanup_exit);
    678     if (SOC_CONTROL(unit)->l2x_mode == L2MODE_FIFO) {
    679         soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, L2_MOD_FIFO_RECORDf, 1);
    680     } else {
    681         soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, L2_MOD_FIFO_RECORDf, 0);
    682     }
    683     if (age_on_hitsa_only) {
    684         soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ACTIONf, 1);
    685     } else {
    686         soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ACTIONf, 3);
    687     }
    688     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, BURST_ENTRIESf,
    689                       _SOC_TR3_L2_BULK_BURST_MIN);
    690     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ENTRY_WIDTHf, 0);
    691     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, NUM_ENTRIESf,
    692                       soc_mem_index_count(unit, L2_ENTRY_1m));
    693     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, EXTERNAL_L2_ENTRYf, 0);
    694     rv = WRITE_L2_BULK_CONTROLr(unit, rval);
    695     _SOC_IF_ERROR_ALL_L2X_UNLOCK_JUMP(rv, cleanup_exit);
    696     /* Age entries for SOC_MEM_KEY_L2_ENTRY_1_L2_BRIDGE */
    697     rv = soc_tr3_l2_port_age(unit, L2_BULK_CONTROLr, INVALIDr);
    698     if (rv == SOC_E_TIMEOUT) {
    699         goto skip_age_ext_l2_2;
    700     }
    701     _SOC_IF_ERROR_ALL_L2X_UNLOCK_JUMP(rv, cleanup_exit);
    702     soc_mem_field32_set(unit, L2_ENTRY_1m, &l2_entry_1, KEY_TYPEf,
    703                         SOC_MEM_KEY_L2_ENTRY_1_L2_VFI);
    704     sal_memcpy(&l2_bulk, &l2_entry_1, sizeof(l2_entry_1));
    705     /* Set match data */
    706     rv = WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 0, &l2_bulk);
    707     /* Age entries for SOC_MEM_KEY_L2_ENTRY_1_L2_VFI */
    708     rv = soc_tr3_l2_port_age(unit, L2_BULK_CONTROLr, INVALIDr);
    709     if (rv == SOC_E_TIMEOUT) {
    710         goto skip_age_ext_l2_2;
    711     }
    712 
    713     _SOC_IF_ERROR_ALL_L2X_UNLOCK_JUMP(rv, cleanup_exit);
    714     *retry_loc = -1;
    715 
    716 skip_age_int_l2_1:
    717      if (*retry_loc > 1) {
    718          goto skip_age_int_l2;
    719      }
    720      *retry_loc = 1;
    721      sal_memset(&l2_bulk, 0, sizeof(l2_bulk));
    722      sal_memset(&l2_entry_2, 0, sizeof(l2_entry_2));
    723      /* Then work on L2_ENTRY_2 */
    724      soc_mem_field32_set(unit, L2_ENTRY_2m, &l2_entry_2, VALID_0f, 1);
    725      soc_mem_field32_set(unit, L2_ENTRY_2m, &l2_entry_2, VALID_1f, 1);
    726      soc_mem_field32_set(unit, L2_ENTRY_2m, &l2_entry_2, WIDE_0f, 1);
    727      soc_mem_field32_set(unit, L2_ENTRY_2m, &l2_entry_2, WIDE_1f, 1);
    728      field_len = soc_mem_field_length(unit, L2_ENTRY_2m, KEY_TYPE_0f);
    729      soc_mem_field32_set(unit, L2_ENTRY_2m, &l2_entry_2, KEY_TYPE_0f,
    730                          (1 << field_len) - 1);
    731      soc_mem_field32_set(unit, L2_ENTRY_2m, &l2_entry_2, KEY_TYPE_1f,
    732                          (1 << field_len) - 1);
    733      soc_mem_field32_set(unit, L2_ENTRY_2m, &l2_entry_2, STATIC_BIT_0f, 1);
    734      soc_mem_field32_set(unit, L2_ENTRY_2m, &l2_entry_2, STATIC_BIT_1f, 1);
    735      if (age_on_hitsa_only) {
    736          soc_mem_field32_set(unit, L2_ENTRY_2m, &l2_entry_2, HITSAf, 1);
    737      }
    738      sal_memcpy(&l2_bulk, &l2_entry_2, sizeof(l2_entry_2));
    739      /* Set match mask */
    740      rv = WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 1, &l2_bulk);
    741      _SOC_IF_ERROR_ALL_L2X_UNLOCK_JUMP(rv, cleanup_exit);
    742      soc_mem_field32_set(unit, L2_ENTRY_2m, &l2_entry_2, KEY_TYPE_0f,
    743                          SOC_MEM_KEY_L2_ENTRY_2_L2_BRIDGE);
    744      soc_mem_field32_set(unit, L2_ENTRY_2m, &l2_entry_2, KEY_TYPE_1f,
    745                          SOC_MEM_KEY_L2_ENTRY_2_L2_BRIDGE);
    746      soc_mem_field32_set(unit, L2_ENTRY_2m, &l2_entry_2, STATIC_BIT_0f, 0);
    747      soc_mem_field32_set(unit, L2_ENTRY_2m, &l2_entry_2, STATIC_BIT_1f, 0);
    748      if (age_on_hitsa_only) {
    749          soc_mem_field32_set(unit, L2_ENTRY_2m, &l2_entry_2, HITSAf, 0);
    750      }
    751      sal_memcpy(&l2_bulk, &l2_entry_2, sizeof(l2_entry_2));
    752      /* Set match data */
    753      rv = WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 0, &l2_bulk);
    754      _SOC_IF_ERROR_ALL_L2X_UNLOCK_JUMP(rv, cleanup_exit);
    755      rv = READ_L2_BULK_CONTROLr(unit, &rval);
    756      _SOC_IF_ERROR_ALL_L2X_UNLOCK_JUMP(rv, cleanup_exit);
    757      if (SOC_CONTROL(unit)->l2x_mode == L2MODE_FIFO) {
    758          soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, L2_MOD_FIFO_RECORDf, 1);
    759      } else {
    760          soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, L2_MOD_FIFO_RECORDf, 0);
    761      }
    762      if (age_on_hitsa_only) {
    763          soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ACTIONf, 1);
    764      } else {
    765          soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ACTIONf, 3);
    766      }
    767      soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, BURST_ENTRIESf,
    768                        _SOC_TR3_L2_BULK_BURST_MIN);
    769      soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ENTRY_WIDTHf, 1);
    770      soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, NUM_ENTRIESf,
    771                        soc_mem_index_count(unit, L2_ENTRY_2m));
    772      rv = WRITE_L2_BULK_CONTROLr(unit, rval);
    773      _SOC_IF_ERROR_ALL_L2X_UNLOCK_JUMP(rv, cleanup_exit);
    774      /* Age entries for SOC_MEM_KEY_L2_ENTRY_2_L2_BRIDGE */
    775      rv = soc_tr3_l2_port_age(unit, L2_BULK_CONTROLr, INVALIDr);
    776      if (rv == SOC_E_TIMEOUT) {
    777          goto skip_age_ext_l2_2;
    778      }
    779      _SOC_IF_ERROR_ALL_L2X_UNLOCK_JUMP(rv, cleanup_exit);
    780      soc_mem_field32_set(unit, L2_ENTRY_2m, &l2_entry_2, KEY_TYPE_0f,
    781                          SOC_MEM_KEY_L2_ENTRY_2_L2_VFI);
    782      soc_mem_field32_set(unit, L2_ENTRY_2m, &l2_entry_2, KEY_TYPE_1f,
    783                          SOC_MEM_KEY_L2_ENTRY_2_L2_VFI);
    784      sal_memcpy(&l2_bulk, &l2_entry_2, sizeof(l2_entry_2));
    785      /* Set match data */
    786      rv = WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 0, &l2_bulk);
    787      _SOC_IF_ERROR_ALL_L2X_UNLOCK_JUMP(rv, cleanup_exit);
    788      /* Age entries for SOC_MEM_KEY_L2_ENTRY_2_L2_VFI */
    789      rv = soc_tr3_l2_port_age(unit, L2_BULK_CONTROLr, INVALIDr);
    790      if (rv == SOC_E_TIMEOUT) {
    791          goto skip_age_ext_l2_2;
    792      }
    793      _SOC_IF_ERROR_ALL_L2X_UNLOCK_JUMP(rv, cleanup_exit);
    794 
    795      *retry_loc = -1;
    796 
    797 skip_age_int_l2:
    798     if (!soc_feature(unit, soc_feature_esm_support)) {
    799         goto skip_age_ext_l2_2;
    800     }
    801     if (soc_mem_index_count(unit, EXT_L2_ENTRY_1m) == 0) {
    802         goto skip_age_ext_l2_1;
    803     }
    804     if (*retry_loc > 2) {
    805         goto skip_age_ext_l2_1;
    806     }
    807     *retry_loc = 2;
    808     sal_memset(&l2_bulk, 0, sizeof(l2_bulk));
    809     sal_memset(&ext_l2_entry_1, 0, sizeof(ext_l2_entry_1));
    810     /* First work on EXT_L2_ENTRY_1 */
    811     soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &ext_l2_entry_1, FREEf, 1);
    812     soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &ext_l2_entry_1, STATIC_BITf, 1);
    813     if (age_on_hitsa_only) {
    814         soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &ext_l2_entry_1, HITSAf, 1);
    815     }
    816     sal_memcpy(&l2_bulk, &ext_l2_entry_1, sizeof(ext_l2_entry_1));
    817 
    818     /* Set match mask */
    819     rv = WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 1, &l2_bulk);
    820     _SOC_IF_ERROR_ALL_L2X_UNLOCK_JUMP(rv, cleanup_exit);
    821     soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &ext_l2_entry_1, FREEf, 0);
    822     soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &ext_l2_entry_1, STATIC_BITf, 0);
    823     if (age_on_hitsa_only) {
    824         soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &ext_l2_entry_1, HITSAf, 0);
    825     }
    826     sal_memcpy(&l2_bulk, &ext_l2_entry_1, sizeof(ext_l2_entry_1));
    827     /* Set match data */
    828     rv = WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 0, &l2_bulk);
    829     _SOC_IF_ERROR_ALL_L2X_UNLOCK_JUMP(rv, cleanup_exit);
    830     rv = READ_L2_BULK_CONTROLr(unit, &rval);
    831     _SOC_IF_ERROR_ALL_L2X_UNLOCK_JUMP(rv, cleanup_exit);
    832     if (SOC_CONTROL(unit)->l2x_mode == L2MODE_FIFO) {
    833         soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, L2_MOD_FIFO_RECORDf, 1);
    834     } else {
    835         soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, L2_MOD_FIFO_RECORDf, 0);
    836     }
    837     if (age_on_hitsa_only) {
    838         soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ACTIONf, 1);
    839     } else {
    840         soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ACTIONf, 3);
    841     }
    842     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, BURST_ENTRIESf,
    843                       _SOC_TR3_L2_BULK_BURST_MIN);
    844     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ENTRY_WIDTHf, 0);
    845     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, NUM_ENTRIESf,
    846                   SOC_MEM_TR3_EXT_L2_MAX_ENTRIES);
    847     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, EXTERNAL_L2_ENTRYf, 1);
    848     rv = WRITE_L2_BULK_CONTROLr(unit, rval);
    849     _SOC_IF_ERROR_ALL_L2X_UNLOCK_JUMP(rv, cleanup_exit);
    850     /* Age entries */
    851     rv = soc_tr3_l2_port_age(unit, L2_BULK_CONTROLr, INVALIDr);
    852     if (rv == SOC_E_TIMEOUT) {
    853         goto skip_age_ext_l2_2;
    854     }
    855     _SOC_IF_ERROR_ALL_L2X_UNLOCK_JUMP(rv, cleanup_exit);
    856     rv = WRITE_ETU_EXT_L2_BULK_INFOr(unit, 0);
    857     _SOC_IF_ERROR_ALL_L2X_UNLOCK_JUMP(rv, cleanup_exit);
    858     /* Issue dummy op */
    859     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ACTIONf, 0);
    860     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ENTRY_WIDTHf, 0);
    861     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, NUM_ENTRIESf, 1);
    862     rv = WRITE_L2_BULK_CONTROLr(unit, rval);
    863     _SOC_IF_ERROR_ALL_L2X_UNLOCK_JUMP(rv, cleanup_exit);
    864     rv = soc_tr3_l2_port_age(unit, L2_BULK_CONTROLr, INVALIDr);
    865     if (rv == SOC_E_TIMEOUT) {
    866         goto skip_age_ext_l2_2;
    867     }
    868     _SOC_IF_ERROR_ALL_L2X_UNLOCK_JUMP(rv, cleanup_exit);
    869     rv = WRITE_ETU_EXT_L2_BULK_INFOr(unit, 0);
    870     _SOC_IF_ERROR_ALL_L2X_UNLOCK_JUMP(rv, cleanup_exit);
    871 
    872     *retry_loc = -1;
    873 
    874 skip_age_ext_l2_1:
    875     if (soc_mem_index_count(unit, EXT_L2_ENTRY_2m) == 0) {
    876         goto skip_age_ext_l2_2;
    877     }
    878     if (*retry_loc >= 0 && *retry_loc < 3) {
    879         goto skip_age_ext_l2_2;
    880     }
    881     *retry_loc = 3;
    882     sal_memset(&l2_bulk, 0, sizeof(l2_bulk));
    883     sal_memset(&ext_l2_entry_2, 0, sizeof(ext_l2_entry_2));
    884 
    885     /* Then work on EXT_L2_ENTRY_2 */
    886     soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &ext_l2_entry_2, FREEf, 1);
    887     soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &ext_l2_entry_2, STATIC_BITf, 1);
    888     if (age_on_hitsa_only) {
    889         soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &ext_l2_entry_2, HITSAf, 1);
    890     }
    891     sal_memcpy(&l2_bulk, &ext_l2_entry_2, sizeof(ext_l2_entry_2));
    892     /* Set match mask */
    893     rv = WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 1, &l2_bulk);
    894     _SOC_IF_ERROR_ALL_L2X_UNLOCK_JUMP(rv, cleanup_exit);
    895     soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &ext_l2_entry_2, FREEf, 0);
    896     soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &ext_l2_entry_2, STATIC_BITf, 0);
    897     if (age_on_hitsa_only) {
    898         soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &ext_l2_entry_2, HITSAf, 0);
    899     }
    900     sal_memcpy(&l2_bulk, &ext_l2_entry_2, sizeof(ext_l2_entry_2));
    901     /* Set match data */
    902     rv = WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 0, &l2_bulk);
    903     _SOC_IF_ERROR_ALL_L2X_UNLOCK_JUMP(rv, cleanup_exit);
    904     rv = READ_L2_BULK_CONTROLr(unit, &rval);
    905     _SOC_IF_ERROR_ALL_L2X_UNLOCK_JUMP(rv, cleanup_exit);
    906     if (SOC_CONTROL(unit)->l2x_mode == L2MODE_FIFO) {
    907         soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, L2_MOD_FIFO_RECORDf, 1);
    908     } else {
    909         soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, L2_MOD_FIFO_RECORDf, 0);
    910     }
    911     if (age_on_hitsa_only) {
    912         soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ACTIONf, 1);
    913     } else {
    914         soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ACTIONf, 3);
    915     }
    916     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, BURST_ENTRIESf,
    917                       _SOC_TR3_L2_BULK_BURST_MIN);
    918     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ENTRY_WIDTHf, 1);
    919     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, NUM_ENTRIESf,
    920                   SOC_MEM_TR3_EXT_L2_MAX_ENTRIES);
    921     rv = WRITE_L2_BULK_CONTROLr(unit, rval);
    922     _SOC_IF_ERROR_ALL_L2X_UNLOCK_JUMP(rv, cleanup_exit);
    923     /* Age entries */
    924     rv = soc_tr3_l2_port_age(unit, L2_BULK_CONTROLr, INVALIDr);
    925     if (rv == SOC_E_TIMEOUT) {
    926         goto skip_age_ext_l2_2;
    927     }
    928     _SOC_IF_ERROR_ALL_L2X_UNLOCK_JUMP(rv, cleanup_exit);
    929     rv = WRITE_ETU_EXT_L2_BULK_INFOr(unit, 0);
    930     _SOC_IF_ERROR_ALL_L2X_UNLOCK_JUMP(rv, cleanup_exit);
    931     /* Issue dummy op */
    932     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ACTIONf, 0);
    933     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ENTRY_WIDTHf, 0);
    934     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, NUM_ENTRIESf, 1);
    935     rv = WRITE_L2_BULK_CONTROLr(unit, rval);
    936     _SOC_IF_ERROR_ALL_L2X_UNLOCK_JUMP(rv, cleanup_exit);
    937     rv = soc_tr3_l2_port_age(unit, L2_BULK_CONTROLr, INVALIDr);
    938     if (rv == SOC_E_TIMEOUT) {
    939         goto skip_age_ext_l2_2;
    940     }
    941     _SOC_IF_ERROR_ALL_L2X_UNLOCK_JUMP(rv, cleanup_exit);
    942     rv = WRITE_ETU_EXT_L2_BULK_INFOr(unit, 0);
    943     _SOC_IF_ERROR_ALL_L2X_UNLOCK_JUMP(rv, cleanup_exit);
    944 
    945     *retry_loc = -1;
    946 
    947 skip_age_ext_l2_2:
    948     _SOC_ALL_L2X_MEM_UNLOCK(unit);
    949     etime = sal_time_usecs();
    950     LOG_VERBOSE(BSL_LS_SOC_ARL,
    951                 (BSL_META_U(unit,
    952                             "l2_bulk_age_thread: unit=%d: done in %d usec\n"),
    953                  unit, SAL_USECS_SUB(etime, stime)));
    954 
    955     return;
    956 
    957 cleanup_exit:
    958     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    959                 (BSL_META_U(unit,
    960                             "l2_bulk_age_thread: exiting\n")));
    961     (void)sal_sem_take(soc->l2x_age_notify, 1);
    962     soc->l2x_age_pid = SAL_THREAD_ERROR;
    963     sal_thread_exit(0);
    964 }
    965 
    966 /*
    967  * Function:
    968  *  _soc_tr3_l2age_sem_wait
    969  * Purpose:
    970  *  Wait in soc->l2x_age_notify semaphore for specified interval
    971  * Parameters:
    972  *  wait_time -  amount of time to be waited on semaphore
    973  * Returns:
    974  *  usec - time spent in semaphore 
    975  */
    976 
    977 
    978 STATIC
    979 sal_usecs_t _soc_tr3_l2age_sem_wait(void * unit_vp, sal_usecs_t wait_time)
    980 {
    981     int unit = PTR_TO_INT(unit_vp);
    982     soc_control_t *soc = SOC_CONTROL(unit);
    983     sal_usecs_t timebefore_agewait = 0, timeafter_agewait = 0, retval = 0;
    984 
    985     timebefore_agewait  = sal_time_usecs();
    986     (void)sal_sem_take(soc->l2x_age_notify, wait_time);
    987     timeafter_agewait = sal_time_usecs();
    988     if (timeafter_agewait > timebefore_agewait) {
    989         retval = timeafter_agewait - timebefore_agewait;
    990     }
    991     else {
    992         retval = ((0xFFFFFFFF - timebefore_agewait) + timeafter_agewait);
    993     }
    994 
    995     return (retval);
    996 }
    997 
    998 
    999 /*
   1000  * Function:
   1001  *  _soc_tr3_l2_bulk_age
   1002  * Purpose:
   1003  *      l2 bulk age thread
   1004  * Parameters:
   1005  *  unit - unit number.
   1006  * Returns:
   1007  *  none
   1008  */
   1009 STATIC void
   1010 _soc_tr3_l2_bulk_age(void *unit_vp)
   1011 {
   1012     int unit = PTR_TO_INT(unit_vp);
   1013     int c, m, r, iter = 0;
   1014     uint32 flags = 0;
   1015     soc_control_t *soc = SOC_CONTROL(unit);
   1016     sal_usecs_t interval;
   1017     sal_usecs_t timebefore_agewait = 0, timeafter_agewait = 0;
   1018     sal_usecs_t actual_wait_time= 0, wait_interval = 0;
   1019     int skip_tr3_l2age_semops = 0;
   1020     int8 retry_loc = -1;  /* To store the memory if bulk action times out */
   1021 
   1022     /* In case a bulk operation times out, we need to store which action timed
   1023        out in order to retry. This variable stores the failed action -
   1024        age or delete. If action succeds this variable is again set back to
   1025        RETRY_DEFAULT */
   1026     int retry_action = RETRY_DEFAULT;
   1027 
   1028     timebefore_agewait  = sal_time_usecs();
   1029     while((interval = soc->l2x_age_interval) != 0) {
   1030         if (!iter) {
   1031             goto age_delay;
   1032         }
   1033 
   1034 run_tr3_l2bulkage_ops:
   1035         LOG_VERBOSE(BSL_LS_SOC_ARL,
   1036                     (BSL_META_U(unit,
   1037                                 "l2_bulk_age_thread: "
   1038                                 "Process iters(total:%d, this run:%d\n"),
   1039                      ++_soc_tr3_l2_bulk_age_iter[unit], iter));
   1040 
   1041         timebefore_agewait  = sal_time_usecs();
   1042         soc->l2x_agetime_adjust_usec = 0;
   1043         soc->l2x_agetime_curr_timeblk = 0;
   1044         soc->l2x_agetime_curr_timeblk_usec = 0;
   1045 
   1046 
   1047     /* If aging should be based on HITSA only, we need to delete all entries
   1048        HITSA = 0 and HITDA = 1 first, and then perform an age action. Age action
   1049        deletes entries with HITSA = 0 and HITDA = 0, and clears all hit bits */
   1050     if (soc->l2x_age_hitsa_only) {
   1051         flags |= _SOC_AGE_ON_HITSA_ONLY;
   1052         if (retry_action == RETRY_DEFAULT || retry_action == RETRY_DELETE) {
   1053             _soc_tr3_l2_do_age(unit, flags, &retry_loc);
   1054 
   1055             if (retry_loc != -1) {
   1056                 /* Bulk delete failed. Need to retry this action */
   1057                 retry_action = RETRY_DELETE;
   1058                 goto age_delay;
   1059             } else {
   1060                 /* Bulk delete succeeded */
   1061                 retry_action = RETRY_DEFAULT;
   1062             }
   1063         }
   1064     }
   1065 
   1066     if (retry_action == RETRY_DEFAULT || retry_action == RETRY_AGE) {
   1067         _soc_tr3_l2_do_age(unit, 0, &retry_loc);
   1068 
   1069         if (retry_loc != -1) {
   1070             /* Bulk age failed. Need to retry this action */
   1071             retry_action = RETRY_AGE;
   1072             goto age_delay;
   1073         } else {
   1074             /* Bulk age succeeded */
   1075             retry_action = RETRY_DEFAULT;
   1076         }
   1077     }
   1078 
   1079     /* age delay processing normally wait in l2x_age_notify semaphore for the
   1080      * specified interval before running bulk operation, now l2 bulk operation
   1081      * API like delete_by_vlan/port will stop and start the age thread.
   1082      * Here during exit, aging thread keeps track of amount of time spent on
   1083      * semaphore in current cycle.  Now when aging thread restarted, it waits
   1084      * (aging interval - time spent on previuos cycle). Lets say, aging interval
   1085      * is 50 sec, aging thread run for 20 sec. At that time, delete by vlan API
   1086      * gets called, it stops and restarts the aging thread. This time aging 
   1087      * thread will wait for (50 sec - 20 sec) =  30 sec before running bulk ops
   1088      *
   1089      * _SOC_TR3_VALID_MAX_AGE_INTERVAL is 2147 sec. Now sem_take takes usec
   1090      * integer vlaue. Max integer vlaue that can be adjusted in 31 bit is
   1091      * 0x7FFFFFFF which approximates to (2147 * 1000000) usec. If age interval
   1092      * is greater then 2147 sec, it is splitted to number of 2147 time blocks
   1093      * and reminder part. For example, if age time is 2150 sec, there will be 
   1094      * (2150/2147 = 1) , one 2147 time block and (2150%2147= 3) , three sec 
   1095      * reminder part. Thread will wait first 2147 sec and then 3 sec before 
   1096      * running bulk operation.
   1097      *
   1098      * if age time is less that 2147 sec, soc->l2x_agetime_adjust_usec keeps
   1099      * track of amount of time spent on semaphore in current cycle. It  is 
   1100      * accumulative in nature , resetted before running bulk ops.
   1101      *
   1102      * if age time is greater then 2147 sec, soc->l2x_agetime_curr_timeblk 
   1103      * keeps track of current time block index and 
   1104      * soc->l2x_agetime_curr_timeblk_usec keeps track of amount of time 
   1105      * spent of sem. during current cycle. soc->l2x_agetime_adjust_usec keeps
   1106      * track of reminder part of age time. All the variable are accumulative 
   1107      * in nature and resetted before running bulk ops.
   1108      */
   1109 age_delay:
   1110         /* If this flow is due to a force-bulk-op, goto exit, no ageing 
   1111         necessary */
   1112         if (skip_tr3_l2age_semops) {
   1113             goto post_skip_l2bulkage_semops;
   1114         }
   1115         if (interval > _SOC_TR3_VALID_MAX_AGE_INTERVAL) {
   1116             int aging_off = 0;
   1117 
   1118             /* age interval greater than 2147 processing. */
   1119 
   1120             /* Cumpute the number of '_SOC_TR3_VALID_MAX_AGE_INTERVAL' blocks
   1121             in the current interval */
   1122             m = interval / _SOC_TR3_VALID_MAX_AGE_INTERVAL;
   1123 
   1124             /* Gather the reminder of the interval that is < than a block
   1125             boundary */
   1126             r = interval % _SOC_TR3_VALID_MAX_AGE_INTERVAL;
   1127 
   1128             /* Loop thru the # of blocks waiting. If we have already waited on
   1129             the sem earlier, the 'l2x_agetime_curr_timeblk' will keep track of
   1130             how long, so start there */
   1131             for (c = soc->l2x_agetime_curr_timeblk; c < m; c++) {
   1132                 /* Compute the mac usec's per '_SOC_TR3_VALID_MAX_AGE_INTERVAL'
   1133                 block */
   1134                 wait_interval = _SOC_TR3_VALID_MAX_AGE_INTERVAL
   1135                                 * _SOC_TR3_L2AGE_USEC_IN_ONESEC;
   1136                 /* Make sure 'wait_interval' is > than the accumulated time */
   1137                 if (soc->l2x_agetime_curr_timeblk_usec < wait_interval) {
   1138                     /* Wait for the duration - any accumulated time */
   1139                     actual_wait_time = _soc_tr3_l2age_sem_wait(unit_vp,
   1140                                wait_interval - soc->l2x_agetime_curr_timeblk_usec);
   1141                     /* Take into account how long we waited */
   1142                     soc->l2x_agetime_curr_timeblk_usec += actual_wait_time;
   1143                     /* If the user is doing a bulk-op, 'soc->l2x_age_interval'
   1144                     would have gone to 0, if so, turn off aging and break */
   1145                     if (!soc->l2x_age_interval) {
   1146                         aging_off =1;
   1147                         break;
   1148                     } else if (interval != soc->l2x_age_interval) {
   1149                         interval = soc->l2x_age_interval;
   1150                         soc->l2x_agetime_curr_timeblk_usec = 0;
   1151                         goto age_delay;
   1152                     }
   1153                 }
   1154                 /* In case of the user changes the age_interval while we are 
   1155                 waiting on sem, the sem_wait exits sooner hence need to turn 
   1156                 off aging, which will run bulk-op, init all vars and go back
   1157                 to sem-wait */
   1158                 if (wait_interval > soc->l2x_agetime_curr_timeblk_usec) {
   1159                     aging_off = 1;
   1160                     break;
   1161                 }
   1162                 /* Increment how many blocks we have traversed thus far */
   1163                 soc->l2x_agetime_curr_timeblk++;
   1164                 soc->l2x_agetime_curr_timeblk_usec = 0;
   1165             }
   1166             /* Wait on the sem for the reminder of the interval that is < than a
   1167             block */
   1168             if (!aging_off) {
   1169                 if ( (r * _SOC_TR3_L2AGE_USEC_IN_ONESEC) >
   1170                             soc->l2x_agetime_adjust_usec ) {
   1171                     wait_interval = (r*_SOC_TR3_L2AGE_USEC_IN_ONESEC) -
   1172                                     soc->l2x_agetime_adjust_usec;
   1173                     soc->l2x_agetime_adjust_usec +=
   1174                                 _soc_tr3_l2age_sem_wait(unit_vp, wait_interval);
   1175                     if (soc->l2x_age_interval && (interval != soc->l2x_age_interval)) {
   1176                         interval = soc->l2x_age_interval;
   1177                         goto age_delay;
   1178                     }
   1179                 }
   1180             }
   1181         } else {
   1182             /* age time interval less then 2147 sec processing */
   1183             if ((interval * _SOC_TR3_L2AGE_USEC_IN_ONESEC) >
   1184                                 soc->l2x_agetime_adjust_usec) {
   1185                 (void)sal_sem_take(soc->l2x_age_notify,
   1186                                   (interval * _SOC_TR3_L2AGE_USEC_IN_ONESEC)
   1187                                   - soc->l2x_agetime_adjust_usec);
   1188             }
   1189             if (soc->l2x_age_interval && (interval != soc->l2x_age_interval)) {
   1190                 interval = soc->l2x_age_interval;
   1191                 goto age_delay;
   1192             }
   1193             /* After the current pass, note the time after age_wait */
   1194             timeafter_agewait = sal_time_usecs();
   1195         }
   1196         iter++;
   1197     }
   1198 
   1199     /* age thread exit processing */
   1200     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1201                 (BSL_META_U(unit,
   1202                             "l2_bulk_age_thread: exiting\n")));
   1203     /* Check if the previous accumulated time exceeds the max interval? */
   1204     if (soc->l2x_prev_age_timeout <= _SOC_TR3_VALID_MAX_AGE_INTERVAL) {
   1205         if (!timeafter_agewait) {
   1206             /* If time_after is not set yet, do it now. This happends when
   1207             thread is not schedduled but is exiting */
   1208             timeafter_agewait = sal_time_usecs();
   1209         }
   1210         /* Normal case, where after is less than before*/
   1211         if (timeafter_agewait >= timebefore_agewait) {
   1212             soc->l2x_agetime_adjust_usec += 
   1213                     (timeafter_agewait - timebefore_agewait);
   1214         }
   1215         else {
   1216             /* This is a wrap around case, where after is less than before */
   1217             soc->l2x_agetime_adjust_usec +=
   1218                     ((0xFFFFFFFF - timebefore_agewait) + timeafter_agewait);
   1219         }
   1220 
   1221         /* Check for a special case where accumulated time exceeds the wait 
   1222         interval In such a case we need to force a bulk-op, before exiting */
   1223         if ((soc->l2x_prev_age_timeout) && (soc->l2x_agetime_adjust_usec >=
   1224                 (soc->l2x_prev_age_timeout * _SOC_TR3_L2AGE_USEC_IN_ONESEC))) {
   1225             skip_tr3_l2age_semops = 1;
   1226             /* Goto the force bulk op section */
   1227             goto run_tr3_l2bulkage_ops;
   1228         }
   1229     }
   1230 post_skip_l2bulkage_semops:
   1231     (void)sal_sem_take(soc->l2x_age_notify, 1);
   1232     soc->l2x_age_pid = SAL_THREAD_ERROR;
   1233     sal_thread_exit(0);
   1234 
   1235 }
   1236                                                                      
   1237 /*
   1238  * Function:
   1239  * 	soc_tr3_l2_bulk_age_start
   1240  * Purpose:
   1241  *   	Start l2 bulk age thread
   1242  * Parameters:
   1243  *	unit - unit number.
   1244  * Returns:
   1245  *	SOC_E_XXX
   1246  */
   1247 int
   1248 soc_tr3_l2_bulk_age_start(int unit, int interval)
   1249 {
   1250     int cfg_interval;
   1251     soc_control_t *soc = SOC_CONTROL(unit);
   1252 
   1253     cfg_interval = soc_property_get(unit, spn_L2_SW_AGING_INTERVAL, 
   1254                                     SAL_BOOT_QUICKTURN ? 30 : 10);
   1255     SOC_CONTROL_LOCK(unit);
   1256     soc->l2x_age_interval = interval ? interval : cfg_interval;
   1257     sal_snprintf(soc->l2x_age_name, sizeof (soc->l2x_age_name),
   1258                  "bcmL2age.%d", unit);
   1259     soc->l2x_age_pid = sal_thread_create(soc->l2x_age_name, SAL_THREAD_STKSZ,
   1260                                          soc_property_get(unit, spn_L2AGE_THREAD_PRI, 50),
   1261                                          _soc_tr3_l2_bulk_age, INT_TO_PTR(unit));
   1262     if (soc->l2x_age_pid == SAL_THREAD_ERROR) {
   1263         LOG_ERROR(BSL_LS_SOC_L2,
   1264                   (BSL_META_U(unit,
   1265                               "bcm_esw_l2_init: Could not start L2 bulk age thread\n")));
   1266         SOC_CONTROL_UNLOCK(unit);
   1267         return SOC_E_MEMORY;
   1268     }
   1269     SOC_CONTROL_UNLOCK(unit);
   1270     return SOC_E_NONE;
   1271 }
   1272 
   1273 /*
   1274  * Function:
   1275  * 	soc_tr3_l2_bulk_age_stop
   1276  * Purpose:
   1277  *   	Stop l2 bulk age thread
   1278  * Parameters:
   1279  *	unit - unit number.
   1280  * Returns:
   1281  *	SOC_E_XXX
   1282  */
   1283 int
   1284 soc_tr3_l2_bulk_age_stop(int unit)
   1285 {
   1286     soc_control_t *soc = SOC_CONTROL(unit);
   1287     int           rv = SOC_E_NONE;
   1288     soc_timeout_t to;
   1289 
   1290     SOC_CONTROL_LOCK(unit);
   1291     soc->l2x_age_interval = 0;  /* Request exit */
   1292     SOC_CONTROL_UNLOCK(unit);
   1293 
   1294     if (soc->l2x_age_pid && (soc->l2x_age_pid != SAL_THREAD_ERROR)) {
   1295         /* Wake up thread so it will check the exit flag */
   1296         sal_sem_give(soc->l2x_age_notify);
   1297 
   1298         /* Give thread a few seconds to wake up and exit */
   1299         if (SAL_BOOT_SIMULATION) {
   1300             soc_timeout_init(&to, 300 * 1000000, 0);
   1301         } else {
   1302             soc_timeout_init(&to, 60 * 1000000, 0);
   1303         }
   1304 
   1305         while (soc->l2x_age_pid != SAL_THREAD_ERROR) {
   1306             if (soc_timeout_check(&to)) {
   1307                 LOG_ERROR(BSL_LS_SOC_L2,
   1308                           (BSL_META_U(unit,
   1309                                       "thread will not exit\n")));
   1310                 rv = SOC_E_INTERNAL;
   1311                 break;
   1312             }
   1313         }
   1314     }
   1315     return rv;
   1316 }
   1317 
   1318 /**************************************************
   1319  * @function soc_tr3_l2_entry_limit_count_update
   1320  *          
   1321  * 
   1322  * @purpose Read L2 table from hardware, calculate 
   1323  *          and restore port/trunk and vlan/vfi 
   1324  *          mac counts. 
   1325  * 
   1326  * @param  unit   @b{(input)}  unit number
   1327  *
   1328  * @returns BCM_E_NONE
   1329  * @returns BCM_E_FAIL
   1330  * 
   1331  * @comments This rountine gets called for an 
   1332  *           L2 table SER event, if any of the
   1333  *           mac limits(system, port, vlan) are
   1334  *           enabled on the device.  
   1335  * 
   1336  * @end
   1337  */
   1338 
   1339 int 
   1340 soc_tr3_l2_entry_limit_count_update(int unit)
   1341 {
   1342     uint32 entry[SOC_MAX_MEM_WORDS], rval;
   1343     uint32 *v_entry;     /* vlan or vfi count entry */
   1344     uint32 *p_entry;     /* port or trunk count entry */
   1345     uint32 *l2;          /* l2 entry */
   1346     int32 v_index = -1;  /* vlan index */
   1347     int32 p_index = -1;  /* port index */
   1348     uint32 s_count = 0;  /* system mac count */
   1349     uint32 p_count = 0;  /* port or trunk mac count */
   1350     uint32 v_count = 0;  /* vlan or vfi mac count */
   1351 
   1352     /* l2 table */     
   1353     int index_min, index_max; 
   1354     int entry_dw, entry_sz;
   1355     int chnk_idx, chnk_idx_max, table_chnk_sz, idx;
   1356     int chunk_size = _SOC_TR3_L2_TABLE_DMA_CHUNK_SIZE;
   1357 
   1358     /* port or trunk mac count table */
   1359     int ptm_index_min, ptm_index_max; 
   1360     int ptm_table_sz, ptm_entry_dw, ptm_entry_sz;
   1361 
   1362     /* vlan or vfi mac count table */
   1363     int vvm_index_min, vvm_index_max; 
   1364     int vvm_table_sz, vvm_entry_dw, vvm_entry_sz;
   1365 
   1366     uint32 *buf = NULL;
   1367     uint32 *ptm_buf = NULL; 
   1368     uint32 *vvm_buf = NULL;
   1369 
   1370     uint32 dest_type, key_type;
   1371     uint32 is_valid, is_limit_counted = 0;
   1372     uint32 is_free;
   1373     soc_mem_t mem;
   1374     int rv;
   1375 
   1376     p_index = -1;
   1377     v_index = -1;
   1378 
   1379 
   1380     /* If MAC learn limit not enabled do nothing */
   1381     SOC_IF_ERROR_RETURN(READ_SYS_MAC_LIMIT_CONTROLr(unit, &rval));
   1382     if (!soc_reg_field_get(unit, SYS_MAC_LIMIT_CONTROLr, 
   1383         rval, ENABLE_INTERNAL_L2_ENTRYf)) {
   1384         LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1385                     (BSL_META_U(unit,
   1386                                 "\nMAC limits not enabled.\n"))); 
   1387         return SOC_E_NONE;
   1388     }
   1389 
   1390 
   1391     /* 
   1392      * Mac limits are enabled.
   1393      * 1. Read (DMA) L2 table to recalculate mac count
   1394      * 2. Iterate through all the entries.
   1395      * 3. if the entry is limit_counted
   1396      * Check if KEY_TYPE is BRIDGE, VLAN or VFI 
   1397      * based on DEST_TYPE determine if Trunk or ModPort
   1398      * Get port index into port_or_trunk_mac_count table
   1399      * Get vlan/vfi index into vlan_or_vfi_mac_count table
   1400      * update the port, vlan/vfi, system mac count.
   1401      * Write(slam) port_or_trunk_mac count and 
   1402      * vlan_or_vfi_mac_count tables.
   1403      */
   1404 
   1405     mem = L2_ENTRY_1m;
   1406     _SOC_ALL_L2X_MEM_LOCK(unit);
   1407 
   1408     /*
   1409      * Allocate memory for port/trunk mac count table to store 
   1410      * the updated count.
   1411      */
   1412     ptm_entry_dw = soc_mem_entry_words(unit, PORT_OR_TRUNK_MAC_COUNTm);
   1413     ptm_entry_sz = ptm_entry_dw * sizeof(uint32); 
   1414     ptm_index_min = soc_mem_index_min(unit, PORT_OR_TRUNK_MAC_COUNTm);
   1415     ptm_index_max = soc_mem_index_max(unit,PORT_OR_TRUNK_MAC_COUNTm);
   1416     ptm_table_sz = (ptm_index_max - ptm_index_min + 1) * ptm_entry_sz;
   1417     
   1418     ptm_buf = soc_cm_salloc(unit, ptm_table_sz, "ptm_tmp");
   1419 
   1420     if (ptm_buf == NULL) {
   1421         _SOC_ALL_L2X_MEM_UNLOCK(unit);
   1422         LOG_ERROR(BSL_LS_SOC_L2,
   1423                   (BSL_META_U(unit,
   1424                               "soc_tr3_l2_entry_limit_count_update: "
   1425                               "Memory allocation failed for port mac count\n")));
   1426         return SOC_E_MEMORY; 
   1427     }
   1428 
   1429     sal_memset(ptm_buf, 0, ptm_table_sz);
   1430 
   1431     /*
   1432      * Allocate memory for vlan/vfi mac count table to store 
   1433      * the updated count.
   1434      */
   1435     vvm_entry_dw = soc_mem_entry_words(unit, VLAN_OR_VFI_MAC_COUNTm);
   1436     vvm_entry_sz = vvm_entry_dw * sizeof(uint32); 
   1437     vvm_index_min = soc_mem_index_min(unit, VLAN_OR_VFI_MAC_COUNTm);
   1438     vvm_index_max = soc_mem_index_max(unit,VLAN_OR_VFI_MAC_COUNTm);
   1439     vvm_table_sz = (vvm_index_max - vvm_index_min + 1) * vvm_entry_sz;
   1440     
   1441     vvm_buf = soc_cm_salloc(unit, vvm_table_sz, "vvm_tmp");
   1442 
   1443     if (vvm_buf == NULL) {
   1444         soc_cm_sfree(unit, ptm_buf);
   1445         _SOC_ALL_L2X_MEM_UNLOCK(unit);
   1446         LOG_ERROR(BSL_LS_SOC_L2,
   1447                   (BSL_META_U(unit,
   1448                               "soc_tr3_l2_entry_limit_count_update: "
   1449                               "Memory allocation failed for vlan mac count\n")));
   1450         return SOC_E_MEMORY; 
   1451     }
   1452 
   1453     sal_memset(vvm_buf, 0, vvm_table_sz);
   1454 
   1455     /* Create a copy L2_ENTRY_1m table for calculating mac count */
   1456     entry_dw = soc_mem_entry_words(unit, mem);
   1457     entry_sz = entry_dw * sizeof(uint32); 
   1458     index_min = soc_mem_index_min(unit, mem);
   1459     index_max = soc_mem_index_max(unit, mem);
   1460     table_chnk_sz = chunk_size * entry_sz;
   1461     
   1462     buf = soc_cm_salloc(unit, table_chnk_sz, "l2x_tmp");
   1463 
   1464     if (buf == NULL) {
   1465         soc_cm_sfree(unit, ptm_buf);
   1466         soc_cm_sfree(unit, vvm_buf);
   1467         _SOC_ALL_L2X_MEM_UNLOCK(unit);
   1468         LOG_ERROR(BSL_LS_SOC_L2,
   1469                   (BSL_META_U(unit,
   1470                               "soc_tr3_l2_entry_limit_count_update: "
   1471                               "Memory allocation failed for %s\n"), 
   1472                    SOC_MEM_NAME(unit, mem)));
   1473         return SOC_E_MEMORY; 
   1474     }
   1475 
   1476     for (chnk_idx = index_min; chnk_idx <= index_max; chnk_idx += chunk_size) {
   1477 
   1478          sal_memset(buf, 0, table_chnk_sz);
   1479 
   1480          chnk_idx_max = ((chnk_idx + chunk_size) <= index_max) ?
   1481                 (chnk_idx + chunk_size - 1) : index_max;
   1482 
   1483          /* DMA L2 Table */
   1484          rv =  soc_mem_read_range(unit, mem, MEM_BLOCK_ANY, chnk_idx, 
   1485                                   chnk_idx_max, buf);
   1486          if (rv < 0) {
   1487              soc_cm_sfree(unit, buf);
   1488              soc_cm_sfree(unit, ptm_buf);
   1489              soc_cm_sfree(unit, vvm_buf);
   1490              _SOC_ALL_L2X_MEM_UNLOCK(unit);
   1491              LOG_ERROR(BSL_LS_SOC_L2,
   1492                        (BSL_META_U(unit,
   1493                                    "DMA failed: %s, mac limts not synced!\n"),
   1494                                    soc_errmsg(rv)));
   1495              return SOC_E_FAIL;
   1496          }                          
   1497 
   1498          /* Iter through all l2 entries in the chunk */
   1499          for (idx = 0; idx <= (chnk_idx_max - chnk_idx); idx++) {
   1500               l2 =  (buf + (idx * entry_dw));
   1501          
   1502               /* check if entry is valid */
   1503               is_valid = soc_mem_field32_get(unit, mem, l2, VALIDf); 
   1504               if (!is_valid) {
   1505                   /* not valid entry skip it */
   1506                   continue;
   1507               } 
   1508 
   1509               /* check if entry is limit counted */
   1510               if (soc_mem_field_valid(unit, mem, LIMIT_COUNTEDf)) {
   1511                   is_limit_counted = soc_mem_field32_get(unit,mem, l2, 
   1512                                                          LIMIT_COUNTEDf);
   1513                   if (!is_limit_counted) {
   1514                       /* entry not limit counted skip it */
   1515                       continue;
   1516                   }
   1517               }
   1518 
   1519               /*
   1520                * Get the key type of the entries
   1521                * Process entries with only key_types
   1522                * 1. SOC_MEM_KEY_L2_ENTRY_1_L2_BRIDGE
   1523                * 2. SOC_MEM_KEY_L2_ENTRY_1_L2_VFI
   1524                */
   1525               key_type = soc_mem_field32_get(unit, mem, l2, KEY_TYPEf); 
   1526 
   1527               if ((key_type != SOC_MEM_KEY_L2_ENTRY_1_L2_BRIDGE) &&
   1528                   (key_type != SOC_MEM_KEY_L2_ENTRY_1_L2_VFI)) {
   1529                   continue; 
   1530               } 
   1531 
   1532               dest_type = soc_mem_field32_get(unit, mem, l2, L2__DEST_TYPEf);
   1533 
   1534               switch (dest_type) {
   1535                   case 0: /* mod port */
   1536                       rv = soc_mem_read(unit, PORT_TABm, 
   1537                                                        MEM_BLOCK_ANY, 0,
   1538                                                        &entry);
   1539                       if (SOC_FAILURE(rv)) {
   1540                           soc_cm_sfree(unit, buf);
   1541                           soc_cm_sfree(unit, ptm_buf);
   1542                           soc_cm_sfree(unit, vvm_buf);
   1543                           _SOC_ALL_L2X_MEM_UNLOCK(unit);
   1544                           return rv;
   1545                       }
   1546 
   1547 	              if (soc_mem_field32_get(unit, PORT_TABm, 
   1548                                               &entry, MY_MODIDf) ==
   1549 	                  soc_mem_field32_get(unit, mem, l2, L2__MODULE_IDf)) {
   1550                           p_index = soc_mem_field32_get(unit, mem, 
   1551                                                         l2, PORT_NUMf) + 
   1552 	            	  soc_mem_index_count(unit, TRUNK_GROUPm) ;
   1553 	              }
   1554                       break;
   1555                   case 1: /* trunk */
   1556                       p_index = soc_mem_field32_get(unit, mem, l2, L2__TGIDf);
   1557                       break;
   1558                   default:
   1559                       /* if VFI based key then break else continue? */
   1560                       break;
   1561               }
   1562 
   1563               /*
   1564                * based on key_type get vlan or vfi
   1565                * to index into VLAN_OR_VFI_MAC_COUNTm
   1566                */
   1567               if (key_type == SOC_MEM_KEY_L2_ENTRY_1_L2_BRIDGE) {
   1568                   v_index = soc_mem_field32_get(unit, mem, l2, L2__VLAN_IDf);
   1569               } else {
   1570                   v_index = soc_mem_field32_get(unit, mem, l2, L2__VFIf) +
   1571                                soc_mem_index_count(unit, VLAN_TABm);
   1572               } 
   1573   
   1574 
   1575              /* 
   1576               * read and update vlan or vfi mac count
   1577               * in buffer also update the sys mac count.
   1578               */
   1579              v_count = 0;
   1580              if (v_index >= 0) {
   1581                  v_entry =  (vvm_buf + (v_index * vvm_entry_dw)); 
   1582                  v_count = soc_mem_field32_get(unit, VLAN_OR_VFI_MAC_COUNTm,
   1583                                           v_entry, COUNTf);
   1584                  s_count++;
   1585                  v_count++;
   1586                  soc_mem_field32_set(unit, VLAN_OR_VFI_MAC_COUNTm, 
   1587                                      v_entry, COUNTf, v_count);
   1588              }
   1589     
   1590              /* 
   1591               * read and update port or trunk mac count
   1592               * in buffer.
   1593               */
   1594              p_count = 0;
   1595              if (p_index >= 0) {
   1596                  p_entry = ptm_buf + (p_index * ptm_entry_dw); 
   1597                  p_count = soc_mem_field32_get(unit, PORT_OR_TRUNK_MAC_COUNTm,
   1598                                                p_entry, COUNTf);
   1599                  p_count++;
   1600                  soc_mem_field32_set(unit, PORT_OR_TRUNK_MAC_COUNTm,
   1601                                      p_entry, COUNTf, p_count);
   1602              }
   1603     
   1604          } /* End for index */
   1605     } /* End for chnk_idx */
   1606 
   1607     /* Free memory */
   1608     soc_cm_sfree(unit, buf);
   1609 
   1610     /* Now create a copy L2_ENTRY_2m table for calculating mac count */
   1611     mem = L2_ENTRY_2m;
   1612     entry_dw = soc_mem_entry_words(unit, mem);
   1613     entry_sz = entry_dw * sizeof(uint32); 
   1614     index_min = soc_mem_index_min(unit, mem);
   1615     index_max = soc_mem_index_max(unit, mem);
   1616     table_chnk_sz = chunk_size * entry_sz;
   1617     
   1618     buf = soc_cm_salloc(unit, table_chnk_sz, "l2x_tmp");
   1619 
   1620     if (buf == NULL) {
   1621         soc_cm_sfree(unit, ptm_buf);
   1622         soc_cm_sfree(unit, vvm_buf);
   1623         _SOC_ALL_L2X_MEM_UNLOCK(unit);
   1624         LOG_ERROR(BSL_LS_SOC_L2,
   1625                   (BSL_META_U(unit,
   1626                               "soc_tr3_l2_entry_limit_count_update: "
   1627                               "Memory allocation failed for %s\n"), 
   1628                    SOC_MEM_NAME(unit, mem)));
   1629         return SOC_E_MEMORY; 
   1630     }
   1631 
   1632     for (chnk_idx = index_min; chnk_idx <= index_max; chnk_idx += chunk_size) {
   1633 
   1634          sal_memset(buf, 0, table_chnk_sz);
   1635 
   1636          chnk_idx_max = ((chnk_idx + chunk_size) <= index_max) ?
   1637                 (chnk_idx + chunk_size - 1) : index_max;
   1638 
   1639          /* DMA L2 Table */
   1640          rv =  soc_mem_read_range(unit, mem, MEM_BLOCK_ANY, chnk_idx, 
   1641                                   chnk_idx_max, buf);
   1642          if (rv < 0) {
   1643              soc_cm_sfree(unit, buf);
   1644              soc_cm_sfree(unit, ptm_buf);
   1645              soc_cm_sfree(unit, vvm_buf);
   1646              _SOC_ALL_L2X_MEM_UNLOCK(unit);
   1647              LOG_ERROR(BSL_LS_SOC_L2,
   1648                        (BSL_META_U(unit,
   1649                                    "DMA failed: %s, mac limts not synced!\n"),
   1650                                    soc_errmsg(rv)));
   1651              return SOC_E_FAIL;
   1652          }                          
   1653 
   1654          /* Iter through all l2 entries in the chunk */
   1655          for (idx = 0; idx <= (chnk_idx_max - chnk_idx); idx++) {
   1656               l2 =  (buf + (idx * entry_dw));
   1657          
   1658               /* check if entry is valid */
   1659               if (!soc_mem_field32_get(unit, mem, l2, VALID_0f)) {
   1660                   /* not valid entry skip it */
   1661                   continue;
   1662               } 
   1663 
   1664               /* check if entry is limit counted */
   1665               if (soc_mem_field_valid(unit, mem, LIMIT_COUNTEDf)) {
   1666                   is_limit_counted = soc_mem_field32_get(unit,mem, l2, 
   1667                                                          LIMIT_COUNTEDf);
   1668                   if (!is_limit_counted) {
   1669                       /* entry not limit counted skip it */
   1670                       continue;
   1671                   }
   1672               }
   1673 
   1674               /*
   1675                * Get the key type of the entries
   1676                * Process entries with only key_types
   1677                * 1. SOC_MEM_KEY_L2_ENTRY_2_L2_BRIDGE
   1678                * 2. SOC_MEM_KEY_L2_ENTRY_2_L2_VFI
   1679                */
   1680               key_type = soc_mem_field32_get(unit, L2_ENTRY_1m, l2, KEY_TYPEf);
   1681 
   1682               if ((key_type != SOC_MEM_KEY_L2_ENTRY_2_L2_BRIDGE) &&
   1683                   (key_type != SOC_MEM_KEY_L2_ENTRY_2_L2_VFI)) {
   1684                   continue; 
   1685               } 
   1686 
   1687               dest_type = soc_mem_field32_get(unit, mem, l2, L2__DEST_TYPEf);
   1688 
   1689               switch (dest_type) {
   1690                   case 0: /* mod port */
   1691                       rv = soc_mem_read(unit, PORT_TABm, 
   1692                                                        MEM_BLOCK_ANY, 0,
   1693                                                        &entry);
   1694                       if (SOC_FAILURE(rv)) {
   1695                           soc_cm_sfree(unit, buf);
   1696                           soc_cm_sfree(unit, ptm_buf);
   1697                           soc_cm_sfree(unit, vvm_buf);
   1698                           _SOC_ALL_L2X_MEM_UNLOCK(unit);
   1699                           return rv;
   1700                       }
   1701 	              if (soc_mem_field32_get(unit, PORT_TABm, 
   1702                                               &entry, MY_MODIDf) ==
   1703 	                  soc_mem_field32_get(unit, mem, l2,  L2__MODULE_IDf)) {
   1704                           p_index = soc_mem_field32_get(unit, mem, 
   1705                                                         l2, L2__PORT_NUMf) + 
   1706 	            	            soc_mem_index_count(unit, TRUNK_GROUPm) ;
   1707 	              }
   1708                       break;
   1709                   case 1: /* trunk */
   1710                       p_index = soc_mem_field32_get(unit, mem, l2, L2__TGIDf);
   1711                       break;
   1712                   default:
   1713                       /* if VFI based key then break else continue? */
   1714                       break;
   1715               }
   1716 
   1717               /*
   1718                * based on key_type get vlan or vfi
   1719                * to index into VLAN_OR_VFI_MAC_COUNTm
   1720                */
   1721               if (key_type == SOC_MEM_KEY_L2_ENTRY_2_L2_BRIDGE) {
   1722                   v_index = soc_mem_field32_get(unit, mem, l2, L2__VLAN_IDf);
   1723               } else {
   1724                   v_index = soc_mem_field32_get(unit, mem, l2, L2__VFIf) +
   1725                                soc_mem_index_count(unit, VLAN_TABm);
   1726               } 
   1727   
   1728 
   1729              /* 
   1730               * read and update vlan or vfi mac count
   1731               * in buffer also update the sys mac count.
   1732               */
   1733              v_count = 0;
   1734              if (v_index >= 0) {
   1735                  v_entry =  (vvm_buf + (v_index * vvm_entry_dw)); 
   1736                  v_count = soc_mem_field32_get(unit, VLAN_OR_VFI_MAC_COUNTm,
   1737                                           v_entry, COUNTf);
   1738                  s_count++;
   1739                  v_count++;
   1740                  soc_mem_field32_set(unit, VLAN_OR_VFI_MAC_COUNTm, 
   1741                                      v_entry, COUNTf, v_count);
   1742              }
   1743     
   1744              /* 
   1745               * read and update port or trunk mac count
   1746               * in buffer.
   1747               */
   1748              p_count = 0;
   1749              if (p_index >= 0) {
   1750                  p_entry = ptm_buf + (p_index * ptm_entry_dw); 
   1751                  p_count = soc_mem_field32_get(unit, PORT_OR_TRUNK_MAC_COUNTm,
   1752                                                p_entry, COUNTf);
   1753                  p_count++;
   1754                  soc_mem_field32_set(unit, PORT_OR_TRUNK_MAC_COUNTm,
   1755                                      p_entry, COUNTf, p_count);
   1756              }
   1757     
   1758          } /* End for index */
   1759     } /* End for chnk_idx */
   1760 
   1761     soc_cm_sfree(unit, buf);
   1762 
   1763     /* Work on EXT_L2_TABLE */
   1764     if (soc_feature(unit, soc_feature_esm_support)) {
   1765         /* Create a copy EXT_L2_ENTRY_1m table for calculating mac count */
   1766         mem = EXT_L2_ENTRY_1m;   
   1767         entry_dw = soc_mem_entry_words(unit, mem);
   1768         entry_sz = entry_dw * sizeof(uint32); 
   1769         index_min = soc_mem_index_min(unit, mem);
   1770         index_max = soc_mem_index_max(unit, mem);
   1771         table_chnk_sz = chunk_size * entry_sz;
   1772     
   1773         buf = soc_cm_salloc(unit, table_chnk_sz, "l2x_tmp");
   1774 
   1775         if (buf == NULL) {
   1776             soc_cm_sfree(unit, ptm_buf);
   1777             soc_cm_sfree(unit, vvm_buf);
   1778             _SOC_ALL_L2X_MEM_UNLOCK(unit);
   1779             LOG_ERROR(BSL_LS_SOC_L2,
   1780                       (BSL_META_U(unit,
   1781                                   "soc_tr3_l2_entry_limit_count_update: "
   1782                                   "Memory allocation failed for %s\n"), 
   1783                        SOC_MEM_NAME(unit, mem)));
   1784             return SOC_E_MEMORY; 
   1785         }
   1786 
   1787         for (chnk_idx = index_min; chnk_idx <= index_max; 
   1788                                    chnk_idx += chunk_size) {
   1789 
   1790              sal_memset(buf, 0, table_chnk_sz);
   1791 
   1792              chnk_idx_max = ((chnk_idx + chunk_size) <= index_max) ?
   1793                     (chnk_idx + chunk_size - 1) : index_max;
   1794 
   1795              /* DMA L2 Table */
   1796              rv =  soc_mem_read_range(unit, mem, MEM_BLOCK_ANY, chnk_idx, 
   1797                                       chnk_idx_max, buf);
   1798              if (rv < 0) {
   1799                  soc_cm_sfree(unit, buf);
   1800                  soc_cm_sfree(unit, ptm_buf);
   1801                  soc_cm_sfree(unit, vvm_buf);
   1802                  _SOC_ALL_L2X_MEM_UNLOCK(unit);
   1803                  LOG_ERROR(BSL_LS_SOC_L2,
   1804                            (BSL_META_U(unit,
   1805                                        "DMA failed: %s, mac limts not synced!\n"),
   1806                                        soc_errmsg(rv)));
   1807                  return SOC_E_FAIL;
   1808              }                          
   1809 
   1810              /* Iter through all l2 entries in the chunk */
   1811              for (idx = 0; idx <= (chnk_idx_max - chnk_idx); idx++) {
   1812                   l2 =  (buf + (idx * entry_dw));
   1813          
   1814                   /* check if entry is valid */
   1815                   is_free = soc_mem_field32_get(unit, mem, l2, FREEf); 
   1816                   if (is_free) {
   1817                       /* not valid entry skip it */
   1818                       continue;
   1819                   } 
   1820 
   1821                   /* check if entry is limit counted */
   1822                   if (soc_mem_field_valid(unit, mem, LIMIT_COUNTEDf)) {
   1823                       is_limit_counted = soc_mem_field32_get(unit,mem, l2, 
   1824                                                              LIMIT_COUNTEDf);
   1825                       if (!is_limit_counted) {
   1826                           /* entry not limit counted skip it */
   1827                           continue;
   1828                       }
   1829                   }
   1830     
   1831                   /*
   1832                    * Get the key type of the entries
   1833                    * Process entries with only key_types
   1834                    * 1. SOC_MEM_KEY_L2_ENTRY_1_L2_BRIDGE
   1835                    * 2. SOC_MEM_KEY_L2_ENTRY_1_L2_VFI
   1836                    */
   1837                   key_type = soc_mem_field32_get(unit, mem, l2, KEY_TYPEf); 
   1838 
   1839                   if ((key_type != SOC_MEM_KEY_L2_ENTRY_1_L2_BRIDGE) &&
   1840                       (key_type != SOC_MEM_KEY_L2_ENTRY_1_L2_VFI)) {
   1841                       continue; 
   1842                   } 
   1843 
   1844                   dest_type = soc_mem_field32_get(unit, mem, l2, DEST_TYPEf);
   1845 
   1846                   switch (dest_type) {
   1847                       case 0: /* mod port */
   1848                           rv = soc_mem_read(unit, PORT_TABm, 
   1849                                                            MEM_BLOCK_ANY, 0,
   1850                                                            &entry);
   1851                           if (SOC_FAILURE(rv)) {
   1852                               soc_cm_sfree(unit, buf);
   1853                               soc_cm_sfree(unit, ptm_buf);
   1854                               soc_cm_sfree(unit, vvm_buf);
   1855                               _SOC_ALL_L2X_MEM_UNLOCK(unit);
   1856                               return rv;
   1857                           }
   1858 	                  if (soc_mem_field32_get(unit, PORT_TABm, 
   1859                                                   &entry, MY_MODIDf) ==
   1860 	                      soc_mem_field32_get(unit, mem, l2, MODULE_IDf)) {
   1861                               p_index = soc_mem_field32_get(unit, mem, 
   1862                                                             l2, PORT_NUMf) + 
   1863 	            	                soc_mem_index_count(unit, TRUNK_GROUPm) ;
   1864 	                  }
   1865                           break;
   1866                       case 1: /* trunk */
   1867                           p_index = soc_mem_field32_get(unit, mem, 
   1868                                                         l2, TGIDf);
   1869                           break;
   1870                       default:
   1871                           /* if VFI based key then break else continue? */
   1872                           break;
   1873                   }
   1874     
   1875                   /*
   1876                    * based on key_type get vlan or vfi
   1877                    * to index into VLAN_OR_VFI_MAC_COUNTm
   1878                    */
   1879                   if (key_type == SOC_MEM_KEY_L2_ENTRY_1_L2_BRIDGE) {
   1880                       v_index = soc_mem_field32_get(unit, mem, l2, VLAN_IDf);
   1881                   } else {
   1882                       v_index = soc_mem_field32_get(unit, mem, l2, VFIf) +
   1883                                    soc_mem_index_count(unit, VLAN_TABm);
   1884                   } 
   1885   
   1886 
   1887                  /* 
   1888                   * read and update vlan or vfi mac count
   1889                   * in buffer also update the sys mac count.
   1890                   */
   1891                  v_count = 0;
   1892                  if (v_index >= 0) {
   1893                      v_entry =  (vvm_buf + (v_index * vvm_entry_dw)); 
   1894                      v_count = soc_mem_field32_get(unit, VLAN_OR_VFI_MAC_COUNTm,
   1895                                               v_entry, COUNTf);
   1896                      s_count++;
   1897                      v_count++;
   1898                      soc_mem_field32_set(unit, VLAN_OR_VFI_MAC_COUNTm, 
   1899                                          v_entry, COUNTf, v_count);
   1900                  }
   1901     
   1902                  /* 
   1903                   * read and update port or trunk mac count
   1904                   * in buffer.
   1905                   */
   1906                  p_count = 0;
   1907                  if (p_index >= 0) {
   1908                      p_entry = ptm_buf + (p_index * ptm_entry_dw); 
   1909                      p_count = soc_mem_field32_get(unit, 
   1910                                                    PORT_OR_TRUNK_MAC_COUNTm,
   1911                                                    p_entry, COUNTf);
   1912                      p_count++;
   1913                      soc_mem_field32_set(unit, PORT_OR_TRUNK_MAC_COUNTm,
   1914                                          p_entry, COUNTf, p_count);
   1915                  }
   1916     
   1917              } /* End for index */
   1918         } /* End for chnk_idx */
   1919     
   1920         /* Free memory */
   1921         soc_cm_sfree(unit, buf);
   1922 
   1923         /* Create a copy EXT_L2_ENTRY_2m table for calculating mac count */
   1924         mem = EXT_L2_ENTRY_2m;   
   1925         entry_dw = soc_mem_entry_words(unit, mem);
   1926         entry_sz = entry_dw * sizeof(uint32); 
   1927         index_min = soc_mem_index_min(unit, mem);
   1928         index_max = soc_mem_index_max(unit, mem);
   1929         table_chnk_sz = chunk_size * entry_sz;
   1930     
   1931         buf = soc_cm_salloc(unit, table_chnk_sz, "l2x_tmp");
   1932 
   1933         if (buf == NULL) {
   1934             soc_cm_sfree(unit, ptm_buf);
   1935             soc_cm_sfree(unit, vvm_buf);
   1936             _SOC_ALL_L2X_MEM_UNLOCK(unit);
   1937             LOG_ERROR(BSL_LS_SOC_L2,
   1938                       (BSL_META_U(unit,
   1939                                   "soc_tr3_l2_entry_limit_count_update: "
   1940                                   "Memory allocation failed for %s\n"), 
   1941                        SOC_MEM_NAME(unit, mem)));
   1942             return SOC_E_MEMORY; 
   1943         }
   1944 
   1945         for (chnk_idx = index_min; chnk_idx <= index_max; chnk_idx += chunk_size) {
   1946 
   1947              sal_memset(buf, 0, table_chnk_sz);
   1948 
   1949              chnk_idx_max = ((chnk_idx + chunk_size) <= index_max) ?
   1950                     (chnk_idx + chunk_size - 1) : index_max;
   1951 
   1952              /* DMA L2 Table */
   1953              rv =  soc_mem_read_range(unit, mem, MEM_BLOCK_ANY, chnk_idx, 
   1954                                       chnk_idx_max, buf);
   1955              if (rv < 0) {
   1956                  soc_cm_sfree(unit, buf);
   1957                  soc_cm_sfree(unit, ptm_buf);
   1958                  soc_cm_sfree(unit, vvm_buf);
   1959                  _SOC_ALL_L2X_MEM_UNLOCK(unit);
   1960                  LOG_ERROR(BSL_LS_SOC_L2,
   1961                            (BSL_META_U(unit,
   1962                                        "DMA failed: %s, mac limts not synced!\n"),
   1963                                        soc_errmsg(rv)));
   1964                  return SOC_E_FAIL;
   1965              }                          
   1966 
   1967              /* Iter through all l2 entries in the chunk */
   1968              for (idx = 0; idx <= (chnk_idx_max - chnk_idx); idx++) {
   1969                   l2 =  (buf + (idx * entry_dw));
   1970          
   1971                   /* check if entry is valid */
   1972                   is_free = soc_mem_field32_get(unit, mem, l2, FREEf); 
   1973                   if (is_free) {
   1974                       /* not valid entry skip it */
   1975                       continue;
   1976                   } 
   1977 
   1978                   /* check if entry is limit counted */
   1979                   if (soc_mem_field_valid(unit, mem, LIMIT_COUNTEDf)) {
   1980                       is_limit_counted = soc_mem_field32_get(unit,mem, l2, 
   1981                                                              LIMIT_COUNTEDf);
   1982                       if (!is_limit_counted) {
   1983                           /* entry not limit counted skip it */
   1984                           continue;
   1985                       }
   1986                   }
   1987     
   1988                   /*
   1989                    * Get the key type of the entries
   1990                    * Process entries with only key_types
   1991                    * 1. SOC_MEM_KEY_L2_ENTRY_2_L2_BRIDGE
   1992                    * 2. SOC_MEM_KEY_L2_ENTRY_2_L2_VFI
   1993                    */
   1994                   key_type = soc_mem_field32_get(unit, mem, l2, KEY_TYPEf); 
   1995 
   1996                   if ((key_type != SOC_MEM_KEY_L2_ENTRY_2_L2_BRIDGE) &&
   1997                       (key_type != SOC_MEM_KEY_L2_ENTRY_2_L2_VFI)) {
   1998                       continue; 
   1999                   } 
   2000 
   2001                   dest_type = soc_mem_field32_get(unit, mem, l2, DEST_TYPEf);
   2002 
   2003                   switch (dest_type) {
   2004                       case 0: /* mod port */
   2005                           rv = soc_mem_read(unit, PORT_TABm, 
   2006                                                            MEM_BLOCK_ANY, 0,
   2007                                                            &entry);
   2008                           if (SOC_FAILURE(rv)) {
   2009                               soc_cm_sfree(unit, buf);
   2010                               soc_cm_sfree(unit, ptm_buf);
   2011                               soc_cm_sfree(unit, vvm_buf);
   2012                               _SOC_ALL_L2X_MEM_UNLOCK(unit);
   2013                               return rv;
   2014                           }
   2015 	                  if (soc_mem_field32_get(unit, PORT_TABm, 
   2016                                                   &entry, MY_MODIDf) ==
   2017 	                      soc_mem_field32_get(unit, mem, l2, MODULE_IDf)) {
   2018                               p_index = soc_mem_field32_get(unit, mem, 
   2019                                                             l2, PORT_NUMf) + 
   2020 	            	                soc_mem_index_count(unit, TRUNK_GROUPm) ;
   2021 	                  }
   2022                           break;
   2023                       case 1: /* trunk */
   2024                           p_index = soc_mem_field32_get(unit, mem, 
   2025                                                         l2, TGIDf);
   2026                           break;
   2027                       default:
   2028                           /* if VFI based key then break else continue? */
   2029                           break;
   2030                   }
   2031     
   2032                   /*
   2033                    * based on key_type get vlan or vfi
   2034                    * to index into VLAN_OR_VFI_MAC_COUNTm
   2035                    */
   2036                   if (key_type == SOC_MEM_KEY_L2_ENTRY_2_L2_BRIDGE) {
   2037                       v_index = soc_mem_field32_get(unit, mem, l2, VLAN_IDf);
   2038                   } else {
   2039                       v_index = soc_mem_field32_get(unit, mem, l2, VFIf) +
   2040                                    soc_mem_index_count(unit, VLAN_TABm);
   2041                   } 
   2042   
   2043 
   2044                  /* 
   2045                   * read and update vlan or vfi mac count
   2046                   * in buffer also update the sys mac count.
   2047                   */
   2048                  v_count = 0;
   2049                  if (v_index >= 0) {
   2050                      v_entry =  (vvm_buf + (v_index * vvm_entry_dw)); 
   2051                      v_count = soc_mem_field32_get(unit, VLAN_OR_VFI_MAC_COUNTm,
   2052                                               v_entry, COUNTf);
   2053                      s_count++;
   2054                      v_count++;
   2055                      soc_mem_field32_set(unit, VLAN_OR_VFI_MAC_COUNTm, 
   2056                                          v_entry, COUNTf, v_count);
   2057                  }
   2058     
   2059                  /* 
   2060                   * read and update port or trunk mac count
   2061                   * in buffer.
   2062                   */
   2063                  p_count = 0;
   2064                  if (p_index >= 0) {
   2065                      p_entry = ptm_buf + (p_index * ptm_entry_dw); 
   2066                      p_count = soc_mem_field32_get(unit, 
   2067                                                    PORT_OR_TRUNK_MAC_COUNTm,
   2068                                                    p_entry, COUNTf);
   2069                      p_count++;
   2070                      soc_mem_field32_set(unit, PORT_OR_TRUNK_MAC_COUNTm,
   2071                                          p_entry, COUNTf, p_count);
   2072                  }
   2073     
   2074              } /* End for index */
   2075         } /* End for chnk_idx */
   2076     } /* End if soc_feature_esm_support */
   2077 
   2078     /* Write the tables to hardware */
   2079      /* coverity[stack_use_overflow] */
   2080      rv = soc_mem_write_range(unit, PORT_OR_TRUNK_MAC_COUNTm, MEM_BLOCK_ANY, 
   2081                               ptm_index_min, ptm_index_max, (void *)ptm_buf);
   2082 
   2083     if (rv < 0) {
   2084         soc_cm_sfree(unit, buf);
   2085         soc_cm_sfree(unit, ptm_buf);
   2086         soc_cm_sfree(unit, vvm_buf);
   2087         _SOC_ALL_L2X_MEM_UNLOCK(unit);
   2088         LOG_ERROR(BSL_LS_SOC_L2,
   2089                   (BSL_META_U(unit,
   2090                               "PORT_OR_TRUNK_MAC_COUNT write failed: "
   2091                               "%s, mac limts not synced!\n"),
   2092                    soc_errmsg(rv)));
   2093         return SOC_E_FAIL;
   2094     }
   2095 
   2096     rv = soc_mem_write_range(unit, VLAN_OR_VFI_MAC_COUNTm, MEM_BLOCK_ANY, 
   2097                              vvm_index_min, vvm_index_max, (void *)vvm_buf);
   2098 
   2099     if (rv < 0) {
   2100         soc_cm_sfree(unit, buf);
   2101         soc_cm_sfree(unit, ptm_buf);
   2102         soc_cm_sfree(unit, vvm_buf);
   2103         _SOC_ALL_L2X_MEM_UNLOCK(unit);
   2104         LOG_ERROR(BSL_LS_SOC_L2,
   2105                   (BSL_META_U(unit,
   2106                               "VLAN_OR_VFI_MAC_COUNT write failed: "
   2107                               "%s, mac limts not synced!\n"),
   2108                    soc_errmsg(rv)));
   2109         return SOC_E_FAIL;
   2110     }
   2111      
   2112     /* Update system count */
   2113     soc_reg_field_set(unit, SYS_MAC_COUNTr, &rval, COUNTf, s_count);
   2114     rv = WRITE_SYS_MAC_COUNTr(unit, rval);
   2115     
   2116     /* Free memory */
   2117     soc_cm_sfree(unit, buf);
   2118     soc_cm_sfree(unit, ptm_buf);
   2119     soc_cm_sfree(unit, vvm_buf);
   2120 
   2121     _SOC_ALL_L2X_MEM_UNLOCK(unit);
   2122     return rv;
   2123 }
   2124 
   2125 #endif /* BCM_XGS_SWITCH_SUPPORT */