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


      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 L2 Table Manipulation API routines.
      8  *
      9  * The L2Xm pseudo-table is an aggregate structure supported by
     10  * hardware.  When an entry is read from it, it is constructed from the
     11  * L2X_BASEm, L2X_VALIDm, L2X_HITm, and L2X_STATICm tables.
     12  * NOTE: The L2X pseudo-table is read-only.
     13  *
     14  * A low-level L2 shadow table is optionally kept in soc->arlShadow by
     15  * using a callback to get all inserts/deletes from the l2xmsg task.  It
     16  * can be disabled by setting the l2xmsg_avl property to 0.
     17  */
     18 
     19 #include <shared/bsl.h>
     20 
     21 #include <sal/core/libc.h>
     22 #include <shared/bsl.h>
     23 #include <soc/drv.h>
     24 #include <soc/l2x.h>
     25 #include <soc/ptable.h>
     26 #include <soc/debug.h>
     27 #include <soc/util.h>
     28 #include <soc/mem.h>
     29 #include <soc/tucana.h>
     30 #ifdef BCM_TRIUMPH3_SUPPORT
     31 #include <soc/triumph3.h>
     32 #endif
     33 #ifdef BCM_KATANA2_SUPPORT
     34 #include <bcm_int/esw/katana2.h>
     35 #endif
     36 #ifdef BCM_TRIUMPH3_SUPPORT
     37 #include <soc/tomahawk3.h>
     38 #endif
     39 
     40 #define DEFAULT_L2DELETE_CHUNKS		(64)	/* 16k entries / 64 = 256 */
     41             
     42 #ifdef BCM_XGS_SWITCH_SUPPORT
     43 
     44 /*
     45  * While the L2 table is frozen, the L2Xm lock is held.
     46  *
     47  * All tasks must obtain the L2Xm lock before modifying the CML bits or
     48  * age timer registers.
     49  */
     50 
     51 typedef struct l2_freeze_s {
     52     int                 frozen;
     53     int                 save_age_sec;
     54     int                 save_age_ena;
     55     int                 new_age_set;
     56     int                 hw_frozen;
     57 } l2_freeze_t;
     58 
     59 typedef struct cml_freeze_s {
     60     int                 frozen;
     61     int                 *save_cml; 
     62     int                 *save_cml_move; 
     63     int                 *save_vp_cml;
     64     int                 *save_vp_cml_move; 
     65     SHR_BITDCL          *vp_bitmap;         /* Managed in BCM layer */
     66 #ifdef BCM_TRIDENT2_SUPPORT
     67     sal_mutex_t         cml_freeze_mutex;
     68 #endif
     69 #ifdef BCM_TRIDENT3_SUPPORT
     70     soc_l2x_cml_cb_fn   cml_func;  /*callback function to set lport_tab in TD3*/
     71 #endif
     72 } cml_freeze_t;
     73 
     74 l2_freeze_t l2_freeze_state[SOC_MAX_NUM_DEVICES];
     75 cml_freeze_t cml_freeze_state[SOC_MAX_NUM_DEVICES];
     76 static int l2_freeze_mode[SOC_MAX_NUM_DEVICES];
     77 
     78 #ifdef BCM_TRIDENT2_SUPPORT
     79 #define SOC_CML_FREEZE_LOCK(unit) \
     80     sal_mutex_take(cml_freeze_state[unit].cml_freeze_mutex, sal_mutex_FOREVER)
     81 
     82 #define SOC_CML_FREEZE_UNLOCK(unit) \
     83     sal_mutex_give(cml_freeze_state[unit].cml_freeze_mutex)
     84 #endif
     85 
     86 #ifdef PLISIM
     87 #ifdef _KATANA_DEBUG /* BCM_KATANA_SUPPORT */
     88 STATIC uint32 port_age_enable=FALSE;
     89 STATIC uint32 port_age_flags=0;
     90 STATIC _bcm_l2_replace_t *port_age_rep_st=NULL;
     91 #define SOC_L2X_TGID_TRUNK_INDICATOR(unit) \
     92         SOC_IS_RAVEN(unit) ? 0x40 : 0x20
     93 #define SOC_L2X_TGID_PORT_TRUNK_MASK           0x1f
     94 #define SOC_L2X_TGID_PORT_TRUNK_MASK_HI        0x60
     95 #endif
     96 #endif
     97 
     98 /*
     99  * Function:
    100  *	soc_l2x_entry_compare_key
    101  * Purpose:
    102  *	Comparison function for AVL shadow table operations.  Compares
    103  *	key portion of entry only.
    104  * Parameters:
    105  *	user_data - used to pass StrataSwitch unit #
    106  *	datum1 - first L2X entry to compare
    107  *	datum2 - second L2X entry to compare
    108  * Returns:
    109  *	datum1 <=> datum2
    110  */
    111 
    112 int
    113 soc_l2x_entry_compare_key(void *user_data,
    114                           shr_avl_datum_t *datum1,
    115                           shr_avl_datum_t *datum2)
    116 {
    117     int		unit = PTR_TO_INT(user_data);
    118 
    119     return soc_mem_compare_key(unit, L2Xm, datum1, datum2);
    120 }
    121 
    122 /*
    123  * Function:
    124  *	soc_l2x_entry_compare_all
    125  * Purpose:
    126  *	Comparison function for AVL shadow table operations.  Compares
    127  *	entire key+data of entry, but key is still most significant.
    128  * Parameters:
    129  *	user_data - used to pass StrataSwitch unit #
    130  *	datum1 - first L2X entry to compare
    131  *	datum2 - second L2X entry to compare
    132  * Returns:
    133  *	datum1 <=> datum2
    134  */
    135 
    136 int
    137 soc_l2x_entry_compare_all(void *user_data,
    138                           shr_avl_datum_t *datum1,
    139                           shr_avl_datum_t *datum2)
    140 {
    141     int		unit = PTR_TO_INT(user_data);
    142     int		i;
    143 
    144     i = soc_mem_compare_key(unit, L2Xm, datum1, datum2);
    145 
    146     if (i == 0) {
    147         i = sal_memcmp(datum1, datum2, sizeof (l2x_entry_t));
    148     }
    149 
    150     return i;
    151 }
    152 
    153 /*
    154  * Function:
    155  *	soc_l2x_entry_dump
    156  * Purpose:
    157  *	Debug dump function for AVL shadow table operations.
    158  * Parameters:
    159  *	user_data - used to pass StrataSwitch unit #
    160  *	datum - L2X entry to dump
    161  *	extra_data - unused
    162  * Returns:
    163  *	SOC_E_XXX
    164  */
    165 
    166 int
    167 soc_l2x_entry_dump(void *user_data, shr_avl_datum_t *datum, void *extra_data)
    168 {
    169     int		unit = PTR_TO_INT(user_data);
    170 
    171     COMPILER_REFERENCE(extra_data);
    172 
    173     soc_mem_entry_dump(unit, L2Xm, (l2x_entry_t *) datum, BSL_LSS_CLI);
    174     LOG_CLI((BSL_META_U(unit,
    175                         "\n")));
    176 
    177     return SOC_E_NONE;
    178 }
    179 
    180 /*
    181  * Function:
    182  *	soc_l2x_shadow_callback
    183  * Purpose:
    184  *	Internal callback routine for updating an AVL tree shadow table
    185  * Parameters:
    186  *	unit - StrataSwitch unit number.
    187  *	entry_del - Entry to be deleted or updated, NULL if none.
    188  *	entry_add - Entry to be inserted or updated, NULL if none.
    189  *	fn_data - unused.
    190  * Notes:
    191  *	Used only if L2X shadow table is enabled.
    192  */
    193 
    194 STATIC void
    195 soc_l2x_shadow_callback(int unit,
    196                         int flags,
    197                         l2x_entry_t *entry_del,
    198                         l2x_entry_t *entry_add,
    199                         void *fn_data)
    200 {
    201     soc_control_t	*soc = SOC_CONTROL(unit);
    202 
    203     if (flags & (SOC_L2X_ENTRY_DUMMY | SOC_L2X_ENTRY_NO_ACTION |
    204                  SOC_L2X_ENTRY_OVERFLOW)) {
    205         return;
    206     }
    207 
    208     sal_mutex_take(soc->arlShadowMutex, sal_mutex_FOREVER);
    209 
    210     if (entry_del != NULL) {
    211         shr_avl_delete(soc->arlShadow, soc_l2x_entry_compare_key,
    212                        (shr_avl_datum_t *)entry_del);
    213     }
    214 
    215     if (entry_add != NULL) {
    216         shr_avl_insert(soc->arlShadow, soc_l2x_entry_compare_key,
    217                        (shr_avl_datum_t *)entry_add);
    218     }
    219 
    220     sal_mutex_give(soc->arlShadowMutex);
    221 }
    222 
    223 /*
    224  * Function:
    225  *	_soc_l2x_cml_struct_free
    226  * Purpose:
    227  *	Frees cml_freeze_state structure for a given unit 
    228  * Parameters:
    229  *	unit - StrataSwitch unit number.
    230  * Returns:
    231  *	    NONE 
    232  */
    233 
    234 void
    235 _soc_l2x_cml_struct_free(int unit)
    236 {
    237     if (NULL != cml_freeze_state[unit].save_cml) {
    238         sal_free(cml_freeze_state[unit].save_cml);
    239         cml_freeze_state[unit].save_cml = NULL;
    240     }
    241     if (NULL != cml_freeze_state[unit].save_cml_move) {
    242         sal_free(cml_freeze_state[unit].save_cml_move);
    243         cml_freeze_state[unit].save_cml_move = NULL;
    244     }
    245     if (NULL != cml_freeze_state[unit].save_vp_cml) {
    246         sal_free(cml_freeze_state[unit].save_vp_cml);
    247         cml_freeze_state[unit].save_vp_cml = NULL;
    248     }
    249     if (NULL != cml_freeze_state[unit].save_vp_cml_move) {
    250         sal_free(cml_freeze_state[unit].save_vp_cml_move);
    251         cml_freeze_state[unit].save_vp_cml_move = NULL;
    252     }
    253 
    254     /* We DO NOT free the vp_bitmap here because it is a copy
    255      * of a BCM-layer pointer for SOC reference.
    256      * We do mark it NULL for safety.
    257      */
    258     cml_freeze_state[unit].vp_bitmap = NULL;
    259 #ifdef BCM_TRIDENT3_SUPPORT
    260     if (SOC_IS_TRIDENT3X(unit)) {
    261         cml_freeze_state[unit].cml_func = NULL;
    262     }
    263 #endif
    264 
    265 #ifdef BCM_TRIDENT2_SUPPORT
    266     if (SOC_IS_TD2_TT2(unit)) {
    267         if (cml_freeze_state[unit].cml_freeze_mutex != NULL) {
    268             sal_mutex_destroy(cml_freeze_state[unit].cml_freeze_mutex);
    269             cml_freeze_state[unit].cml_freeze_mutex = NULL;
    270         }
    271     }
    272 #endif
    273     return;
    274 }
    275 
    276 /*
    277  * Function:
    278  *	_soc_l2x_cml_struct_alloc
    279  * Purpose:
    280  *	Allocates cml_freeze_state structure for a given unit 
    281  * Parameters:
    282  *	unit - StrataSwitch unit number.
    283  * Returns:
    284  *	SOC_E_NONE - Allocated succesfully
    285  *  SOC_E_MEMORY - Allocation failed
    286  */
    287 
    288 int
    289 _soc_l2x_cml_struct_alloc(int unit)
    290 {
    291     int cml_alloc_size, num_ports = 0;
    292     if (soc_feature(unit, soc_feature_linkphy_coe) ||
    293         soc_feature(unit, soc_feature_subtag_coe)) {
    294         num_ports = (SOC_MAX_NUM_PP_PORTS > SOC_MAX_NUM_PORTS) ?
    295                     SOC_MAX_NUM_PP_PORTS : SOC_MAX_NUM_PORTS;
    296     } else {
    297         num_ports = SOC_MAX_NUM_PORTS;
    298     }
    299 
    300     cml_alloc_size = sizeof(int) * num_ports;
    301     
    302     cml_freeze_state[unit].save_cml = (int *)sal_alloc(cml_alloc_size, "CML");
    303     if (NULL == cml_freeze_state[unit].save_cml) {
    304         goto e_memory;
    305     }
    306     sal_memset(cml_freeze_state[unit].save_cml, 0, cml_alloc_size);
    307 
    308     cml_freeze_state[unit].save_cml_move = 
    309         (int *)sal_alloc(cml_alloc_size, "CML MOVE");
    310     if (NULL == cml_freeze_state[unit].save_cml_move) {
    311         goto e_memory;
    312     }
    313     sal_memset(cml_freeze_state[unit].save_cml_move, 0, cml_alloc_size);
    314 
    315     if (SOC_MEM_IS_VALID(unit, SOURCE_VPm)) {
    316         cml_alloc_size = sizeof(int) * soc_mem_index_count(unit,SOURCE_VPm); 
    317         cml_freeze_state[unit].save_vp_cml = 
    318             (int *)sal_alloc(cml_alloc_size, "VP CML");
    319         if (NULL == cml_freeze_state[unit].save_vp_cml) {
    320             goto e_memory;
    321         }
    322         sal_memset(cml_freeze_state[unit].save_vp_cml, 0, cml_alloc_size);
    323 
    324         cml_freeze_state[unit].save_vp_cml_move = 
    325             (int *)sal_alloc(cml_alloc_size, "VP CML MOVE");
    326         if (NULL == cml_freeze_state[unit].save_vp_cml_move) {
    327             goto e_memory;
    328         }
    329         sal_memset(cml_freeze_state[unit].save_vp_cml_move, 0, cml_alloc_size);
    330     }
    331     /* We DO NOT initialize the vp_bitmap here because it is a copy
    332      * of a BCM-layer pointer for SOC reference.
    333      * We do mark it NULL for safety until the BCM layer passes
    334      * a valid pointer.
    335      */
    336     cml_freeze_state[unit].vp_bitmap = NULL;
    337 #ifdef BCM_TRIDENT3_SUPPORT
    338     if (SOC_IS_TRIDENT3X(unit)) {
    339         cml_freeze_state[unit].cml_func = NULL;
    340     }
    341 #endif/*BCM_TRIDENT3_SUPPORT*/
    342 
    343 #ifdef BCM_TRIDENT2_SUPPORT
    344     if (SOC_IS_TD2_TT2(unit)) {
    345         if ((cml_freeze_state[unit].cml_freeze_mutex =
    346             sal_mutex_create("soc_cml_freeze_lock")) == NULL) {
    347             return (SOC_E_MEMORY);
    348         }
    349     }
    350 #endif
    351     return SOC_E_NONE;
    352 
    353 e_memory:
    354     _soc_l2x_cml_struct_free(unit);
    355 
    356     return SOC_E_MEMORY;
    357 
    358 }
    359 
    360 /*
    361  * Function:
    362  *	soc_l2x_cml_vp_bitmap_set
    363  * Purpose:
    364  *	Record pointer to the in-use virtual port bitmap managed by
    365  *      the BCM layer.
    366  * Parameters:
    367  *	unit - StrataSwitch unit number.
    368  *      vp_bitmap - pointer to BCM-layer VP use bitmap.
    369  * Returns:
    370  *	Nothing
    371  */
    372 
    373 void
    374 soc_l2x_cml_vp_bitmap_set(int unit, SHR_BITDCL *vp_bitmap)
    375 {
    376 #if defined(BCM_TOMAHAWK3_SUPPORT)
    377     /* On Tomahawk3, do not store the bitmap since VP memory is not supported */
    378     if (SOC_IS_TOMAHAWK3(unit)) {
    379         return;
    380     } else
    381 #endif /* BCM_TOMAHAWK3_SUPPORT */
    382     {
    383         cml_freeze_state[unit].vp_bitmap = vp_bitmap;
    384     }
    385 }
    386 
    387 /*
    388  * Function:
    389  *	soc_l2x_attach
    390  * Purpose:
    391  *	Allocate L2X subsystem resources
    392  * Parameters:
    393  *	unit - StrataSwitch unit number.
    394  * Returns:
    395  *	SOC_E_XXX
    396  * Notes:
    397  *	The L2X tree shadow table is optional and its allocation
    398  *	is controlled using a property.
    399  */
    400 
    401 int
    402 soc_l2x_attach(int unit)
    403 {
    404     soc_control_t	*soc = SOC_CONTROL(unit);
    405 
    406     soc->l2x_age_timeout = soc_property_get(unit, spn_ARL_CLEAN_TIMEOUT_USEC,
    407                                             15000000);
    408     soc->l2x_mode = soc_l2x_mode_cfg_get(unit);
    409 
    410 #ifdef BCM_TRIUMPH3_SUPPORT
    411     if (SOC_IS_TRIUMPH3(unit)) {
    412         return soc_tr3_l2_attach(unit);
    413     }
    414 #endif
    415 
    416 #ifdef BCM_TOMAHAWK3_SUPPORT
    417     if (SOC_IS_TOMAHAWK3(unit)) {
    418         /* FIFO mode is not supported, since h/w to support it does not exist
    419          * on TH3. So this property setting is ignored
    420          */
    421         soc->l2x_mode = L2MODE_POLL;
    422         return soc_th3_l2x_attach(unit);
    423     }
    424 #endif
    425 
    426     (void)soc_l2x_detach(unit);
    427 
    428     if (soc_property_get(unit, spn_L2XMSG_AVL, TRUE)) {
    429         int		datum_bytes, datum_max;
    430 
    431         datum_bytes = sizeof (l2x_entry_t);
    432         datum_max = soc_mem_index_count(unit, L2Xm);
    433 
    434         if (shr_avl_create(&soc->arlShadow,
    435                            INT_TO_PTR(unit),
    436                            datum_bytes,
    437                            datum_max) < 0) {
    438             return SOC_E_MEMORY;
    439         }
    440 
    441         if ((soc->arlShadowMutex = sal_mutex_create("asMutex")) == NULL) {
    442             (void)soc_l2x_detach(unit);
    443             return SOC_E_MEMORY;
    444         }
    445 
    446         soc_l2x_register(unit, soc_l2x_shadow_callback, NULL);
    447     }
    448 
    449     /* Reset l2 freeze structure. */
    450     sal_memset(l2_freeze_state + unit, 0, sizeof(l2_freeze_t));
    451 
    452     /* Allocate cml freeze structure */
    453     return _soc_l2x_cml_struct_alloc(unit);
    454 }
    455 
    456 /*
    457  * Function:
    458  *	soc_l2x_detach
    459  * Purpose:
    460  *	Deallocate L2X subsystem resources
    461  * Parameters:
    462  *	unit - StrataSwitch unit number.
    463  * Returns:
    464  *	SOC_E_XXX
    465  */
    466 
    467 int
    468 soc_l2x_detach(int unit)
    469 {
    470     soc_control_t *soc = SOC_CONTROL(unit);
    471 
    472 #ifdef BCM_TRIUMPH3_SUPPORT
    473     if (SOC_IS_TRIUMPH3(unit)) {
    474         return soc_tr3_l2_detach(unit);
    475     }
    476 #endif
    477 
    478 #ifdef BCM_TOMAHAWK3_SUPPORT
    479     if (SOC_IS_TOMAHAWK3(unit)) {
    480         return soc_th3_l2x_detach(unit);
    481     }
    482 #endif
    483 
    484     soc_l2x_unregister(unit, soc_l2x_shadow_callback, NULL);
    485 
    486     /* Free cml_freeze structure  */
    487     _soc_l2x_cml_struct_free(unit);
    488 
    489     if (soc->arlShadow != NULL) {
    490         shr_avl_destroy(soc->arlShadow);
    491         soc->arlShadow = NULL;
    492     }
    493 
    494     if (soc->arlShadowMutex != NULL) {
    495         sal_mutex_destroy(soc->arlShadowMutex);
    496         soc->arlShadowMutex = NULL;
    497     }
    498 
    499     return SOC_E_NONE;
    500 }
    501 
    502 /*
    503  * Function:
    504  *	soc_l2x_init
    505  * Purpose:
    506  *	Initialize L2 table subsystem.
    507  * Parameters:
    508  *	unit - StrataSwitch unit number.
    509  * Returns:
    510  *	SOC_E_xxx
    511  * Notes:
    512  *	This routine must not do anything time consuming since it is
    513  *	called by soc_init().
    514  */
    515 
    516 int
    517 soc_l2x_init(int unit)
    518 {
    519     /* The L2 table is cleared in soc_misc_init(). */
    520     return SOC_E_NONE;
    521 }
    522 
    523 #if defined(BCM_XGS12_SWITCH_SUPPORT)
    524 /*
    525  * Function:
    526  *	soc_l2x_lookup
    527  * Purpose:
    528  *	Send an L2 lookup message over the S-Channel and receive the
    529  *	response.
    530  * Parameters:
    531  *	unit - StrataSwitch unit #
    532  *	key - L2X entry to look up; only MAC+VLAN fields are relevant
    533  *	result - L2X entry to receive entire found entry
    534  *	index_ptr (OUT) - If found, receives table index where found
    535  * Returns:
    536  *	SOC_E_INTERNAL if retries exceeded or other internal error
    537  *	SOC_E_NOT_FOUND if the entry is not found.
    538  *	SOC_E_NONE (0) on success (entry found):
    539  * Notes:
    540  *	The S-Channel response contains either a matching L2 entry,
    541  *	or an entry with a key of all f's if not found.  It is okay
    542  *	if the result pointer is the same as the key pointer.
    543  *	Retries the lookup in cases where the particular chip requires it.
    544  */
    545 
    546 int
    547 soc_l2x_lookup(int unit,
    548                l2x_entry_t *key, l2x_entry_t *result,
    549                int *index_ptr)
    550 {
    551     schan_msg_t 	schan_msg;
    552     int                 src_blk;
    553     int                 opcode;
    554 
    555     schan_msg_clear(&schan_msg);
    556     src_blk = SOC_BLOCK2SCH(unit, CMIC_BLOCK(unit));
    557     soc_schan_header_cmd_set(unit, &schan_msg.header, ARL_LOOKUP_CMD_MSG,
    558                              0, src_blk, 0, 8, 0, 0);  
    559     schan_msg.arllkup.address = soc_mem_addr(unit, L2Xm, 0, ARL_BLOCK(unit), 0);
    560 
    561     /* Fill in packet data */
    562 
    563     sal_memcpy(schan_msg.arllkup.data, key, sizeof (schan_msg.arllkup.data));
    564 
    565     /*
    566      * Write onto S-Channel "ARL lookup" command packet consisting of
    567      * header word + address + two words of ARL key, and read back header
    568      * word + 2 words of a special lookup result format.
    569      */
    570 
    571     SOC_IF_ERROR_RETURN(soc_schan_op(unit, &schan_msg, 4, 3, 1));
    572 
    573     /* Check result */
    574     soc_schan_header_status_get(unit, &schan_msg.header, &opcode, NULL, NULL,
    575                                 NULL, NULL, NULL);
    576     if (opcode != READ_MEMORY_ACK_MSG) {
    577         LOG_ERROR(BSL_LS_SOC_L2,
    578                   (BSL_META_U(unit,
    579                               "soc_l2x_lookup: "
    580                               "invalid S-Channel reply, expected READ_MEMORY_ACK:\n")));
    581         soc_schan_dump(unit, &schan_msg, 3);
    582         return SOC_E_INTERNAL;
    583     }
    584 
    585     /*
    586      * Fill in result entry from read data.
    587      * Note that the lookup does not return the key, so it must be copied.
    588      *
    589      * Format of S-Channel response:
    590      *		readresp.header : Memory Read Ack S-channel header
    591      *		readresp.data[0]: { 4'h0, hit, static, l2_table_data }
    592      *		readresp.data[1]: { 18'h0, index_into_L2_table[13:0] }
    593      */
    594 
    595     if (schan_msg.readresp.data[0] == 0xffffffff &&
    596         schan_msg.readresp.data[1] == 0xffffffff) {
    597         *index_ptr = -1;
    598         return SOC_E_NOT_FOUND;
    599     }
    600 
    601     /* MACADDR<31:0> */
    602     result->entry_data[0] = key->entry_data[0];
    603 
    604     /* CPU, COS<2:0>, VLAN<12:0>, MACADDR<47:32> */
    605     result->entry_data[1] = ((schan_msg.readresp.data[0] << 28) |
    606                              (key->entry_data[1] & 0x0fffffff));
    607 
    608     /* ZERO<6:0>, VALID=1, HIT, STATIC .. DST_DISCARD */
    609     result->entry_data[2] = schan_msg.readresp.data[0] >> 4;
    610     result->entry_data[2] |= 1 << (88-64);
    611 
    612     *index_ptr = schan_msg.readresp.data[1];
    613 
    614     if (bsl_check(bslLayerSoc, bslSourceSocmem, bslSeverityNormal, unit)) {
    615         LOG_INFO(BSL_LS_SOC_SOCMEM,
    616                  (BSL_META_U(unit,
    617                              "L2 entry lookup: ")));
    618         soc_mem_entry_dump(unit, L2Xm, result, BSL_INFO|BSL_LS_SOC_SOCMEM);
    619         LOG_INFO(BSL_LS_SOC_SOCMEM,
    620                  (BSL_META_U(unit,
    621                              " (index=%d)\n"), *index_ptr));
    622     }
    623 
    624     return SOC_E_NONE;
    625 }
    626 
    627 /*
    628  * Function:
    629  *	_soc_l2x_hit_clear
    630  * Purpose:
    631  *	Clear the hit bit on a specified L2 entry.
    632  * Parameters:
    633  *	unit - StrataSwitch PCI device unit number
    634  *	entry - Entry to operate on
    635  * Returns:
    636  *	SOC_E_NONE - success
    637  *	SOC_E_NOT_FOUND - no such address
    638  *	SOC_E_XXX - other
    639  * Notes:
    640  *	The proper way to clear hit bits is to use soc_l2x_insert()
    641  *	with the hit bit clear.  This is just a helper routine for
    642  *	a 5690 problem.
    643  *
    644  *	5690 cannot clear hit bits atomically, hence there is a race
    645  *	condition where if other hit bit(s) got set in the same bucket
    646  *	between our read and write operations, they could also be
    647  *	cleared.
    648  */
    649 
    650 int
    651 _soc_l2x_hit_clear(int unit, l2x_entry_t *entry)
    652 {
    653     l2x_entry_t		result;
    654     l2x_hit_entry_t	hit_bits;
    655     int			index, bucket, bit, r;
    656 
    657     if ((r = soc_l2x_lookup(unit, entry, &result, &index)) < 0) {
    658         return r;
    659     }
    660 
    661     bucket = index / SOC_L2X_BUCKET_SIZE;
    662     bit = index % SOC_L2X_BUCKET_SIZE;
    663 
    664     /* Read/modify/write bucket hit bits */
    665 
    666     soc_mem_lock(unit, L2X_HITm);
    667 
    668     if ((r = soc_mem_read(unit, L2X_HITm, MEM_BLOCK_ANY,
    669                           bucket, &hit_bits)) < 0) {
    670         soc_mem_unlock(unit, L2X_HITm);
    671         return r;
    672     }
    673 
    674     hit_bits.entry_data[0] &= ~(1 << bit);
    675 
    676     if ((r = soc_mem_write(unit, L2X_HITm, MEM_BLOCK_ANY,
    677                            bucket, &hit_bits)) < 0) {
    678         soc_mem_unlock(unit, L2X_HITm);
    679         return r;
    680     }
    681 
    682     soc_mem_unlock(unit, L2X_HITm);
    683 
    684     return SOC_E_NONE;
    685 }
    686 
    687 /*
    688  * Function:
    689  *	soc_l2x_insert
    690  * Purpose:
    691  *	Insert an entry into the L2X hash table.
    692  * Parameters:
    693  *	unit - StrataSwitch unit #
    694  *	entry - L2X entry to insert
    695  * Returns:
    696  *	SOC_E_NONE - success
    697  *	SOC_E_FULL - hash bucket full
    698  * Notes:
    699  *	Uses hardware insertion; sends an L2 INSERT message over the
    700  *	S-Channel.  The hardware needs the L2Xm entry type.
    701  *	This affects the L2_ENTRYm table, L2_VALIDm table, L2_STATICm
    702  *	table, and the L2_HITm table.
    703  */
    704 
    705 int
    706 soc_l2x_insert(int unit, l2x_entry_t *entry)
    707 {
    708     l2x_entry_t         valid_entry;
    709     schan_msg_t 	schan_msg;
    710     int			rv;
    711     int                 src_blk;
    712 
    713     if (bsl_check(bslLayerSoc, bslSourceSocmem, bslSeverityNormal, unit)) {
    714         LOG_INFO(BSL_LS_SOC_SOCMEM,
    715                  (BSL_META_U(unit,
    716                              "Insert table[L2X]: ")));
    717         soc_mem_entry_dump(unit, L2Xm, entry, BSL_INFO|BSL_LS_SOC_SOCMEM);
    718         LOG_INFO(BSL_LS_SOC_SOCMEM,
    719                  (BSL_META_U(unit,
    720                              "\n")));
    721     }
    722 
    723     memcpy(&valid_entry, entry, sizeof(l2x_entry_t));
    724     soc_L2Xm_field32_set(unit, &valid_entry, VALID_BITf, 1);
    725 
    726 #define SOC_L2X_MEM_BYTES 11
    727     schan_msg_clear(&schan_msg);
    728     src_blk = SOC_BLOCK2SCH(unit, CMIC_BLOCK(unit));
    729     soc_schan_header_cmd_set(unit, &schan_msg.header, ARL_INSERT_CMD_MSG,
    730                              0, src_blk, 0, SOC_L2X_MEM_BYETS, 0, 0);  
    731 #undef SOC_L2X_MEM_BYTES
    732 
    733     /* Fill in ARL packet data */
    734 
    735     sal_memcpy(schan_msg.arlins.data, &valid_entry, 
    736                sizeof (schan_msg.arlins.data));
    737 
    738     /* Lock ARL memory to avoid modifying L2 table while frozen */
    739 
    740     soc_mem_lock(unit, L2Xm);
    741 
    742     /* Execute S-Channel operation (header word + 3 DWORDs) */
    743 
    744     rv = soc_schan_op(unit, &schan_msg, 4, 0, 1);
    745 
    746     if (rv == SOC_E_FAIL) {
    747         LOG_INFO(BSL_LS_SOC_SOCMEM,
    748                  (BSL_META_U(unit,
    749                              "Insert table[L2X]: hash bucket full\n")));
    750         rv = SOC_E_FULL;
    751     }
    752 
    753     soc_mem_unlock(unit, L2Xm);
    754 
    755     /* 5690 workaround; see _soc_l2x_hit_clear() for details */
    756 
    757     if (rv >= 0 &&
    758         soc_feature(unit, soc_feature_l2x_ins_sets_hit) &&
    759         !soc_L2Xm_field32_get(unit, entry, HIT_BITf)) {
    760         rv = _soc_l2x_hit_clear(unit, entry);
    761     }
    762 
    763     return rv;
    764 }
    765 
    766 /*
    767  * Function:
    768  *	soc_l2x_delete
    769  * Purpose:
    770  *	Delete an entry from the L2X hash table.
    771  * Parameters:
    772  *	unit - StrataSwitch unit #
    773  *	entry - L2X entry to delete
    774  * Returns:
    775  *	SOC_E_NONE - success
    776  *	SOC_E_FULL - hash bucket full
    777  * Notes:
    778  *	Uses hardware deletion; sends an L2 DELETE message over the
    779  *	S-Channel.  The hardware needs the L2Xm entry type.
    780  *	Only the L2_VALIDm table is affected.
    781  */
    782 
    783 int
    784 soc_l2x_delete(int unit, l2x_entry_t *entry)
    785 {
    786     schan_msg_t 	schan_msg;
    787     int			rv;
    788     int                 src_blk;
    789 
    790     if (bsl_check(bslLayerSoc, bslSourceSocmem, bslSeverityNormal, unit)) {
    791         LOG_INFO(BSL_LS_SOC_SOCMEM,
    792                  (BSL_META_U(unit,
    793                              "Delete table[L2X]: ")));
    794         soc_mem_entry_dump(unit, L2Xm, entry, BSL_INFO|BSL_LS_SOC_SOCMEM);
    795         LOG_INFO(BSL_LS_SOC_SOCMEM,
    796                  (BSL_META_U(unit,
    797                              "\n")));
    798     }
    799 
    800 #define SOC_L2X_MEM_KEY_BYTES 8
    801     schan_msg_clear(&schan_msg);
    802     src_blk = SOC_BLOCK2SCH(unit, CMIC_BLOCK(unit));
    803     soc_schan_header_cmd_set(unit, &schan_msg.header, ARL_DELETE_CMD_MSG,
    804                              0, src_blk, 0, SOC_L2X_MEM_KEY_BYTES, 0, 0);  
    805 #undef SOC_L2X_MEM_KEY_BYTES
    806 
    807     /* Fill in packet data */
    808 
    809     sal_memcpy(schan_msg.arldel.data, entry, sizeof (schan_msg.arldel.data));
    810 
    811     /* Lock ARL memory to avoid modifying L2 table while frozen */
    812 
    813     soc_mem_lock(unit, L2Xm);
    814 
    815     /* Execute S-Channel operation (header word + 2 DWORDs) */
    816     rv = soc_schan_op(unit, &schan_msg, 3, 0, 1);
    817 
    818     soc_mem_unlock(unit, L2Xm);
    819 
    820     return rv;
    821 }
    822 
    823 /*
    824  * Function:
    825  *	soc_l2x_delete_all
    826  * Purpose:
    827  *	Clear the L2 table by invalidating entries.
    828  * Parameters:
    829  *	unit - StrataSwitch unit #
    830  *	static_too - if TRUE, delete static and non-static entries;
    831  *		     if FALSE, delete only non-static entries
    832  * Returns:
    833  *	SOC_E_XXX
    834  */
    835 
    836 int
    837 soc_l2x_delete_all(int unit, int static_too)
    838 {
    839     soc_control_t	*soc = SOC_CONTROL(unit);
    840     int			index_min, index_max, index;
    841     l2x_valid_entry_t	valid_bits;
    842     l2x_static_entry_t	static_bits;
    843     int			rv = SOC_E_NONE;
    844 
    845     soc_mem_lock(unit, L2Xm);
    846 
    847     sal_memset(&valid_bits, 0, sizeof (valid_bits));
    848 
    849     index_min = soc_mem_index_min(unit, L2X_VALIDm);
    850     index_max = soc_mem_index_max(unit, L2X_VALIDm);
    851 
    852     for (index = index_min; index <= index_max; index++) {
    853         if (!static_too) {
    854             if ((rv = soc_mem_read(unit, L2X_VALIDm, MEM_BLOCK_ANY,
    855                                    index, &valid_bits)) < 0) {
    856                 goto done;
    857             }
    858 
    859             if ((rv = soc_mem_read(unit, L2X_STATICm, MEM_BLOCK_ANY,
    860                                    index, &static_bits)) < 0) {
    861                 goto done;
    862             }
    863 
    864             valid_bits.entry_data[0] &= static_bits.entry_data[0];
    865         } /* else the valid bits will always be 0 */
    866 
    867         if ((rv = soc_mem_write(unit, L2X_VALIDm, MEM_BLOCK_ALL,
    868                                 index, &valid_bits)) < 0) {
    869             goto done;
    870         }
    871     }
    872 
    873     if (soc->arlShadow != NULL) {
    874         sal_mutex_take(soc->arlShadowMutex, sal_mutex_FOREVER);
    875         (void) shr_avl_delete_all(soc->arlShadow);
    876         sal_mutex_give(soc->arlShadowMutex);
    877     }
    878 
    879  done:
    880 
    881     soc_mem_unlock(unit, L2Xm);
    882 
    883     return rv;
    884 }
    885 #endif /* BCM_XGS12_SWITCH_SUPPORT */
    886 #ifdef PLISIM
    887 #ifdef _KATANA_DEBUG /* BCM_KATANA_SUPPORT */
    888 void _bcm_kt_enable_port_age_simulation(uint32 flags, _bcm_l2_replace_t *rep_st)
    889 {
    890 	port_age_enable=TRUE;
    891 	port_age_flags=flags;
    892 	port_age_rep_st=rep_st;
    893 	return ;
    894 }
    895 STATIC int perform_port_age_simulation(int unit)
    896 {
    897     	uint32 		sync_op;
    898         soc_field_t     valid_bit = VALID_BITf;
    899 	int             static_bit_val;
    900 	int             pending_bit_val;
    901     	int             port_val, mod_val;
    902 	vlan_id_t       vlan_val;
    903 	int 		vfi_val;
    904 	int             tgid_hi=0,tgid_lo=0;
    905 	int 		tgid_val=0, tid_val=0;
    906 	int		trunk128;
    907 	uint32		tid;
    908 
    909 
    910     	/* Indexes to iterate over memories, chunks and entries */
    911 	int             chnk_idx, ent_idx, chnk_idx_max, mem_idx_max;
    912 	int             buf_size, chunksize, chnk_end;
    913 	/* Buffer to store chunk of L2 table we currently work on */
    914 	uint32          *l2_tbl_chnk;
    915 	uint32          *l2_entry;
    916 	int             rv = SOC_E_NONE;
    917 
    918 	if ( port_age_enable==FALSE) {
    919         LOG_CLI((BSL_META_U(unit,
    920                             "INFO:PortAging simulation not enabled yet \n")));	
    921 		return SOC_E_NONE;
    922 	}
    923 	port_age_enable=FALSE;
    924     LOG_CLI((BSL_META_U(unit,
    925                         "Performing PortAging simulation... STATIC %d \n"),
    926              port_age_flags & BCM_L2_REPLACE_MATCH_STATIC));
    927 
    928 	if (SOC_IS_FBX(unit)) {
    929         	valid_bit = VALIDf;
    930     	}
    931 	tid = port_age_rep_st->match_trunk;
    932 	if (!(port_age_flags & BCM_L2_REPLACE_DELETE) || (port_age_flags & _BCM_L2_REPLACE_DELETE_ALL)) {
    933        		return SOC_E_NONE;
    934 	}
    935 	switch (port_age_flags & (BCM_L2_REPLACE_MATCH_DEST | BCM_L2_REPLACE_MATCH_VLAN)) {
    936 		case BCM_L2_REPLACE_MATCH_DEST:
    937 			if (port_age_rep_st->isTrunk) {
    938 				sync_op = SOC_L2X_TRUNK_DEL;
    939 			} else {
    940 				sync_op = SOC_L2X_PORTMOD_DEL;
    941 			}
    942 			break;
    943 		case BCM_L2_REPLACE_MATCH_VLAN:
    944 			sync_op = SOC_L2X_VLAN_DEL;
    945 			break;
    946 		case BCM_L2_REPLACE_MATCH_DEST | BCM_L2_REPLACE_MATCH_VLAN:
    947 			if (port_age_rep_st->isTrunk) {
    948 				sync_op = SOC_L2X_TRUNK_VLAN_DEL;
    949 			} else {
    950 				sync_op = SOC_L2X_PORTMOD_VLAN_DEL;
    951 			}
    952 			break;
    953 		default:
    954             LOG_CLI((BSL_META_U(unit,
    955                                 "Unknown PortAging operation !!! \n")));	
    956 			return SOC_E_PARAM;
    957 	}
    958     	if (!soc_mem_index_count(unit, L2Xm)) {
    959         	return SOC_E_NONE;
    960 	}
    961     	chunksize = soc_property_get(unit, spn_L2DELETE_CHUNKS, L2_MEM_CHUNKS_DEFAULT);
    962 	buf_size = 4 * SOC_MAX_MEM_FIELD_WORDS * chunksize;
    963 	l2_tbl_chnk = soc_cm_salloc(unit, buf_size, "l2 traverse");
    964 	if (NULL == l2_tbl_chnk) {
    965 		return SOC_E_MEMORY;
    966 	}
    967 	mem_idx_max = soc_mem_index_max(unit, L2Xm);
    968 	for (chnk_idx = soc_mem_index_min(unit, L2Xm); chnk_idx <= mem_idx_max; chnk_idx += chunksize) {
    969 		sal_memset((void *)l2_tbl_chnk, 0, buf_size);
    970 		chnk_idx_max = ((chnk_idx + chunksize) < mem_idx_max) ?  (chnk_idx + chunksize - 1) : mem_idx_max;
    971 		rv = soc_mem_read_range(unit, L2Xm, MEM_BLOCK_ANY, chnk_idx, chnk_idx_max, l2_tbl_chnk);
    972 		if (SOC_FAILURE(rv)) {
    973 			break;
    974 		}
    975 		chnk_end = (chnk_idx_max - chnk_idx);
    976 		for (ent_idx = 0 ; ent_idx <= chnk_end; ent_idx ++) {
    977 			l2_entry = soc_mem_table_idx_to_pointer(unit, L2Xm, uint32 *, l2_tbl_chnk, ent_idx);
    978 			if (!soc_mem_field32_get(unit,L2Xm, l2_entry,valid_bit)) {
    979 				continue;
    980             		}
    981 		        trunk128 = soc_feature(unit, soc_feature_trunk_extended);
    982 			if (!trunk128)
    983 			{
    984 				tid &= SOC_L2X_TGID_PORT_TRUNK_MASK;
    985 				tid |= SOC_L2X_TGID_TRUNK_INDICATOR(unit);
    986 			}
    987             		if (soc_feature(unit, soc_feature_trunk_group_overlay)) {
    988                 		port_val = soc_mem_field32_get(unit, L2Xm, l2_entry, PORT_NUMf);
    989 				if (trunk128)
    990 				{
    991 					tid_val =  soc_mem_field32_get(unit, L2Xm, l2_entry, TGIDf);
    992 				}
    993             		} else {
    994                 		port_val = soc_mem_field32_get(unit, L2Xm, l2_entry, TGID_PORTf);
    995 				if (trunk128)
    996 				{
    997 					tgid_val = soc_mem_field32_get(unit, L2Xm, l2_entry, MODULE_IDf);
    998 			               	tgid_hi = (tid & SOC_L2X_TGID_PORT_TRUNK_MASK_HI) >> SOC_TRUNK_BIT_POS(unit);
    999 					tgid_lo = tid & SOC_L2X_TGID_PORT_TRUNK_MASK;
   1000 					tgid_lo |= SOC_L2X_TGID_TRUNK_INDICATOR(unit);
   1001 				}
   1002             		}
   1003 			mod_val 		= soc_mem_field32_get(unit,L2Xm,l2_entry,MODULE_IDf);
   1004 			static_bit_val 	= soc_mem_field32_get(unit,L2Xm,l2_entry,STATIC_BITf);
   1005 			pending_bit_val 	= soc_mem_field32_get(unit,L2Xm,l2_entry,PENDINGf);
   1006 			vlan_val 	= soc_mem_field32_get(unit,L2Xm,l2_entry,VLAN_IDf);
   1007 			vfi_val 		= soc_mem_field32_get(unit, L2Xm,l2_entry, VFIf);
   1008 			switch(sync_op)
   1009 			{
   1010 				case SOC_L2X_PORTMOD_DEL:
   1011                 			if (soc_mem_field32_get(unit, L2Xm, l2_entry, Tf)) {
   1012                     				continue;
   1013                 			}
   1014 					if ((port_val != port_age_rep_st->match_port) || (mod_val != port_age_rep_st->match_module)) {
   1015 						continue;
   1016 					}
   1017 					break;
   1018 				case SOC_L2X_VLAN_DEL:
   1019                				if (soc_mem_field32_get(unit, L2Xm, l2_entry, Tf)) {
   1020                					continue;
   1021                				}
   1022 					if (vlan_val != port_age_rep_st->match_vid) {
   1023 						continue;
   1024 					}
   1025 					break;
   1026 				case SOC_L2X_VFI_DEL:
   1027                     LOG_CLI((BSL_META_U(unit,
   1028                                         "NOT IMPLEMENTED!\n")));	
   1029 					continue;
   1030 				case SOC_L2X_PORTMOD_VLAN_DEL:
   1031                				if (soc_mem_field32_get(unit, L2Xm, l2_entry, Tf)) {
   1032                					continue;
   1033                				}
   1034 					if ((vlan_val != port_age_rep_st->match_vid) || (port_val != port_age_rep_st->match_port) || (mod_val != port_age_rep_st->match_module)) {
   1035 						continue;
   1036 					}
   1037 					break;
   1038 				case SOC_L2X_TRUNK_DEL:
   1039 				case SOC_L2X_TRUNK_VLAN_DEL:
   1040 					if(trunk128) {
   1041 						LOG_CLI((BSL_META_U(unit,
   1042                                                                     "Trunk128...\n")));
   1043 						if (soc_feature(unit, soc_feature_trunk_group_overlay)) {
   1044 				                    	if (!soc_mem_field32_get(unit, L2Xm, l2_entry, Tf)) {
   1045 								continue;
   1046 							}
   1047 							if (tid_val != port_age_rep_st->match_trunk) {
   1048 								continue;
   1049 							}
   1050 							}else {
   1051 								if ((tgid_lo != port_val) ||(tgid_hi != tgid_val)) {
   1052 									continue;
   1053 								}
   1054 							}
   1055 							if (sync_op == SOC_L2X_TRUNK_VLAN_DEL) {
   1056 								if(vlan_val != port_age_rep_st->match_vid) {
   1057 									continue;
   1058 								}
   1059 							}
   1060 						} else {
   1061 							if (port_val != port_age_rep_st->match_trunk) {
   1062 								continue;
   1063 							}
   1064 							if (sync_op == SOC_L2X_TRUNK_VLAN_DEL) {
   1065 								if(vlan_val != port_age_rep_st->match_vid) {
   1066 									continue;
   1067 								}
   1068 							}
   1069 						}
   1070 						break;
   1071 				default:
   1072 					continue;
   1073 			}
   1074 			/* Check for static entry deletion */
   1075 			if ( (port_age_flags & BCM_L2_REPLACE_MATCH_STATIC) != BCM_L2_REPLACE_MATCH_STATIC) {
   1076 				if (static_bit_val == 1) {
   1077                     LOG_CLI((BSL_META_U(unit,
   1078                                         "Skipped STATIC L2 Entry Deletion:"
   1079                                         "port_val:%d mod_id : %d static_bit_val : %d "
   1080                                         "pending_bit_val %d vlan_id : %d vfi_id : %d "
   1081                                         "\n"),
   1082                              port_val, mod_val, static_bit_val,
   1083                              pending_bit_val, vlan_val, vfi_val));
   1084 					continue;
   1085 				}
   1086 			}
   1087 			if( (port_age_flags & BCM_L2_REPLACE_PENDING) == BCM_L2_REPLACE_PENDING) {
   1088 				if (pending_bit_val != 1) {
   1089                     LOG_CLI((BSL_META_U(unit,
   1090                                         "Skipped Non Pending L2 Entry Deletion:"
   1091                                         "port_val:%d mod_id : %d static_bit_val : %d "
   1092                                         "pending_bit_val %d vlan_id : %d vfi_id : %d "
   1093                                         "\n"),
   1094                              port_val, mod_val, static_bit_val,
   1095                              pending_bit_val, vlan_val, vfi_val));
   1096 					continue;
   1097 				}
   1098 			}
   1099 			/* soc_mem_field32_set(unit,L2Xm, l2_entry,valid_bit,0); */
   1100 			rv = soc_mem_delete(unit, L2Xm, MEM_BLOCK_ALL, l2_entry);
   1101        			if (SOC_FAILURE(rv)) {
   1102 				break;
   1103        			}
   1104                 LOG_CLI((BSL_META_U(unit,
   1105                                     "Deleted L2 Entry:port_val:%d mod_id : %d "
   1106                                     "static_bit_val : %d pending_bit_val : %d "
   1107                                     "vlan_id : %d vfi_id : %d \n"),
   1108                          port_val, mod_val, static_bit_val,
   1109                          pending_bit_val, vlan_val, vfi_val));
   1110         	}
   1111 	}
   1112 	soc_cm_sfree(unit, l2_tbl_chnk);
   1113 	return SOC_E_NONE;
   1114 }
   1115 #endif
   1116 #endif
   1117 
   1118 #ifdef BCM_TRIDENT2_SUPPORT
   1119 STATIC int 
   1120 _soc_l2x_td2_convert_delete_to_replace(int unit) 
   1121 {
   1122     uint32 rval;  
   1123     SOC_IF_ERROR_RETURN(READ_L2_BULK_CONTROLr(unit, &rval));  
   1124     if (soc_reg_field_get(unit, L2_BULK_CONTROLr, rval, 
   1125                             ACTIONf) == 1) {
   1126         l2_bulk_replace_mask_entry_t repl_mask;
   1127         l2_bulk_replace_data_entry_t repl_data;
   1128         sal_memset(&repl_mask, 0xFF, sizeof(repl_mask));
   1129         sal_memset(&repl_data, 0, sizeof(repl_data));
   1130         SOC_IF_ERROR_RETURN
   1131             (WRITE_L2_BULK_REPLACE_MASKm(unit, MEM_BLOCK_ALL, 0, &repl_mask));
   1132         SOC_IF_ERROR_RETURN
   1133             (WRITE_L2_BULK_REPLACE_DATAm(unit, MEM_BLOCK_ALL, 0, &repl_data));
   1134         SOC_IF_ERROR_RETURN
   1135             (soc_reg_field32_modify(unit, L2_BULK_CONTROLr, REG_PORT_ANY, 
   1136                                     ACTIONf, 2));  
   1137     }  
   1138     return SOC_E_NONE;
   1139 }
   1140 
   1141 STATIC int 
   1142 _soc_l2x_td2_frozen_cml_restore(int unit) 
   1143 {
   1144     uint32       rval;
   1145     cml_freeze_t *f_cml = &cml_freeze_state[unit]; /* Cml freeze state.*/
   1146 
   1147 
   1148     SOC_CML_FREEZE_LOCK(unit);
   1149     /* If going out of freeze restore values to HW. */
   1150     if (f_cml->frozen == 1) {
   1151         SOC_IF_ERROR_RETURN(
   1152             READ_ING_MISC_CONFIG2r(unit, &rval));
   1153         soc_reg_field_set(unit, ING_MISC_CONFIG2r, &rval, 
   1154                                 CML_OVERRIDE_ENABLE_NEWf, 0);
   1155         soc_reg_field_set(unit, ING_MISC_CONFIG2r, &rval, 
   1156                                 CML_OVERRIDE_ENABLE_MOVEf, 0);
   1157         SOC_IF_ERROR_RETURN(
   1158             WRITE_ING_MISC_CONFIG2r(unit, rval));
   1159     } 
   1160 
   1161     /* Regardless of status, decrement frozen count. */
   1162     f_cml->frozen--;
   1163     SOC_CML_FREEZE_UNLOCK(unit);
   1164     return SOC_E_NONE;
   1165 }
   1166 
   1167 STATIC int 
   1168 _soc_l2x_td2_frozen_cml_save(int unit) 
   1169 {
   1170     uint32       rval;
   1171     cml_freeze_t *f_cml = &cml_freeze_state[unit]; /* Cml freeze state.*/
   1172 
   1173     SOC_CML_FREEZE_LOCK(unit);
   1174     /* Freezing l2 - disable learning. */
   1175     if (f_cml->frozen == 0) {
   1176         SOC_IF_ERROR_RETURN(
   1177             READ_ING_MISC_CONFIG2r(unit, &rval));
   1178         soc_reg_field_set(unit, ING_MISC_CONFIG2r, &rval, 
   1179                                 CML_OVERRIDE_ENABLE_NEWf, 1);
   1180         soc_reg_field_set(unit, ING_MISC_CONFIG2r, &rval, 
   1181                                 CML_OVERRIDE_ENABLE_MOVEf, 1);
   1182         SOC_IF_ERROR_RETURN(
   1183             WRITE_ING_MISC_CONFIG2r(unit, rval));
   1184     }
   1185 
   1186     /* Icrement CML frozen indicator. */
   1187     f_cml->frozen++;
   1188     SOC_CML_FREEZE_UNLOCK(unit);
   1189     return SOC_E_NONE;
   1190 }
   1191 
   1192 int 
   1193 soc_l2x_cml_override_is_enabled(int unit) 
   1194 {
   1195     uint32       rval = 0;
   1196     uint32       enable_newf = 0, enable_movef = 0;
   1197     int          rv = SOC_E_NONE;
   1198 
   1199     rv = READ_ING_MISC_CONFIG2r(unit, &rval);
   1200     if (rv != SOC_E_NONE) {
   1201         return 0;
   1202     }
   1203     enable_newf = soc_reg_field_get(unit, ING_MISC_CONFIG2r,
   1204                                         rval, CML_OVERRIDE_ENABLE_NEWf);
   1205 
   1206     enable_movef = soc_reg_field_get(unit, ING_MISC_CONFIG2r,
   1207                                          rval, CML_OVERRIDE_ENABLE_MOVEf);
   1208 
   1209     rval = (enable_newf == 0 && enable_movef == 0)? 0:1;
   1210     return rval;
   1211 }
   1212 
   1213 #endif /* BCM_TRIDENT2_SUPPORT */
   1214 
   1215 #ifdef BCM_WARM_BOOT_SUPPORT
   1216 /*
   1217  * Function:
   1218  *      soc_l2x_wb_scache_size_get
   1219  * Purpose:
   1220  *      Returns required scache size for L2 part
   1221  * Parameters:
   1222  *      unit                 - (IN)  Unit number.
   1223  *      req_scache_size      - (OUT) Request scache size
   1224  * Returns:
   1225  *      SOC_E_XXX
   1226  * Notes:
   1227  */
   1228 int
   1229 soc_l2x_wb_scache_size_get(int unit, int *req_scache_size)
   1230 {
   1231     int alloc_size = 0;
   1232 
   1233     alloc_size += sizeof(l2_freeze_mode);
   1234     *req_scache_size += alloc_size;
   1235     return SOC_E_NONE;
   1236 }
   1237 
   1238 /*
   1239  * Function:
   1240  *      soc_l2x_scache_sync
   1241  * Purpose:
   1242  *      Syncs L2 part warmboot state to scache
   1243  * Parameters:
   1244  *      unit                 - (IN)  Unit number.
   1245  *      scache_ptr           - (IN)  Scache pointer.
   1246  * Returns:
   1247  *      SOC_E_XXX
   1248  * Notes:
   1249  */
   1250 int
   1251 soc_l2x_scache_sync(int unit, uint8 **scache_ptr)
   1252 {
   1253     int *iptr = NULL;
   1254 
   1255     iptr = (int *)(*scache_ptr);
   1256     *iptr = l2_freeze_mode[unit];
   1257     iptr++;
   1258     *scache_ptr = (uint8 *)iptr;
   1259 
   1260     return SOC_E_NONE;
   1261 }
   1262 
   1263 /*
   1264  * Function:
   1265  *      soc_l2x_reinit
   1266  * Purpose:
   1267  *      Recovers L2 part warmboot state from scache
   1268  * Parameters:
   1269  *      unit                 - (IN)  Unit number.
   1270  *      scache_ptr           - (IN)  Scache pointer.
   1271  * Returns:
   1272  *      SOC_E_XXX
   1273  * Notes:
   1274  */
   1275 int
   1276 soc_l2x_reinit(int unit, uint8 **scache_ptr)
   1277 {
   1278     int *iptr = NULL;
   1279 
   1280     iptr = (int *)(*scache_ptr);
   1281     l2_freeze_mode[unit] = *iptr;
   1282     iptr++;
   1283     *scache_ptr = (uint8 *)iptr;
   1284 
   1285     return SOC_E_NONE;
   1286 }
   1287 #endif /* BCM_WARM_BOOT_SUPPORT */
   1288 
   1289 /*
   1290  * Function:
   1291  *      soc_l2x_freeze_mode_is_global_override
   1292  * Description:
   1293  *      Check if SDK is using global override to freeze L2X.
   1294  * Parameters:
   1295  *      unit      - (IN) Device number
   1296  * Return Value:
   1297  *      TRUE / FALSE
   1298  */
   1299 int
   1300 soc_l2x_freeze_mode_is_global_override(int unit)
   1301 {
   1302     return (l2_freeze_mode[unit] == SOC_L2X_FREEZE_MODE_GLOBAL_OVERRIDE)? \
   1303             TRUE:FALSE;
   1304 }
   1305 
   1306 /*
   1307  * Function:
   1308  *      soc_l2x_freeze_mode_set
   1309  * Description:
   1310  *      Record configured freeze mode.
   1311  *      Mode cannot be changed during frozen. Because freeze/thaw should
   1312  *      be executed with the same mode.
   1313  * Parameters:
   1314  *      unit      - (IN) Device number
   1315  *      mode      - (IN) Mode to use
   1316  * Return Value:
   1317  *      SOC_E_XXX
   1318  */
   1319 int
   1320 soc_l2x_freeze_mode_set(int unit, int mode)
   1321 {
   1322     int frozen = 0;
   1323     int cur_mode = 0;
   1324 
   1325     SOC_IF_ERROR_RETURN(soc_l2x_freeze_mode_get(unit, &cur_mode));
   1326     if (mode == cur_mode) {
   1327         return SOC_E_NONE;
   1328     }
   1329     SOC_IF_ERROR_RETURN(soc_l2x_is_frozen(unit, SOC_L2X_FROZEN, &frozen));
   1330     if (frozen) {
   1331         return SOC_E_BUSY;
   1332     } else {
   1333         l2_freeze_mode[unit] = mode;
   1334     }
   1335 
   1336     return SOC_E_NONE;
   1337 }
   1338 
   1339 /*
   1340  * Function:
   1341  *      soc_l2x_freeze_mode_get
   1342  * Description:
   1343  *      Retrieve configured freeze mode..
   1344  * Parameters:
   1345  *      unit      - (IN)  Device number
   1346  *      mode      - (OUT) Mode in use
   1347  * Return Value:
   1348  *      SOC_E_XXX
   1349  */
   1350 int
   1351 soc_l2x_freeze_mode_get(int unit, int *mode)
   1352 {
   1353     if (mode == NULL) {
   1354         return SOC_E_PARAM;
   1355     }
   1356     *mode = l2_freeze_mode[unit];
   1357 
   1358     return SOC_E_NONE;
   1359 }
   1360 
   1361 /*
   1362  * Function:
   1363  *	_soc_l2x_port_age
   1364  * Purpose:
   1365  *	Use HW port/VLAN "aging" to delete selected L2 entries.
   1366  * Parameters:
   1367  *	unit	     - StrataSwitch unit #
   1368  *      age_reg0     - port aging register.
   1369  *	age_reg1     - optioanl 2nd port aging register.
   1370  * Returns:
   1371  *	SOC_E_XXX
   1372  * Notes:
   1373  *	Hardware deletion is used.
   1374  *	The chip requires that ARL aging be disabled during this
   1375  *	operation.  An unavoidable side effect is that the hardware
   1376  *	aging timer gets restarted whenever this routine is called.
   1377  */
   1378 int
   1379 soc_l2x_port_age(int unit, soc_reg_t reg0, soc_reg_t reg1)
   1380 {
   1381     static soc_field_t  fields[2] = { STARTf, COMPLETEf };
   1382     static uint32       values[2] = { 1, 0 };
   1383     soc_timeout_t	to;
   1384     int			rv;
   1385     int			timeout_usec;
   1386     int                 reg0_complete, reg1_complete;
   1387     uint32              rval;
   1388     int                 mode;
   1389 #ifdef BCM_TRIDENT2_SUPPORT
   1390     soc_control_t *soc = SOC_CONTROL(unit);
   1391 #endif
   1392 #ifdef BCM_HURRICANE3_SUPPORT
   1393     uint64              rval64;
   1394 #endif
   1395 
   1396     if (reg0 == INVALIDr && reg1 == INVALIDr) {
   1397         return SOC_E_NONE;
   1398     }
   1399 
   1400     timeout_usec = SOC_CONTROL(unit)->l2x_age_timeout;
   1401     mode = SOC_CONTROL(unit)->l2x_mode;
   1402 
   1403     if (mode != L2MODE_FIFO) {
   1404         if (SOC_IS_TOMAHAWKX(unit) || SOC_IS_TRIDENT3X(unit)) {
   1405             SOC_IF_ERROR_RETURN(_soc_l2x_frozen_cml_save(unit));
   1406         } else {
   1407             SOC_IF_ERROR_RETURN(soc_l2x_freeze(unit));
   1408         }
   1409     }
   1410 
   1411 #ifdef BCM_TRIDENT2_SUPPORT
   1412     if (SOC_IS_TRIDENT2(unit) || SOC_IS_TITAN2(unit)) {
   1413         /* if action == 1, convert action to 2 and replace data to be 0 */
   1414         /* TD3TBD, does TD3 need this? */
   1415         rv = _soc_l2x_td2_convert_delete_to_replace(unit);
   1416         if (SOC_FAILURE(rv)) {
   1417             goto exit;
   1418         }
   1419     }
   1420 #endif
   1421 
   1422 #ifdef BCM_TRIDENT2_SUPPORT
   1423     if (soc_feature(unit, soc_feature_l2_hw_aging_bug) &&
   1424         sal_thread_self() == soc->l2x_age_pid) {
   1425         TABLE_DMA_LOCK(unit);
   1426         SOC_SBUSDMA_DM_LOCK(unit);
   1427         SCHAN_LOCK(unit);
   1428     }
   1429 #endif
   1430 
   1431     reg0_complete = TRUE;
   1432     if (reg0 != INVALIDr) {
   1433         rv = soc_reg_fields32_modify(unit, reg0, REG_PORT_ANY, 2, fields,
   1434                                      values);
   1435         if (SOC_FAILURE(rv)) {
   1436             goto done;
   1437         }
   1438         reg0_complete = FALSE;
   1439     }
   1440 
   1441     reg1_complete = TRUE;
   1442     if (reg1 != INVALIDr) {
   1443         rv = soc_reg_fields32_modify(unit, reg1, REG_PORT_ANY, 2, fields,
   1444                                      values);
   1445         if (SOC_FAILURE(rv)) {
   1446             goto done;
   1447         }
   1448         reg1_complete = FALSE;
   1449     }
   1450 
   1451     SOC_CONTROL(unit)->l2x_ppa_in_progress = TRUE;
   1452     soc_timeout_init(&to, timeout_usec, 0);
   1453     for (;;) {
   1454         if (!reg0_complete) {
   1455 #ifdef BCM_HURRICANE3_SUPPORT
   1456             if ((SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) && 
   1457                 reg0 == PER_PORT_AGE_CONTROL_64r) {
   1458                 rv = soc_reg64_get(unit, reg0, REG_PORT_ANY, 0, &rval64);
   1459                 if (SOC_SUCCESS(rv)) {
   1460                     reg0_complete = soc_reg64_field32_get(unit, reg0, rval64, COMPLETEf);
   1461                 }
   1462             } else 
   1463 #endif
   1464             {
   1465                 rv = soc_reg32_get(unit, reg0, REG_PORT_ANY, 0, &rval);
   1466                 if (SOC_SUCCESS(rv)) {
   1467                     reg0_complete = soc_reg_field_get(unit, reg0, rval, COMPLETEf);
   1468                 }
   1469             }
   1470         }
   1471         if (!reg1_complete) {
   1472             rv = soc_reg32_get(unit, reg1, REG_PORT_ANY, 0, &rval);
   1473             if (SOC_SUCCESS(rv)) {
   1474                 reg1_complete = soc_reg_field_get(unit, reg1, rval, COMPLETEf);
   1475             }
   1476         }
   1477 
   1478         if (reg0_complete && reg1_complete) {
   1479             rv = SOC_E_NONE;
   1480             break;
   1481         }
   1482 
   1483         if (soc_timeout_check(&to)) {
   1484             rv = SOC_E_TIMEOUT;
   1485             break;
   1486         }
   1487     }
   1488 
   1489  done:
   1490 #ifdef BCM_TRIDENT2_SUPPORT
   1491     if (soc_feature(unit, soc_feature_l2_hw_aging_bug) &&
   1492         sal_thread_self() == soc->l2x_age_pid) {
   1493         SCHAN_UNLOCK(unit);
   1494         SOC_SBUSDMA_DM_UNLOCK(unit);
   1495         TABLE_DMA_UNLOCK(unit);
   1496     }
   1497 
   1498  exit:
   1499 #endif
   1500     SOC_CONTROL(unit)->l2x_ppa_in_progress = FALSE;
   1501     if (mode != L2MODE_FIFO) {
   1502         if (SOC_IS_TOMAHAWKX(unit) || SOC_IS_TRIDENT3X(unit)) {
   1503             SOC_IF_ERROR_RETURN(_soc_l2x_frozen_cml_restore(unit));
   1504         } else {
   1505             SOC_IF_ERROR_RETURN(soc_l2x_thaw(unit));
   1506         }
   1507     }
   1508 #ifdef PLISIM
   1509 #ifdef _KATANA_DEBUG /* BCM_KATANA_SUPPORT */
   1510     if (SAL_BOOT_PLISIM) {
   1511         if ((rv == SOC_E_NONE) && (SOC_IS_KATANA(unit))) {
   1512             perform_port_age_simulation(unit);
   1513         }
   1514     }
   1515 #endif
   1516 #endif
   1517     return rv;
   1518 }
   1519 
   1520 #ifdef BCM_TRIDENT3_SUPPORT
   1521 int
   1522 soc_l2x_cml_register(int unit, soc_l2x_cml_cb_fn fn)
   1523 {
   1524     cml_freeze_t  *f_cml = &cml_freeze_state[unit];
   1525     f_cml->cml_func = fn;
   1526     return SOC_E_NONE;
   1527 }
   1528 #endif/*BCM_TRIDENT3_SUPPORT*/
   1529 /*
   1530  * Function:
   1531  *  	_soc_l2x_frozen_cml_restore
   1532  * Purpose:
   1533  *  	Helper function to restore port learning mode.
   1534  * Parameters:
   1535  *   	unit - (IN) BCM device number.
   1536  * Returns:
   1537  *	    SOC_E_XXX
   1538  */
   1539 int 
   1540 _soc_l2x_frozen_cml_restore(int unit)
   1541 {
   1542     cml_freeze_t		*f_cml = &cml_freeze_state[unit]; /* Cml freeze state.*/
   1543     soc_port_t		    port;                /* Device port iterator.         */ 
   1544     port_tab_entry_t    pent;                /* Port table hw entry buffer.   */
   1545     int                 cml;                 /* Learn mode for specific port. */ 
   1546     int                 rv = SOC_E_NONE;     /* Operation return status.      */
   1547     soc_pbmp_t          pbmp;
   1548 
   1549 #ifdef BCM_TRIDENT2_SUPPORT
   1550     if (SOC_IS_TD2_TT2(unit) &&
   1551         soc_l2x_freeze_mode_is_global_override(unit)) {
   1552         return _soc_l2x_td2_frozen_cml_restore(unit);
   1553     }
   1554 #endif
   1555 
   1556     SOC_PBMP_CLEAR(pbmp);
   1557     /* Take protection mutex. */ 
   1558     if (SOC_MEM_IS_VALID(unit, PORT_TABm)) {
   1559         soc_mem_lock(unit, PORT_TABm);
   1560     }
   1561     if (SOC_MEM_IS_VALID(unit, SOURCE_VPm)) {
   1562         soc_mem_lock(unit, SOURCE_VPm);
   1563     }
   1564 
   1565     /* If going out of freeze restore sw preserved values to HW. */
   1566     if (f_cml->frozen == 1) {
   1567         SOC_PBMP_ASSIGN(pbmp, PBMP_PORT_ALL(unit));
   1568 #ifdef BCM_KATANA2_SUPPORT
   1569         if (soc_feature(unit, soc_feature_linkphy_coe) ||
   1570             soc_feature(unit, soc_feature_subtag_coe)) {
   1571             _bcm_kt2_subport_pbmp_update(unit, &pbmp);
   1572         }
   1573 #endif
   1574         PBMP_ITER(pbmp, port) {
   1575             /* Read port table entry. */
   1576             if (!SOC_IS_TRIDENT3X(unit)) {
   1577                 rv = READ_PORT_TAB_MOD_CHK(unit, MEM_BLOCK_ANY, port, &pent);
   1578                 if (SOC_FAILURE(rv)) {
   1579                     break;
   1580                 }
   1581             }
   1582             /* Get port current learning mode. */
   1583 #ifdef BCM_TRIDENT3_SUPPORT
   1584            if (SOC_IS_TRIDENT3X(unit)) {
   1585                /*mem write is not allowed during WB*/
   1586                if (SOC_WARM_BOOT(unit)) {
   1587                    break;
   1588                }
   1589                if (f_cml->cml_func == NULL) {
   1590                    rv = SOC_E_FAIL;
   1591                    break;
   1592                }
   1593                rv = f_cml->cml_func(unit, port, FALSE,
   1594                                     &f_cml->save_cml[port],
   1595                                     &f_cml->save_cml_move[port]);
   1596                if (SOC_FAILURE(rv)) {
   1597                     break;
   1598                }
   1599             } else
   1600 #endif /*BCM_TRIDENT3_SUPPORT*/
   1601 #ifdef BCM_TRX_SUPPORT
   1602             if (SOC_IS_TRX(unit)) {
   1603                 int cml_change = FALSE;
   1604                 cml = soc_PORT_TABm_field32_get(unit, &pent, CML_FLAGS_NEWf);
   1605                 if (cml != f_cml->save_cml[port]) {
   1606                     soc_PORT_TABm_field32_set(unit, &pent, CML_FLAGS_NEWf,
   1607                                               f_cml->save_cml[port]);
   1608                     cml_change = TRUE;
   1609                 }
   1610                 cml = soc_PORT_TABm_field32_get(unit, &pent, CML_FLAGS_MOVEf);
   1611                 if (cml != f_cml->save_cml_move[port]) {
   1612                     soc_PORT_TABm_field32_set(unit, &pent, CML_FLAGS_MOVEf,
   1613                                               f_cml->save_cml_move[port]);
   1614                     cml_change = TRUE;
   1615                 }
   1616                 if (cml_change) {
   1617                     rv = WRITE_PORT_TAB_MOD_CHK(unit, MEM_BLOCK_ALL, port,
   1618                                                  &pent);
   1619                     if (SOC_FAILURE(rv)) {
   1620                         break;
   1621                     }
   1622                 }
   1623             } else
   1624 #endif /* BCM_TRX_SUPPORT */
   1625             {
   1626                 cml = soc_PORT_TABm_field32_get(unit, &pent, CMLf);
   1627                 /* Update mode if necessary. */
   1628                 if (cml != f_cml->save_cml[port]) {
   1629                     soc_PORT_TABm_field32_set(unit, &pent, CMLf, 
   1630                                               f_cml->save_cml[port]);
   1631                     rv = WRITE_PORT_TAB_MOD_CHK(unit, MEM_BLOCK_ALL, port, 
   1632                                                 &pent);
   1633                     if (SOC_FAILURE(rv)) {
   1634                         break;
   1635                     }
   1636                 }
   1637             }
   1638         } 
   1639         /* Restore CML value and on Virtual ports */
   1640         if (SOC_SUCCESS(rv) && SOC_MEM_IS_VALID(unit, SOURCE_VPm) &&
   1641             (NULL != f_cml->vp_bitmap)) {
   1642             int  index, index_min, index_max, buf_index, count;
   1643             void *svp, *buf;
   1644 
   1645             index_min = soc_mem_index_min(unit, SOURCE_VPm);
   1646             index_max = soc_mem_index_max(unit, SOURCE_VPm);
   1647             index_min += 1; /* Always skip entry 0 of SVP table */
   1648 
   1649             if (!shr_bitop_range_null(f_cml->vp_bitmap, index_min,
   1650                                       (index_max - index_min + 1))) {
   1651                 buf = soc_cm_salloc(unit,
   1652                                     SOC_MEM_TABLE_BYTES(unit, SOURCE_VPm),
   1653                                     "source_vp for cml restore");
   1654                 if (buf == NULL) {
   1655                     rv = SOC_E_MEMORY;
   1656                 }
   1657 
   1658                 if (SOC_SUCCESS(rv)) {
   1659                 rv = soc_mem_read_range(unit, SOURCE_VPm, MEM_BLOCK_ANY,
   1660                                         index_min, index_max, buf);
   1661                 }
   1662                 if (SOC_SUCCESS(rv)) {
   1663                     count = 0;
   1664                     for (index = index_min; index < index_max; index++) {
   1665                         if (!SHR_BITGET(f_cml->vp_bitmap, index)) {
   1666                             /* VP not in use */
   1667                             continue;
   1668                         }
   1669                         buf_index = index - index_min;
   1670                         svp = soc_mem_table_idx_to_pointer
   1671                             (unit, SOURCE_VPm, void *, buf, buf_index);
   1672                         if (soc_mem_field32_get(unit, SOURCE_VPm, svp,
   1673                                                 ENTRY_TYPEf) == 0) {
   1674                             continue;
   1675                         }
   1676                         soc_mem_field32_set
   1677                             (unit, SOURCE_VPm, svp, CML_FLAGS_MOVEf,
   1678                              f_cml->save_vp_cml_move[buf_index]);
   1679                         soc_mem_field32_set
   1680                             (unit, SOURCE_VPm, svp, CML_FLAGS_NEWf,
   1681                              f_cml->save_vp_cml[buf_index]);
   1682                         count++;
   1683                     }
   1684                     if (count > 0) {
   1685                         rv = soc_mem_write_range(unit, SOURCE_VPm,
   1686                                                  MEM_BLOCK_ANY, index_min,
   1687                                                  index_max, buf);
   1688                     }
   1689                 }
   1690                 if (buf != NULL) {
   1691                     soc_cm_sfree(unit, buf);
   1692                 } /* Else not using any VPs, don't process the SVP table. */
   1693             }
   1694         }
   1695     } 
   1696 
   1697     /* Regardless of status, decrement frozen count. */
   1698     f_cml->frozen--;
   1699 
   1700     /* Release protection mutex. */ 
   1701     if (SOC_MEM_IS_VALID(unit, SOURCE_VPm)) {
   1702         soc_mem_unlock(unit, SOURCE_VPm);
   1703     }
   1704     if (SOC_MEM_IS_VALID(unit, PORT_TABm)) {
   1705         soc_mem_unlock(unit, PORT_TABm);
   1706     }
   1707     return (rv);
   1708 }
   1709 
   1710 
   1711 /*
   1712  * Function:
   1713  *  	_soc_l2x_frozen_cml_save
   1714  * Purpose:
   1715  *  	Helper function to preserve port learning mode in sw structure.
   1716  * Parameters:
   1717  *   	unit - (IN) BCM device number.
   1718  * Returns:
   1719  *	    SOC_E_XXX
   1720  */
   1721 int
   1722 _soc_l2x_frozen_cml_save(int unit)
   1723 {
   1724     cml_freeze_t		*f_cml = &cml_freeze_state[unit]; /* Cml freeze state.*/
   1725     soc_port_t		    port;                /* Device port iterator.         */
   1726     port_tab_entry_t    pent;                /* Port table hw entry buffer.   */
   1727     int                 rv = SOC_E_NONE;     /* Operation return status.      */
   1728     soc_pbmp_t          pbmp;
   1729 
   1730 #ifdef BCM_TRIDENT2_SUPPORT
   1731     if (SOC_IS_TD2_TT2(unit) &&
   1732         soc_l2x_freeze_mode_is_global_override(unit)) {
   1733         return _soc_l2x_td2_frozen_cml_save(unit);
   1734     }
   1735 #endif
   1736 
   1737     SOC_PBMP_CLEAR(pbmp);
   1738 
   1739     /* Take protection mutex. */ 
   1740     if (SOC_MEM_IS_VALID(unit, PORT_TABm)) {
   1741         soc_mem_lock(unit, PORT_TABm);
   1742     }
   1743     if (SOC_MEM_IS_VALID(unit, SOURCE_VPm)) {
   1744         soc_mem_lock(unit, SOURCE_VPm);
   1745     }
   1746 
   1747     /* Freezing l2 save l2 learn mode and disable learning. */
   1748     if (f_cml->frozen == 0) {
   1749         SOC_PBMP_ASSIGN(pbmp, PBMP_PORT_ALL(unit));
   1750 #ifdef BCM_KATANA2_SUPPORT
   1751         if (soc_feature(unit, soc_feature_linkphy_coe) ||
   1752             soc_feature(unit, soc_feature_subtag_coe)) {
   1753             _bcm_kt2_subport_pbmp_update(unit, &pbmp);
   1754         }
   1755 #endif
   1756         PBMP_ITER(pbmp, port) {
   1757             /* Read port table entry. */
   1758             if (!SOC_IS_TRIDENT3X(unit)) {
   1759                 rv = READ_PORT_TAB_MOD_CHK(unit, MEM_BLOCK_ANY, port, &pent);
   1760                 if (SOC_FAILURE(rv)) {
   1761                     break;
   1762                 }
   1763             }
   1764 #ifdef BCM_TRIDENT3_SUPPORT
   1765            if (SOC_IS_TRIDENT3X(unit)) {
   1766                /*mem write is not allowed during WB*/
   1767                if (SOC_WARM_BOOT(unit)) {
   1768                    break;
   1769                }
   1770                if (f_cml->cml_func == NULL) {
   1771                    rv = SOC_E_FAIL;
   1772                    break;
   1773                }
   1774                rv = f_cml->cml_func(unit, port, TRUE,
   1775                                     &f_cml->save_cml[port],
   1776                                     &f_cml->save_cml_move[port]);
   1777                if (SOC_FAILURE(rv)) {
   1778                     break;
   1779                }
   1780             } else
   1781 #endif /*BCM_TRIDENT3_SUPPORT*/
   1782 #ifdef BCM_TRX_SUPPORT
   1783             if (SOC_IS_TRX(unit)) {
   1784                 f_cml->save_cml[port] =
   1785                     soc_PORT_TABm_field32_get(unit, &pent, CML_FLAGS_NEWf);
   1786                 f_cml->save_cml_move[port] =
   1787                     soc_PORT_TABm_field32_get(unit, &pent, CML_FLAGS_MOVEf);
   1788 
   1789                 /* Set bits to the equivilant of DROP and COPY TO CPU */
   1790                 soc_PORT_TABm_field32_set(unit, &pent, CML_FLAGS_NEWf,
   1791                                           f_cml->save_cml[port] & 0x03);
   1792                 soc_PORT_TABm_field32_set(unit, &pent, CML_FLAGS_MOVEf,
   1793                                           f_cml->save_cml_move[port] & 0x03);
   1794                 rv = WRITE_PORT_TAB_MOD_CHK(unit, MEM_BLOCK_ALL, port, &pent);
   1795                 if (SOC_FAILURE(rv)) {
   1796                     break;
   1797                 }
   1798             } else
   1799 #endif /* BCM_TRX_SUPPORT */
   1800             {
   1801                 /* Save current learning mode in sw structure. */
   1802                 f_cml->save_cml[port] = soc_PORT_TABm_field32_get(unit, &pent, CMLf);
   1803 
   1804                 /* Disable L2 learning on the port. */
   1805                 if ((f_cml->save_cml[port] == PVP_CML_SWITCH) ||
   1806                     (f_cml->save_cml[port] == PVP_CML_CPU_SWITCH)) {
   1807                     soc_PORT_TABm_field32_set(unit, &pent, CMLf, PVP_CML_FORWARD);
   1808                     rv = WRITE_PORT_TAB_MOD_CHK(unit, MEM_BLOCK_ALL, port, &pent);
   1809                     if (SOC_FAILURE(rv)) {
   1810                         break;
   1811                     }
   1812                 } 
   1813             }
   1814         }
   1815 
   1816         /* Saving CML value and disable learning on Virtual ports */
   1817         if (SOC_SUCCESS(rv) && SOC_MEM_IS_VALID(unit, SOURCE_VPm) &&
   1818             (NULL != f_cml->vp_bitmap)) {
   1819             int  index, index_min, index_max, buf_index, count;
   1820             void *svp, *buf;
   1821 
   1822             index_min = soc_mem_index_min(unit, SOURCE_VPm);
   1823             index_max = soc_mem_index_max(unit, SOURCE_VPm);
   1824             index_min += 1; /* Always skip entry 0 of SVP table */
   1825 
   1826             if (!shr_bitop_range_null(f_cml->vp_bitmap, index_min,
   1827                                       (index_max - index_min + 1))) {
   1828                 buf = soc_cm_salloc(unit,
   1829                                     SOC_MEM_TABLE_BYTES(unit, SOURCE_VPm),
   1830                                     "source_vp for cml restore");
   1831                 if (buf == NULL) {
   1832                     rv = SOC_E_MEMORY;
   1833                 }
   1834 
   1835                 if (SOC_SUCCESS(rv)) {
   1836                     rv = soc_mem_read_range(unit, SOURCE_VPm, MEM_BLOCK_ANY,
   1837                                             index_min, index_max, buf);
   1838                 }
   1839                 if (SOC_SUCCESS(rv)) {
   1840                     count = 0;
   1841                     for (index = index_min; index < index_max; index++) {
   1842                         if (!SHR_BITGET(f_cml->vp_bitmap, index)) {
   1843                             /* VP not in use */
   1844                             continue;
   1845                         }
   1846                         buf_index = index - index_min;
   1847                         svp = soc_mem_table_idx_to_pointer
   1848                             (unit, SOURCE_VPm, void *, buf, buf_index);
   1849                         if (soc_mem_field32_get(unit, SOURCE_VPm, svp,
   1850                                                 ENTRY_TYPEf) == 0) {
   1851                             continue;
   1852                         }
   1853                         f_cml->save_vp_cml_move[buf_index] =
   1854                             soc_mem_field32_get(unit, SOURCE_VPm, svp,
   1855                                                 CML_FLAGS_MOVEf);
   1856                         f_cml->save_vp_cml[buf_index] =
   1857                             soc_mem_field32_get(unit, SOURCE_VPm, svp,
   1858                                                 CML_FLAGS_NEWf);
   1859                         /* Set bits to the equivilant of DROP and COPY TO CPU */
   1860                         soc_mem_field32_set(unit, SOURCE_VPm, svp,
   1861                                             CML_FLAGS_MOVEf,
   1862                                             f_cml->save_vp_cml_move[buf_index] &
   1863                                             0x03);
   1864                         soc_mem_field32_set(unit, SOURCE_VPm, svp,
   1865                                             CML_FLAGS_NEWf,
   1866                                             f_cml->save_vp_cml[buf_index] &
   1867                                             0x03);
   1868                         count++;
   1869                     }
   1870                     if (count > 0) {
   1871                         rv = soc_mem_write_range(unit, SOURCE_VPm,
   1872                                                  MEM_BLOCK_ANY, index_min,
   1873                                                  index_max, buf);
   1874                     }
   1875                 }
   1876                 if (buf != NULL) {
   1877                     soc_cm_sfree(unit, buf);
   1878                 }
   1879             } /* Else not using any VPs, don't process the SVP table. */
   1880         }
   1881     } 
   1882 
   1883     /* Increase CML frozen indicator. */
   1884     if (SOC_SUCCESS(rv)) {
   1885         f_cml->frozen++;
   1886     }
   1887     if (SOC_MEM_IS_VALID(unit, SOURCE_VPm)) {
   1888         soc_mem_unlock(unit, SOURCE_VPm); /* UNLOCK Virtual port */
   1889     }
   1890     if (SOC_MEM_IS_VALID(unit, PORT_TABm)) {
   1891         soc_mem_unlock(unit, PORT_TABm);	/* PORT_UNLOCK */
   1892     }
   1893     return(rv);  
   1894 }
   1895 
   1896 /*
   1897  * Function:
   1898  *	    soc_l2x_is_frozen
   1899  * Purpose:
   1900  *   	Provides indication if L3 table is in frozen state
   1901  * Parameters:
   1902  *	   unit - (IN) BCM device number.
   1903  *     frozen - (OUT) TRUE if L2x is frozen, FLASE otherwise
   1904  * Returns:
   1905  *	   SOC_E_NONE
   1906  * Notes:
   1907  *	Does not change the frozen status of L2x table only reads it.
   1908  */
   1909 
   1910 int
   1911 soc_l2x_is_frozen(int unit, int frozen_type, int *frozen)
   1912 {
   1913     l2_freeze_t		    *f_l2 = &l2_freeze_state[unit];
   1914 
   1915 #ifdef BCM_TRIUMPH3_SUPPORT
   1916     if (SOC_IS_TRIUMPH3(unit)) {
   1917         return soc_tr3_l2_is_frozen(unit, frozen);
   1918     }
   1919 #endif
   1920     if (frozen_type == SOC_L2X_FROZEN_WITH_LOCK) {
   1921         *frozen = (f_l2->frozen > 0) ? TRUE : FALSE ;
   1922     } else if (frozen_type == SOC_L2X_FROZEN_WITHOUT_LOCK) {
   1923         *frozen = (f_l2->hw_frozen > 0) ? TRUE : FALSE ;
   1924     } else {
   1925         *frozen = (f_l2->frozen > 0 || f_l2->hw_frozen > 0) ? TRUE : FALSE ;
   1926     }
   1927     return (SOC_E_NONE);
   1928 }
   1929 
   1930 /*
   1931  * Function:
   1932  *	    soc_age_timer_cache_set
   1933  * Purpose:
   1934  *   	set value of l2_freeze_state[unit].save_age_ena
   1935  *    and l2_freeze_state[unit].save_age_sec
   1936  * Parameters:
   1937  *	   unit - (IN) BCM device number.
   1938  * Returns:
   1939  *	   NONE
   1940  */
   1941 void
   1942 soc_age_timer_cache_set(int unit, int age_seconds, int enabled)
   1943 {
   1944     l2_freeze_t		    *f_l2 = &l2_freeze_state[unit];
   1945 
   1946     f_l2->save_age_sec = age_seconds;
   1947     f_l2->save_age_ena = enabled;
   1948     f_l2->new_age_set = 1;
   1949     return;
   1950 }
   1951 
   1952 /*
   1953  * Function:
   1954  *	    soc_age_timer_cache_get
   1955  * Purpose:
   1956  *   	get value of l2_freeze_state[unit].save_age_ena
   1957  *    and l2_freeze_state[unit].save_age_sec
   1958  * Parameters:
   1959  *	   unit - (IN) BCM device number.
   1960  * Returns:
   1961  *	   NONE
   1962  */
   1963 void
   1964 soc_age_timer_cache_get(int unit, int *age_seconds, int *enabled)
   1965 {
   1966     l2_freeze_t		    *f_l2 = &l2_freeze_state[unit];
   1967 
   1968     *age_seconds = f_l2->save_age_sec;
   1969     *enabled = f_l2->save_age_ena;
   1970     return;
   1971 }
   1972 
   1973 /*
   1974  * Function:
   1975  *	    soc_l2x_selective_freeze
   1976  * Purpose:
   1977  *   	Temporarily quiesce L2 table from H/W activity (learning, aging)
   1978  *    Does not quiesce S/W activity
   1979  * Parameters:
   1980  *	   unit - (IN) BCM device number. 
   1981  * freeze_mode -(IN) 1: Only H/W is frozen
   1982  * Returns:
   1983  *	   SOC_E_XXX
   1984  */
   1985 
   1986 /*soc_l2x_selective_freeze matches with soc_l2x_selective_thaw */
   1987 int
   1988 soc_l2x_selective_freeze(int unit, int freeze_mode)
   1989 {
   1990     l2_freeze_t		    *f_l2 = &l2_freeze_state[unit];
   1991     int                 rv = SOC_E_NONE;
   1992     int                 age_sec = 0;
   1993     int                 age_ena = 0;
   1994 
   1995     /* Check if already frozen. */
   1996     SOC_L2X_MEM_LOCK(unit);
   1997     if (f_l2->frozen > 0 || f_l2->hw_frozen > 0) {
   1998         /* Keep count - do nothing. */
   1999         if (freeze_mode == SOC_L2X_FROZEN_WITH_LOCK) {
   2000             f_l2->frozen++;
   2001         } else {
   2002             f_l2->hw_frozen++;
   2003         }
   2004         SOC_L2X_MEM_UNLOCK(unit);
   2005         return (SOC_E_NONE);
   2006     }
   2007 
   2008     /*
   2009      * Increase l2 frozen indicator in the beginning to
   2010      * avoid _soc_l2x_frozen_cml_save() being called twice
   2011      * in reentrance unexpectedly.
   2012      */
   2013     if (freeze_mode == SOC_L2X_FROZEN_WITH_LOCK) {
   2014         f_l2->frozen++;
   2015     } else {
   2016         f_l2->hw_frozen++;
   2017     }
   2018     SOC_L2X_MEM_UNLOCK(unit);
   2019 
   2020     /* Preserve ports learning mode & disable learning. */
   2021     rv = _soc_l2x_frozen_cml_save(unit);
   2022     if (SOC_FAILURE(rv)) {
   2023         /* Decrease l2 frozen indicator. */
   2024         if (freeze_mode == SOC_L2X_FROZEN_WITH_LOCK) {
   2025             f_l2->frozen--;
   2026         } else {
   2027             f_l2->hw_frozen--;
   2028         }
   2029         return rv;
   2030     }
   2031 
   2032     /*
   2033      * Lock l2x, disable learning and aging.
   2034      */
   2035     SOC_L2X_MEM_LOCK(unit);
   2036 
   2037     /* Read l2 aging interval. */
   2038     rv = SOC_FUNCTIONS(unit)->soc_age_timer_get(unit,
   2039                                             &age_sec,
   2040                                             &age_ena);
   2041     if (SOC_FAILURE(rv)) {
   2042         /* Decrease l2 frozen indicator. */
   2043         if (freeze_mode == SOC_L2X_FROZEN_WITH_LOCK) {
   2044             f_l2->frozen--;
   2045         } else {
   2046             f_l2->hw_frozen--;
   2047         }
   2048         SOC_L2X_MEM_UNLOCK(unit);
   2049         _soc_l2x_frozen_cml_restore(unit);
   2050         return rv;
   2051     }
   2052     /* If use bcm_esw_l2_age_timer_set to set new age seconde, we use new age_sec. */
   2053     if (!f_l2->new_age_set) {
   2054         f_l2->save_age_sec = age_sec;
   2055         f_l2->save_age_ena = age_ena;
   2056     }
   2057     /* If l2 aging is on - disable it. */
   2058     /* If use bcm_esw_l2_age_timer_set to set new age seconde as 0  - save it. */
   2059     if (f_l2->save_age_ena || f_l2->new_age_set) {
   2060         rv = SOC_FUNCTIONS(unit)->soc_age_timer_set(unit,
   2061                                                 f_l2->save_age_sec, 0);
   2062         if (SOC_FAILURE(rv)) {
   2063             /* Decrease l2 frozen indicator. */
   2064             if (freeze_mode == SOC_L2X_FROZEN_WITH_LOCK) {
   2065                 f_l2->frozen--;
   2066             } else {
   2067                 f_l2->hw_frozen--;
   2068             }
   2069             SOC_L2X_MEM_UNLOCK(unit);
   2070             _soc_l2x_frozen_cml_restore(unit);
   2071             return rv;
   2072         }
   2073         f_l2->new_age_set = 0;
   2074     }
   2075 
   2076     SOC_L2X_MEM_UNLOCK(unit);
   2077     return (SOC_E_NONE);
   2078 }
   2079 /*
   2080  * Function:
   2081  *	    soc_l2x_freeze
   2082  * Purpose:
   2083  *   	Temporarily quiesce L2 table from all activity (learning, aging)
   2084  *    Include H/W and S/W activity
   2085  * Parameters:
   2086  *	   unit - (IN) BCM device number. 
   2087  * Returns:
   2088  *	   SOC_E_XXX
   2089  */
   2090 int
   2091 soc_l2x_freeze(int unit)
   2092 {
   2093 #ifdef BCM_TRIUMPH3_SUPPORT
   2094     if (SOC_IS_TRIUMPH3(unit)) {
   2095         return soc_tr3_l2_freeze(unit);
   2096     }
   2097 #endif
   2098 
   2099     SOC_IF_ERROR_RETURN(soc_l2x_selective_freeze(unit, SOC_L2X_FROZEN_WITH_LOCK));
   2100 
   2101     SOC_L2X_MEM_LOCK(unit);
   2102 
   2103     return (SOC_E_NONE);
   2104 }
   2105 
   2106 /*
   2107  * Function:
   2108  *   	soc_l2x_selective_thaw
   2109  * Purpose:
   2110  *	    Restore normal L2 H/W activity.
   2111  * Parameters:
   2112  *	    unit -   (IN) BCM device number.
   2113  *  thaw_mode - Only H/W is thawed
   2114  * Returns:
   2115  *	    SOC_E_XXX
   2116  */
   2117 /*soc_l2x_selective_freeze matches with soc_l2x_selective_thaw */
   2118 int
   2119 soc_l2x_selective_thaw(int unit, int thaw_mode)
   2120 {
   2121     l2_freeze_t		    *f_l2 = &l2_freeze_state[unit];
   2122     int                 l2rv, cmlrv;
   2123 
   2124     /* Sanity check to protect from thaw without freeze. */
   2125     SOC_L2X_MEM_LOCK(unit);
   2126     if (thaw_mode == SOC_L2X_FROZEN_WITH_LOCK) {
   2127         if (f_l2->frozen == 0) {
   2128             SOC_L2X_MEM_UNLOCK(unit);
   2129             assert(0);
   2130             return (SOC_E_UNAVAIL);
   2131         }
   2132         /* In case of nested freeze/thaw just decrement reference counter. */
   2133         if (f_l2->frozen > 1 ||
   2134             (f_l2->frozen == 1 && f_l2->hw_frozen > 0)) {
   2135             f_l2->frozen--;
   2136             SOC_L2X_MEM_UNLOCK(unit);
   2137             return (SOC_E_NONE);
   2138         }
   2139     } else {
   2140         if (f_l2->hw_frozen == 0) {
   2141             SOC_L2X_MEM_UNLOCK(unit);
   2142             return (SOC_E_NONE);
   2143         }
   2144         /* In case of nested freeze/thaw just decrement reference counter. */
   2145         if (f_l2->hw_frozen > 1 ||
   2146             (f_l2->hw_frozen == 1 && f_l2->frozen > 0)) {
   2147             f_l2->hw_frozen--;
   2148             SOC_L2X_MEM_UNLOCK(unit);
   2149             return (SOC_E_NONE);
   2150         }
   2151     }
   2152     /*
   2153      * Last thaw restore L2 learning and aging.
   2154      */
   2155     l2rv = SOC_E_NONE;
   2156     /* If use bcm_esw_l2_age_timer_set to set new age seconde as 0  - save it. */
   2157     if (f_l2->save_age_ena || f_l2->new_age_set) {
   2158         l2rv = SOC_FUNCTIONS(unit)->soc_age_timer_set(unit,
   2159                                                   f_l2->save_age_sec,
   2160                                                   f_l2->save_age_ena);
   2161         f_l2->new_age_set = 0;
   2162     }
   2163 
   2164     /* L2 freeze reference counter decrement. */
   2165     if (thaw_mode == SOC_L2X_FROZEN_WITH_LOCK) {
   2166         f_l2->frozen--;
   2167     } else {
   2168         f_l2->hw_frozen--;
   2169     }
   2170 
   2171     SOC_L2X_MEM_UNLOCK(unit);
   2172 
   2173     /* Restore port learning mode. */
   2174     cmlrv = _soc_l2x_frozen_cml_restore(unit);
   2175 
   2176     if (SOC_FAILURE(l2rv)) {
   2177         return l2rv;
   2178     }
   2179     return cmlrv;
   2180 }
   2181 
   2182 /*
   2183  * Function:
   2184  *   	soc_l2x_thaw
   2185  * Purpose:
   2186  *	    Restore normal L2 activity.
   2187  * Parameters:
   2188  *	    unit - (IN) BCM device number.
   2189  * Returns:
   2190  *	    SOC_E_XXX
   2191  */
   2192 
   2193 int
   2194 soc_l2x_thaw(int unit)
   2195 {
   2196 
   2197 #ifdef BCM_TRIUMPH3_SUPPORT
   2198     if (SOC_IS_TRIUMPH3(unit)) {
   2199         return soc_tr3_l2_thaw(unit);
   2200     }
   2201 #endif
   2202 
   2203     SOC_L2X_MEM_UNLOCK(unit);
   2204 
   2205     return soc_l2x_selective_thaw(unit, SOC_L2X_FROZEN_WITH_LOCK);
   2206 }
   2207 
   2208 /*
   2209  * Function:
   2210  *	soc_l2x_frozen_cml_set
   2211  * Purpose:
   2212  *	Update the saved Cpu Managed Learning mode for a port
   2213  *	if the device is frozen.
   2214  * Parameters:
   2215  *	unit		device number
   2216  *	port		port number
   2217  *	cml		Cpu-Managed-Learning mode to update
   2218  *	cml_move        Station move Cpu-Managed-Learning mode to update
   2219  *	repl_cml	CML mode to use in port table update
   2220  *	repl_cml_move   Station move CML mode to use in port table update
   2221  * Returns:
   2222  *	SOC_E_NONE	frozen cml is updated
   2223  *	SOC_E_FAIL	unit is not frozen
   2224  *
   2225  *  NOTE: 
   2226  *     PORT_TAB must be locked when calling this routine.
   2227  */
   2228 int
   2229 soc_l2x_frozen_cml_set(int unit, soc_port_t port, int cml, int cml_move, int *repl_cml, int *repl_cml_move)
   2230 {
   2231     cml_freeze_t	*f_cml = &cml_freeze_state[unit];
   2232     int frozen = 0;
   2233 
   2234     if (SOC_IS_TD2_TT2(unit) &&
   2235         soc_l2x_freeze_mode_is_global_override(unit)) {
   2236         return SOC_E_UNAVAIL;
   2237     }
   2238 
   2239 #if defined(BCM_TRIUMPH3_SUPPORT)
   2240     if (SOC_IS_TRIUMPH3(unit)) {
   2241         soc_tr3_l2_is_frozen(unit, &frozen);
   2242     } else
   2243 #endif
   2244     {
   2245         frozen = f_cml->frozen;
   2246     }
   2247 
   2248     if (frozen) {
   2249         f_cml->save_cml[port] = cml;
   2250         f_cml->save_cml_move[port] = cml_move;
   2251         if (repl_cml != NULL) {
   2252 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_TRX_SUPPORT)
   2253             if (SOC_IS_TRIUMPH3(unit) || SOC_IS_TRX(unit)) {
   2254                 /* Since L2 is frozen, bits 4, 3 should be clear, they would
   2255                    reflect the actual value after thaw */
   2256                 *repl_cml = (cml & 0x3);
   2257             } else
   2258 #endif
   2259             {
   2260                 *repl_cml = PVP_CML_FORWARD;
   2261             }
   2262         }
   2263         if (repl_cml_move != NULL) {
   2264 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_TRX_SUPPORT)
   2265             if (SOC_IS_TRIUMPH3(unit) || SOC_IS_TRX(unit)) {
   2266                 /* Since L2 is frozen, bits 4, 3 should be clear, they would
   2267                    reflect the actual value after thaw */
   2268                 *repl_cml_move = (cml_move & 0x3);
   2269             } else
   2270 #endif
   2271             {
   2272                 *repl_cml_move = PVP_CML_FORWARD;
   2273             }
   2274         }
   2275 
   2276         return SOC_E_NONE;
   2277     }
   2278     return SOC_E_FAIL;
   2279 }
   2280 
   2281 /*
   2282  * Function:
   2283  *	soc_l2x_frozen_cml_get
   2284  * Purpose:
   2285  *	Get the saved Cpu Managed Learning mode for a port
   2286  *	if the device is frozen.
   2287  * Parameters:
   2288  *	unit		device number
   2289  *	port		port number
   2290  *	cml		(OUT) saved Cpu-Managed-Learning mode
   2291  *	cml_move        (OUT) saved Station move Cpu-Managed-Learning mode
   2292  * Returns:
   2293  *	SOC_E_NONE	frozen cml is returned
   2294  *	SOC_E_FAIL	unit is not frozen
   2295  *
   2296  *  NOTE: 
   2297  *     PORT_TAB must be locked when calling this routine.
   2298  */
   2299 int
   2300 soc_l2x_frozen_cml_get(int unit, soc_port_t port, int *cml, int *cml_move)
   2301 {
   2302     cml_freeze_t	*f_cml = &cml_freeze_state[unit];
   2303     int frozen = 0;
   2304 
   2305     if (SOC_IS_TD2_TT2(unit) &&
   2306         soc_l2x_freeze_mode_is_global_override(unit)) {
   2307         return SOC_E_UNAVAIL;
   2308     }
   2309 
   2310 #if defined(BCM_TRIUMPH3_SUPPORT)
   2311     if (SOC_IS_TRIUMPH3(unit)) {
   2312         soc_tr3_l2_is_frozen(unit, &frozen);
   2313     } else
   2314 #endif
   2315     {
   2316         frozen = f_cml->frozen;
   2317     }
   2318 
   2319     if (frozen) {
   2320         if (cml) {
   2321         *cml = f_cml->save_cml[port];
   2322         }
   2323         if (cml_move) {
   2324             *cml_move = f_cml->save_cml_move[port];
   2325         }
   2326         
   2327         return SOC_E_NONE;
   2328     }
   2329     return SOC_E_FAIL;
   2330 }
   2331 
   2332 
   2333 #ifdef BCM_FIREBOLT_SUPPORT
   2334 static int
   2335 soc_fb_l2x_entries(int unit)
   2336 {
   2337     int         index_min, index_max, index, total, rv;
   2338     uint32      *ent;
   2339     uint32      *buf = NULL;
   2340     int         validf = -1;
   2341 
   2342 
   2343     index_min = soc_mem_index_min(unit, L2Xm);
   2344     index_max = soc_mem_index_max(unit, L2Xm);
   2345     buf = soc_cm_salloc(unit,
   2346                         SOC_MEM_TABLE_BYTES(unit, L2Xm),
   2347                         "l2x_entries");
   2348     if (buf == NULL) {
   2349         return SOC_E_MEMORY;
   2350     }
   2351 
   2352     rv = soc_mem_read_range(unit, L2Xm, MEM_BLOCK_ANY,
   2353                             index_min, index_max, buf);
   2354 
   2355     if (rv < 0) {
   2356         soc_cm_sfree(unit, buf);
   2357         return rv;
   2358     }
   2359 
   2360     total = 0;
   2361     ent = buf;
   2362 
   2363     if (soc_feature(unit, soc_feature_base_valid)) {
   2364         validf = BASE_VALIDf;
   2365     } else {
   2366         validf = VALIDf;
   2367     }
   2368 
   2369     for (index = 0; index < (index_max - index_min); index++) {
   2370         if (soc_L2Xm_field32_get(unit, ent, validf)) {
   2371             total++;
   2372         }
   2373         ent += soc_mem_entry_words(unit, L2Xm);
   2374     }
   2375 
   2376     soc_cm_sfree(unit, buf);
   2377 
   2378     return total;
   2379 }
   2380 #endif /* BCM_FIREBOLT_SUPPORT */
   2381 
   2382 /*
   2383  * Function:
   2384  *	soc_l2x_entries
   2385  * Purpose:
   2386  *	Return number of valid entries in L2 table.
   2387  * Parameters:
   2388  *	unit - StrataSwitch unit #
   2389  * Returns:
   2390  *	If >= 0, number of entries in L2 table
   2391  *	If < 0, SOC_E_XXX
   2392  * Notes:
   2393  *	Somewhat slow; has to read whole table.
   2394  *	New improved: Now with DMA power.
   2395  */
   2396 
   2397 int
   2398 soc_l2x_entries(int unit)
   2399 {
   2400 #ifdef BCM_FIREBOLT_SUPPORT
   2401     if (SOC_IS_FBX(unit)) {
   2402         return soc_fb_l2x_entries(unit);
   2403     }
   2404 #endif /* BCM_FIREBOLT_SUPPORT */
   2405     return 0;
   2406 }
   2407 
   2408 #ifdef BCM_FIREBOLT_SUPPORT
   2409 /*
   2410  * Function:
   2411  *      soc_fb_l2x_bank_lookup
   2412  * Purpose:
   2413  *      Send an L2 lookup message over the S-Channel and receive the
   2414  *      response.
   2415  * Parameters:
   2416  *      unit - StrataSwitch unit #
   2417  *      banks - For dual hashing, which halves are selected (inverted)
   2418  *      key - L2X entry to look up; only MAC+VLAN fields are relevant
   2419  *      result - L2X entry to receive entire found entry
   2420  *      index_ptr (OUT) - If found, receives table index where found
   2421  * Returns:
   2422  *      SOC_E_INTERNAL if retries exceeded or other internal error
   2423  *      SOC_E_NOT_FOUND if the entry is not found.
   2424  *      SOC_E_NONE (0) on success (entry found):
   2425  * Notes:
   2426  *      The S-Channel response contains either a matching L2 entry,
   2427  *      or an entry with a key of all f's if not found.  It is okay
   2428  *      if the result pointer is the same as the key pointer.
   2429  *      Retries the lookup in cases where the particular chip requires it.
   2430  */
   2431 
   2432 int
   2433 soc_fb_l2x_bank_lookup(int unit, uint8 banks,
   2434                l2x_entry_t *key, l2x_entry_t *result,
   2435                int *index_ptr)
   2436 {
   2437     schan_msg_t    schan_msg;
   2438     int entry_dw = soc_mem_entry_words(unit, L2Xm);
   2439     int nbits;
   2440     int rv;
   2441     int                 dst_blk, src_blk, data_byte_len;
   2442     uint32              bank_ignore_mask;
   2443     int                 opcode, nack;
   2444 
   2445     schan_msg_clear(&schan_msg);
   2446     src_blk = SOC_BLOCK2SCH(unit, CMIC_BLOCK(unit));
   2447     dst_blk = SOC_BLOCK2SCH(unit, IPIPE_BLOCK(unit));
   2448     bank_ignore_mask = banks & 0x3;
   2449     data_byte_len = entry_dw * 4;
   2450     soc_schan_header_cmd_set(unit, &schan_msg.header, L2_LOOKUP_CMD_MSG,
   2451                              dst_blk, src_blk, 0, data_byte_len, 0,
   2452                              bank_ignore_mask);  
   2453 
   2454     /* Fill in entry data */
   2455 
   2456     sal_memcpy(schan_msg.l2x2.data, key, sizeof (schan_msg.l2x2.data));
   2457 
   2458     /*
   2459      * Write onto S-Channel "L2 lookup" command packet consisting of
   2460      * header word + three words of L2 key, and read back header
   2461      * word + 4 words of lookup result. (index of the extry + contents of
   2462      * the entry)
   2463      */
   2464 
   2465     rv = soc_schan_op(unit, &schan_msg, entry_dw + 1, entry_dw + 2, 1);
   2466 
   2467     /* Check result */
   2468     soc_schan_header_status_get(unit, &schan_msg.header, &opcode, NULL, NULL,
   2469                                 NULL, NULL, &nack);
   2470     if (opcode != L2_LOOKUP_ACK_MSG) {
   2471         LOG_ERROR(BSL_LS_SOC_L2,
   2472                   (BSL_META_U(unit,
   2473                               "soc_fb_l2x_bank_lookup: "
   2474                               "invalid S-Channel reply, expected L2_LOOKUP_ACK_MSG:\n")));
   2475         soc_schan_dump(unit, &schan_msg, entry_dw + 2);
   2476         return SOC_E_INTERNAL;
   2477     }
   2478 
   2479     /*
   2480      * Fill in result entry from read data.
   2481      *
   2482      * Format of S-Channel response:
   2483      *          readresp.header : L2 lookup Ack S-channel header
   2484      *          readresp.data[0]: index of the entry in the L2Xm Table
   2485      *          readresp.data[1-3]: entry contents
   2486      * =============================================================
   2487      * | PERR_PBM | MFIFO_FULL | OP_FAIL | Index  | L2x entry data |
   2488      * =============================================================
   2489      */
   2490     nbits = soc_mem_entry_bits(unit, L2Xm) % 32; /* Data Bits in last word */
   2491 
   2492     if ((nack != 0) || (rv == SOC_E_FAIL)) {
   2493         *index_ptr = -1;
   2494         if (soc_feature(unit, soc_feature_l2x_parity)) {
   2495             int op_fail_pos;
   2496             op_fail_pos = SOC_L2X_OP_FAIL_POS(unit);
   2497             if ((schan_msg.readresp.data[3] >> (op_fail_pos + 2)) & 0xff) {
   2498                 uint32 index = (schan_msg.readresp.data[2] >> nbits) &
   2499                                ((1 << (32 - nbits)) - 1);
   2500                 index |= (schan_msg.readresp.data[3] << (32 - nbits)) &
   2501                          soc_mem_index_max(unit, L2Xm); /* Assume size of table 2^N */
   2502                 LOG_ERROR(BSL_LS_SOC_L2,
   2503                           (BSL_META_U(unit,
   2504                                       "Lookup table[L2Xm]: Parity Error Index %d Bucket Bitmap 0x%08x\n"),
   2505                            index,
   2506                            (schan_msg.readresp.data[3] >> (op_fail_pos + 2)) & 0xff ));
   2507                 return SOC_E_INTERNAL;
   2508             }
   2509         }
   2510         return SOC_E_NOT_FOUND;
   2511     }
   2512 
   2513     /* MACADDR<31:0> */
   2514     result->entry_data[0] = schan_msg.readresp.data[0];
   2515 
   2516     /* CPU, PRI<2:0>, VLAN<12:0>, MACADDR<47:32> */
   2517     result->entry_data[1] = schan_msg.readresp.data[1];
   2518 
   2519     /* HIT SA, HIT DA, VALID, MIRROR, RPE, STATIC_BIT, RESERVED,
   2520      * MAC_BLOCK_INDEX, L3 MODULE_ID, PORT_TGID, SCP, SRC_DISCARD,
   2521      * DST_DISCARD
   2522      */
   2523     result->entry_data[2] = schan_msg.readresp.data[2] & ((1 << nbits) - 1);
   2524 
   2525     *index_ptr = (schan_msg.readresp.data[2] >> nbits) &
   2526                  ((1 << (32 - nbits)) - 1);
   2527     *index_ptr |= (schan_msg.readresp.data[3] << (32 - nbits));
   2528     *index_ptr &= soc_mem_index_max(unit, L2Xm); /* Assume size of table 2^N */
   2529     if (bsl_check(bslLayerSoc, bslSourceSocmem, bslSeverityNormal, unit)) {
   2530         LOG_INFO(BSL_LS_SOC_SOCMEM,
   2531                  (BSL_META_U(unit,
   2532                              "L2 entry lookup: ")));
   2533         soc_mem_entry_dump(unit, L2Xm, result, BSL_INFO|BSL_LS_SOC_SOCMEM);
   2534         LOG_INFO(BSL_LS_SOC_SOCMEM,
   2535                  (BSL_META_U(unit,
   2536                              " (index=%d)\n"), *index_ptr));
   2537     }
   2538 
   2539     return SOC_E_NONE;
   2540 }
   2541 
   2542 /*
   2543  * Function:
   2544  *      soc_fb_l2x_bank_insert
   2545  * Purpose:
   2546  *      Insert an entry into the L2X hash table.
   2547  * Parameters:
   2548  *      unit - StrataSwitch unit #
   2549  *      banks - For dual hashing, which halves are selected (inverted)
   2550  *      entry - L2X entry to insert
   2551  * Returns:
   2552  *      SOC_E_NONE - success
   2553  *      SOC_E_FULL - hash bucket full
   2554  *      SOC_E_BUSY - modfifo full
   2555  * Notes:
   2556  *      Uses hardware insertion; sends an L2 INSERT message over the
   2557  *      S-Channel.  The hardware needs the L2Xm entry type.
   2558  */
   2559 
   2560 int
   2561 soc_fb_l2x_bank_insert(int unit, uint8 banks, l2x_entry_t *entry)
   2562 {
   2563     schan_msg_t 	schan_msg;
   2564     int			rv;
   2565     int                 op_fail_pos;
   2566     int entry_dw = soc_mem_entry_words(unit, L2Xm);
   2567     int nbits;
   2568     int                 dst_blk, src_blk, data_byte_len;
   2569     uint32              bank_ignore_mask;
   2570     int                 opcode, nack;
   2571 
   2572     if (bsl_check(bslLayerSoc, bslSourceSocmem, bslSeverityNormal, unit)) {
   2573         LOG_INFO(BSL_LS_SOC_SOCMEM,
   2574                  (BSL_META_U(unit,
   2575                              "Insert table[L2_ENTRY]: ")));
   2576         soc_mem_entry_dump(unit, L2Xm, entry, BSL_INFO|BSL_LS_SOC_SOCMEM);
   2577         LOG_INFO(BSL_LS_SOC_SOCMEM,
   2578                  (BSL_META_U(unit,
   2579                              "\n")));
   2580     }
   2581 
   2582     schan_msg_clear(&schan_msg);
   2583     src_blk = SOC_BLOCK2SCH(unit, CMIC_BLOCK(unit));
   2584     dst_blk = SOC_BLOCK2SCH(unit, IPIPE_BLOCK(unit));
   2585     bank_ignore_mask = banks & 0x3;
   2586     data_byte_len = entry_dw * 4;
   2587     soc_schan_header_cmd_set(unit, &schan_msg.header, ARL_INSERT_CMD_MSG,
   2588                              dst_blk, src_blk, 0, data_byte_len, 0,
   2589                              bank_ignore_mask);  
   2590 
   2591     /* Fill in ARL packet data */
   2592 
   2593     sal_memcpy(schan_msg.l2x2.data, entry, sizeof (schan_msg.l2x2.data));
   2594 
   2595     /* Execute S-Channel operation (header word + 3 DWORDs) */
   2596 
   2597     rv = soc_schan_op(unit, &schan_msg, entry_dw + 1, entry_dw + 2, 1);
   2598 
   2599     soc_schan_header_status_get(unit, &schan_msg.header, &opcode, NULL, NULL,
   2600                                 NULL, NULL, &nack);
   2601     if (opcode != ARL_INSERT_DONE_MSG) {
   2602         LOG_ERROR(BSL_LS_SOC_L2,
   2603                   (BSL_META_U(unit,
   2604                               "soc_fb_l2x_bank_insert: "
   2605                               "invalid S-Channel reply, expected L2_INSERT_ACK_MSG:\n")));
   2606         soc_schan_dump(unit, &schan_msg, 1);
   2607         return SOC_E_INTERNAL;
   2608     }
   2609 
   2610     /*
   2611      * =============================================================
   2612      * | PERR_PBM | MFIFO_FULL | OP_FAIL | Index  | L2x entry data |
   2613      * =============================================================
   2614      */
   2615     nbits = soc_mem_entry_bits(unit, L2Xm) % 32; /* Data Bits in last word */
   2616     op_fail_pos = SOC_L2X_OP_FAIL_POS(unit);
   2617 
   2618     /* bit-106 OP_FAIL; bit-107 ModFifo Full */
   2619     if ((nack != 0) || (rv == SOC_E_FAIL)) {
   2620         if (schan_msg.readresp.data[3] & (1 << op_fail_pos)) {
   2621             LOG_INFO(BSL_LS_SOC_SOCMEM,
   2622                      (BSL_META_U(unit,
   2623                                  "Insert table[L2Xm]: hash bucket full\n")));
   2624             rv = SOC_E_FULL;
   2625         } else if (schan_msg.readresp.data[3] & (1 << (op_fail_pos + 1))) {
   2626             LOG_INFO(BSL_LS_SOC_SOCMEM,
   2627                      (BSL_META_U(unit,
   2628                                  "Insert table[L2Xm]: Modfifo full\n")));
   2629             rv = SOC_E_BUSY;
   2630         } else if (soc_feature(unit, soc_feature_l2x_parity) &&
   2631                    ((schan_msg.readresp.data[3] >> (op_fail_pos + 2)) & 0xff)) {
   2632             uint32 index = (schan_msg.readresp.data[2] >> nbits) &
   2633                            ((1 << (32 - nbits)) - 1);
   2634             index |= (schan_msg.readresp.data[3] << (32 - nbits)) &
   2635                      soc_mem_index_max(unit, L2Xm); /* Assume size of table 2^N */
   2636             LOG_ERROR(BSL_LS_SOC_L2,
   2637                       (BSL_META_U(unit,
   2638                                   "Insert table[L2Xm]: Parity Error Index %d Bucket Bitmap 0x%08x\n"),
   2639                        index,
   2640                        (schan_msg.readresp.data[3] >> (op_fail_pos + 2)) & 0xff ));
   2641             rv = SOC_E_INTERNAL;
   2642         } else {
   2643             rv = SOC_E_FAIL;
   2644         }
   2645     }
   2646 
   2647     return rv;
   2648 }
   2649 
   2650 /*
   2651  * Function:
   2652  *	soc_fb_l2x_bank_delete
   2653  * Purpose:
   2654  *	Delete an entry from the L2X hash table.
   2655  * Parameters:
   2656  *	unit - StrataSwitch unit #
   2657  *      banks - For dual hashing, which halves are selected (inverted)
   2658  *	entry - L2X entry to delete
   2659  * Returns:
   2660  *	SOC_E_NONE - success
   2661  *	SOC_E_NOT_FOUND - hash bucket full
   2662  *      SOC_E_BUSY - modfifo full
   2663  * Notes:
   2664  *	Uses hardware deletion; sends an L2 DELETE message over the
   2665  *	S-Channel.  The hardware needs the L2Xm entry type.
   2666  */
   2667 
   2668 int
   2669 soc_fb_l2x_bank_delete(int unit, uint8 banks, l2x_entry_t *entry)
   2670 {
   2671     schan_msg_t 	schan_msg;
   2672     int			rv;
   2673     int                 op_fail_pos;
   2674     int                 nbits;
   2675     int entry_dw = soc_mem_entry_words(unit, L2Xm);
   2676     int                 dst_blk, src_blk, data_byte_len;
   2677     uint32              bank_ignore_mask;
   2678     int                 opcode, nack;
   2679 
   2680     if (bsl_check(bslLayerSoc, bslSourceSocmem, bslSeverityNormal, unit)) {
   2681         LOG_INFO(BSL_LS_SOC_SOCMEM,
   2682                  (BSL_META_U(unit,
   2683                              "Delete table[L2Xm]: ")));
   2684         soc_mem_entry_dump(unit, L2Xm, entry, BSL_INFO|BSL_LS_SOC_SOCMEM);
   2685         LOG_INFO(BSL_LS_SOC_SOCMEM,
   2686                  (BSL_META_U(unit,
   2687                              "\n")));
   2688     }
   2689 
   2690     schan_msg_clear(&schan_msg);
   2691     src_blk = SOC_BLOCK2SCH(unit, CMIC_BLOCK(unit));
   2692     dst_blk = SOC_BLOCK2SCH(unit, IPIPE_BLOCK(unit));
   2693     bank_ignore_mask = banks & 0x3;
   2694     data_byte_len = entry_dw * 4;
   2695     soc_schan_header_cmd_set(unit, &schan_msg.header, ARL_DELETE_CMD_MSG,
   2696                              dst_blk, src_blk, 0, data_byte_len, 0,
   2697                              bank_ignore_mask);  
   2698 
   2699     /* Fill in packet data */
   2700 
   2701     sal_memcpy(schan_msg.l2x2.data, entry, sizeof (schan_msg.l2x2.data));
   2702 
   2703     /* Execute S-Channel operation (header word + 2 DWORDs) */
   2704     rv = soc_schan_op(unit, &schan_msg, entry_dw + 1, entry_dw + 2, 1);
   2705 
   2706     soc_schan_header_status_get(unit, &schan_msg.header, &opcode, NULL, NULL,
   2707                                 NULL, NULL, &nack);
   2708     if (opcode != ARL_DELETE_DONE_MSG) {
   2709         LOG_ERROR(BSL_LS_SOC_L2,
   2710                   (BSL_META_U(unit,
   2711                               "soc_fb_l2x_bank_delete: "
   2712                               "invalid S-Channel reply, expected L2_DELETE_ACK_MSG:\n")));
   2713         soc_schan_dump(unit, &schan_msg, 1);
   2714         return SOC_E_INTERNAL;
   2715     }
   2716 
   2717     /*
   2718      * =============================================================
   2719      * | PERR_PBM | MFIFO_FULL | OP_FAIL | Index  | L2x entry data |
   2720      * =============================================================
   2721      */
   2722     nbits = soc_mem_entry_bits(unit, L2Xm) % 32; /* Data Bits in last word */
   2723     op_fail_pos = SOC_L2X_OP_FAIL_POS(unit);
   2724 
   2725     /* bit-106 OP_FAIL; bit-107 ModFifo Full */
   2726     if ((nack != 0) || (rv == SOC_E_FAIL)) {
   2727         if (schan_msg.readresp.data[3] & (1 << op_fail_pos)) {
   2728             LOG_INFO(BSL_LS_SOC_SOCMEM,
   2729                      (BSL_META_U(unit,
   2730                                  "Delete table[L2Xm]: Not found\n")));
   2731             rv = SOC_E_NOT_FOUND;
   2732         } else if (schan_msg.readresp.data[3] & (1 << (op_fail_pos + 1))) {
   2733             LOG_INFO(BSL_LS_SOC_SOCMEM,
   2734                      (BSL_META_U(unit,
   2735                                  "Delete table[L2Xm]: Modfifo full\n")));
   2736             rv = SOC_E_BUSY;
   2737         } else if (soc_feature(unit, soc_feature_l2x_parity) &&
   2738                    ((schan_msg.readresp.data[3] >> (op_fail_pos + 2)) & 0xff)) {
   2739             uint32 index = (schan_msg.readresp.data[2] >> nbits) &
   2740                            ((1 << (32 - nbits)) - 1);
   2741             index |= (schan_msg.readresp.data[3] << (32 - nbits)) &
   2742                      soc_mem_index_max(unit, L2Xm); /* Assume size of table 2^N */
   2743             LOG_ERROR(BSL_LS_SOC_L2,
   2744                       (BSL_META_U(unit,
   2745                                   "Delete table[L2Xm]: Parity Error Index %d Bucket Bitmap 0x%08x\n"),
   2746                        index,
   2747                        (schan_msg.readresp.data[3] >> (op_fail_pos + 2)) & 0xff ));
   2748             rv = SOC_E_INTERNAL;
   2749         } else {
   2750             rv = SOC_E_FAIL;
   2751         }
   2752     }
   2753 
   2754     return rv;
   2755 }
   2756 
   2757 /*
   2758  * Original non-bank versions of the FB L2X table op functions
   2759  */
   2760 
   2761 int
   2762 soc_fb_l2x_insert(int unit, l2x_entry_t *entry)
   2763 {
   2764 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_RAVEN_SUPPORT) || \
   2765     defined(BCM_TRX_SUPPORT)
   2766     if (soc_feature(unit, soc_feature_dual_hash)) {
   2767         return
   2768             _soc_mem_dual_hash_insert(unit, L2Xm, COPYNO_ALL, (void *)entry,
   2769                           NULL, SOC_DUAL_HASH_MOVE_MAX_L2X(unit));
   2770     } else
   2771 #endif
   2772     {
   2773         return soc_fb_l2x_bank_insert(unit, 0, entry);
   2774     }
   2775 }
   2776 
   2777 int
   2778 soc_fb_l2x_delete(int unit, l2x_entry_t *entry)
   2779 {
   2780     return soc_fb_l2x_bank_delete(unit, 0, entry);
   2781 }
   2782 
   2783 int
   2784 soc_fb_l2x_lookup(int unit, l2x_entry_t *key,
   2785                   l2x_entry_t *result, int *index_ptr)
   2786 {
   2787     return soc_fb_l2x_bank_lookup(unit, 0, key, result, index_ptr);
   2788 }
   2789 
   2790 /*
   2791  * Function:
   2792  *	soc_fb_l2x_delete_all
   2793  * Purpose:
   2794  *	Clear the L2 table by invalidating entries.
   2795  * Parameters:
   2796  *	unit - StrataSwitch unit #
   2797  *	static_too - if TRUE, delete static and non-static entries;
   2798  *		     if FALSE, delete only non-static entries
   2799  * Returns:
   2800  *	SOC_E_XXX
   2801  */
   2802 
   2803 int
   2804 soc_fb_l2x_delete_all(int unit)
   2805 {
   2806     soc_control_t	*soc = SOC_CONTROL(unit);
   2807     int			    index_min, index_max, index, mem_max;
   2808     l2x_entry_t     *l2x_entry;
   2809     int			rv = SOC_E_NONE;
   2810     int             *buffer = NULL;
   2811     int             mem_size, idx;
   2812 
   2813     index_min = soc_mem_index_min(unit, L2_ENTRY_ONLYm);
   2814     mem_max = soc_mem_index_max(unit, L2_ENTRY_ONLYm);
   2815     mem_size =  DEFAULT_L2DELETE_CHUNKS * sizeof(l2x_entry_t);
   2816 
   2817     buffer = soc_cm_salloc(unit, mem_size, "L2X_delete");
   2818     if (NULL == buffer) {
   2819         return SOC_E_MEMORY;
   2820     }
   2821 
   2822     soc_mem_lock(unit, L2Xm);
   2823     for (idx = index_min; idx < mem_max; idx += DEFAULT_L2DELETE_CHUNKS) {
   2824         index_max = idx + DEFAULT_L2DELETE_CHUNKS - 1;
   2825         if ( index_max > mem_max) {
   2826             index_max = mem_max;
   2827         }
   2828         if ((rv = soc_mem_read_range(unit, L2_ENTRY_ONLYm, MEM_BLOCK_ANY,
   2829                                      idx, index_max, buffer)) < 0 ) {
   2830             break;
   2831         }
   2832         for (index = 0; index < index_max - idx + 1; index++) {
   2833             l2x_entry =
   2834                 soc_mem_table_idx_to_pointer(unit, L2_ENTRY_ONLYm,
   2835                                              l2x_entry_t *, buffer, index);
   2836                 sal_memcpy(l2x_entry, soc_mem_entry_null(unit, L2_ENTRY_ONLYm),
   2837                            sizeof(l2x_entry_t));
   2838         }
   2839         if ((rv = soc_mem_write_range(unit, L2_ENTRY_ONLYm, MEM_BLOCK_ALL, 
   2840                                      idx, index_max, buffer)) < 0) {
   2841             break;
   2842         }
   2843     }
   2844     soc_mem_unlock(unit, L2Xm);
   2845 
   2846     if (soc->arlShadow != NULL) {
   2847         sal_mutex_take(soc->arlShadowMutex, sal_mutex_FOREVER);
   2848         (void) shr_avl_delete_all(soc->arlShadow);
   2849         sal_mutex_give(soc->arlShadowMutex);
   2850     }
   2851     soc_cm_sfree(unit, buffer);
   2852     
   2853 
   2854     return rv;
   2855 }
   2856 
   2857 #endif /* BCM_FIREBOLT_SUPPORT */
   2858 
   2859 #if defined(BCM_TOMAHAWK3_SUPPORT)
   2860 /*
   2861  * Function:
   2862  *	soc_th3_l2x_reset_freeze_state
   2863  * Purpose:
   2864  *	This function clears aging related information during attach sequence
   2865  * Parameters:
   2866  *  unit - StrataSwitch unit number
   2867  * Returns:
   2868  *	No value
   2869  */
   2870 void soc_th3_l2x_reset_freeze_state(int unit)
   2871 {
   2872     sal_memset(l2_freeze_state + unit, 0, sizeof(l2_freeze_t));
   2873 }
   2874 #endif /* BCM_TOMAHAWK3_SUPPORT */
   2875 
   2876 #endif /* BCM_XGS_SWITCH_SUPPORT */