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

l2.c (442581B)


      1 /*
      2  * 
      3  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      4  * 
      5  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      6  *
      7  * File:        l2.c
      8  * Purpose:     Triumph3 L2 function implementations
      9  */
     10 
     11 #include <shared/bsl.h>
     12 
     13 #include <soc/defs.h>
     14 #if defined(BCM_TRIUMPH3_SUPPORT)
     15 
     16 #include <assert.h>
     17  
     18 #include <sal/core/libc.h>
     19  
     20 #include <soc/mem.h>
     21 #include <soc/cm.h>
     22 #include <soc/drv.h>
     23 #include <soc/register.h>
     24 #include <soc/memory.h>
     25 #include <soc/hash.h>
     26 #include <soc/l2x.h>
     27 #include <soc/l2u.h>
     28 #include <soc/triumph3.h>
     29 #include <soc/ism_hash.h>
     30 #ifdef BCM_KATANA2_SUPPORT 
     31 #include <soc/katana2.h> 
     32 #endif 
     33 #include <bcm/l2.h>
     34 #include <bcm/error.h>
     35 #include <bcm/failover.h>
     36  
     37 #include <bcm_int/esw/l2gre.h>
     38 #include <bcm_int/esw/l2.h>
     39 #include <bcm_int/esw/mpls.h>
     40 #include <bcm_int/esw/mim.h>
     41 #include <bcm_int/common/multicast.h>
     42 #include <bcm_int/esw/stack.h>
     43 #include <bcm_int/esw/trill.h>
     44 #include <bcm_int/esw/virtual.h>
     45 #include <bcm_int/esw/vlan.h>
     46 #include <bcm_int/esw/triumph3.h>
     47 #include <bcm_int/esw_dispatch.h>
     48 #include <bcm_int/esw/triumph.h>
     49 
     50 /****************************************************************
     51  *
     52  * L2 software tables, per unit.
     53  */
     54 static int _bcm_tr3_l2_init[BCM_MAX_NUM_UNITS];
     55 static soc_profile_mem_t *_bcm_l2_tr3_port_cbl_profile[BCM_MAX_NUM_UNITS];
     56 
     57 /*
     58  * Define:
     59  * BCM_TR3_L2_INIT
     60  * Purpose:
     61  *  Causes a routine to return BCM_E_INIT  if L2 software module
     62  *  is not yet initialized.
     63  */
     64 
     65 #define BCM_TR3_L2_INIT(unit) \
     66     if (0 == _bcm_tr3_l2_init[unit]) return BCM_E_INIT
     67 
     68 /***********************************************************************
     69  *
     70  * L2X Message Registration
     71  */
     72 
     73 #define _BCM_TR3_L2_CB_MAX 3
     74 
     75 typedef struct _bcm_tr3_l2x_cb_entry_s {
     76     bcm_l2_addr_callback_t fn;
     77     void                   *fn_data;
     78 } _bcm_tr3_l2_cb_entry_t;
     79 
     80 #define _BCM_TR3_L2X_THREAD_STOP (1 << 0)
     81 typedef struct _bcm_tr3_l2_data_s {
     82     _bcm_tr3_l2_cb_entry_t cb[_BCM_TR3_L2_CB_MAX];
     83     int                    cb_count;
     84     int                    flags;
     85     sal_mutex_t            l2_mutex;
     86 } _bcm_tr3_l2_data_t;
     87 
     88 static _bcm_tr3_l2_data_t *_bcm_tr3_l2_data[SOC_MAX_NUM_DEVICES];
     89 
     90 
     91 #define BCM_TR3_L2_CB_LOCK(unit) \
     92     sal_mutex_take(_bcm_tr3_l2_data[unit]->l2_mutex, sal_mutex_FOREVER)
     93 
     94 #define BCM_TR3_L2_CB_UNLOCK(unit) \
     95     sal_mutex_give(_bcm_tr3_l2_data[unit]->l2_mutex)
     96 
     97 #define BCM_TR3_L2_CB_MUTEX(unit) \
     98     if (_bcm_tr3_l2_data[unit] == NULL || \
     99         (_bcm_tr3_l2_data[unit]->l2_mutex == NULL && \
    100         (_bcm_tr3_l2_data[unit]->l2_mutex = \
    101             sal_mutex_create("bcm_tr3_l2_lock")) == NULL))  \
    102             return BCM_E_MEMORY
    103 
    104 /****************************************************************
    105  *
    106  * L2 MAC block software accounting, per unit.
    107  */
    108 
    109 typedef struct _bcm_tr3_mac_block_info_s {
    110     bcm_pbmp_t mb_pbmp;
    111     int ref_count;
    112 } _bcm_tr3_mac_block_info_t;
    113 
    114 static _bcm_tr3_mac_block_info_t *_tr3_mbi_entries[BCM_MAX_NUM_UNITS];
    115 static int _tr3_mbi_num[BCM_MAX_NUM_UNITS];
    116 
    117 /****************************************************************
    118  *
    119  * L2 learn limit software representation, per unit.
    120  */
    121 
    122 #define BCM_MAC_LIMIT_MAX(_u_) (soc_feature(_u_, soc_feature_esm_support))       ?  \
    123                                 ((soc_mem_index_count(_u_, L2_ENTRY_1m))     +  \
    124                                  (soc_mem_index_count(_u_, EXT_L2_ENTRY_1m)) +  \
    125                                  (soc_mem_index_count(_u_, EXT_L2_ENTRY_2m))):  \
    126                                  (soc_mem_index_count(_u_, L2_ENTRY_1m))
    127 
    128 /****************************************************************
    129  *
    130  * L2 entry types in one structure.
    131  */
    132 
    133 #define _BCM_TR3_L2_SELECT_REDUCED          \
    134          (_BCM_TR3_L2_SELECT_L2_ENTRY_1 | _BCM_TR3_L2_SELECT_EXT_L2_ENTRY_1)
    135 #define _BCM_TR3_L2_SELECT_EXTENDED         \
    136          (_BCM_TR3_L2_SELECT_L2_ENTRY_2 | _BCM_TR3_L2_SELECT_EXT_L2_ENTRY_2)
    137 #define _BCM_TR3_L2_SELECT_INTERNAL         \
    138          (_BCM_TR3_L2_SELECT_L2_ENTRY_1 | _BCM_TR3_L2_SELECT_L2_ENTRY_2)
    139 #define _BCM_TR3_L2_SELECT_EXTERNAL         \
    140          (_BCM_TR3_L2_SELECT_EXT_L2_ENTRY_1 | _BCM_TR3_L2_SELECT_EXT_L2_ENTRY_2)
    141 #define _BCM_TR3_L2_SELECT_ALL_TABLES       \
    142          (_BCM_TR3_L2_SELECT_REDUCED | _BCM_TR3_L2_SELECT_EXTENDED)
    143 
    144 static uint8 _bcm_tr3_l2_mems_valid[SOC_MAX_NUM_DEVICES];
    145 
    146 #define _BCM_TR3_L2_SELECT_ALL(unit) _bcm_tr3_l2_mems_valid[unit]
    147 
    148 #define _BCM_TR3_L2_MEM_BANKS_ALL       (-1)
    149 
    150 #define _BCM_TR3_L2_MEM_TYPE_VALID(_entries_, _mem_type_) \
    151         (0 != (_entries_->entry_flags & _BCM_TR3_L2_SELECT_##_mem_type_))
    152 
    153 /****************************************************************
    154  *
    155  * L2 entry field abstractions
    156  */
    157 
    158 typedef enum _bcm_tr3_l2_mem_type_e {
    159     _BCM_TR3_L2_MEM_L2_ENTRY_1,
    160     _BCM_TR3_L2_MEM_L2_ENTRY_2,
    161     _BCM_TR3_L2_MEM_EXT_L2_ENTRY_1,
    162     _BCM_TR3_L2_MEM_EXT_L2_ENTRY_2,
    163     _BCM_TR3_L2_MEM_NUM
    164 } _bcm_tr3_l2_mem_type_t;
    165 
    166 static soc_mem_t _bcm_tr3_l2_mems[_BCM_TR3_L2_MEM_NUM] = {
    167     L2_ENTRY_1m,
    168     L2_ENTRY_2m,
    169     EXT_L2_ENTRY_1m,
    170     EXT_L2_ENTRY_2m
    171 };
    172 
    173 typedef enum _bcm_tr3_l2_memacc_type_e {
    174     _BCM_TR3_L2_MEMACC_VALID,
    175     _BCM_TR3_L2_MEMACC_VALID_1,
    176     _BCM_TR3_L2_MEMACC_FREE,
    177     _BCM_TR3_L2_MEMACC_KEY_TYPE,
    178     _BCM_TR3_L2_MEMACC_KEY_TYPE_1,
    179     _BCM_TR3_L2_MEMACC_VLAN_ID,
    180     _BCM_TR3_L2_MEMACC_VFI,
    181     _BCM_TR3_L2_MEMACC_MAC_ADDR,
    182     _BCM_TR3_L2_MEMACC_PORT_NUM,
    183     _BCM_TR3_L2_MEMACC_TGID,
    184     _BCM_TR3_L2_MEMACC_L2MC_PTR,
    185     _BCM_TR3_L2_MEMACC_MODULE_ID,
    186     _BCM_TR3_L2_MEMACC_DESTINATION,
    187     _BCM_TR3_L2_MEMACC_DEST_TYPE,
    188     _BCM_TR3_L2_MEMACC_PENDING,
    189     _BCM_TR3_L2_MEMACC_LIMIT_COUNTED,
    190     _BCM_TR3_L2_MEMACC_REMOTE,
    191     _BCM_TR3_L2_MEMACC_RPE,
    192     _BCM_TR3_L2_MEMACC_PRI,
    193     _BCM_TR3_L2_MEMACC_MAC_BLOCK_INDEX,
    194     _BCM_TR3_L2_MEMACC_CLASS_ID,
    195     _BCM_TR3_L2_MEMACC_CLASS_ID_FULL,
    196     _BCM_TR3_L2_MEMACC_SCP,
    197     _BCM_TR3_L2_MEMACC_SRC_DISCARD,
    198     _BCM_TR3_L2_MEMACC_DST_DISCARD,
    199     _BCM_TR3_L2_MEMACC_DST_CPU,
    200     _BCM_TR3_L2_MEMACC_WIDE,
    201     _BCM_TR3_L2_MEMACC_WIDE_1,
    202     _BCM_TR3_L2_MEMACC_STATIC_BIT,
    203     _BCM_TR3_L2_MEMACC_STATIC_BIT_1,
    204     _BCM_TR3_L2_MEMACC_HITSA,
    205     _BCM_TR3_L2_MEMACC_HITDA,
    206     _BCM_TR3_L2_MEMACC_LOCAL_SA,
    207     _BCM_TR3_L2_MEMACC_Q_TAG,
    208     _BCM_TR3_L2_MEMACC_EH_TAG_TYPE,
    209     _BCM_TR3_L2_MEMACC_EH_TM,
    210     _BCM_TR3_L2_MEMACC_EH_QUEUE_TAG,
    211     _BCM_TR3_L2_MEMACC_NUM
    212 } _bcm_tr3_l2_memacc_type_t;
    213 
    214 static soc_field_t _bcm_tr3_l2_entry_1_field_memacc_map[_BCM_TR3_L2_MEMACC_NUM] = {
    215     VALIDf,
    216     INVALIDf,
    217     INVALIDf,
    218     KEY_TYPEf,
    219     INVALIDf,
    220     L2__VLAN_IDf,
    221     L2__VFIf,
    222     L2__MAC_ADDRf,
    223     L2__PORT_NUMf,
    224     L2__TGIDf,
    225     L2__L2MC_PTRf,
    226     L2__MODULE_IDf,
    227     L2__DESTINATIONf,
    228     L2__DEST_TYPEf,
    229     L2__PENDINGf,
    230     L2__LIMIT_COUNTEDf,
    231     L2__REMOTEf,
    232     L2__RPEf,
    233     L2__PRIf,
    234     L2__MAC_BLOCK_INDEXf,
    235     L2__CLASS_IDf,
    236     L2__CLASS_ID_FULLf,
    237     L2__SCPf,
    238     INVALIDf,
    239     INVALIDf,
    240     INVALIDf,
    241     WIDEf,
    242     INVALIDf,
    243     STATIC_BITf,
    244     INVALIDf,
    245     HITSAf,
    246     HITDAf,
    247     LOCAL_SAf,
    248     INVALIDf,
    249     INVALIDf,
    250     INVALIDf,
    251     INVALIDf,
    252 };
    253 
    254 static soc_field_t _bcm_tr3_l2_entry_2_field_memacc_map[_BCM_TR3_L2_MEMACC_NUM] = {
    255     VALID_0f,
    256     VALID_1f,
    257     INVALIDf,
    258     KEY_TYPE_0f,
    259     KEY_TYPE_1f,
    260     L2__VLAN_IDf,
    261     L2__VFIf,
    262     L2__MAC_ADDRf,
    263     L2__PORT_NUMf,
    264     L2__TGIDf,
    265     L2__L2MC_PTRf,
    266     L2__MODULE_IDf,
    267     L2__DESTINATIONf,
    268     L2__DEST_TYPEf,
    269     L2__PENDINGf,
    270     L2__LIMIT_COUNTEDf,
    271     L2__REMOTEf,
    272     L2__RPEf,
    273     L2__PRIf,
    274     L2__MAC_BLOCK_INDEXf,
    275     L2__CLASS_IDf,
    276     L2__CLASS_ID_FULLf,
    277     L2__SCPf,
    278     L2__SRC_DISCARDf,
    279     L2__DST_DISCARDf,
    280     L2__DST_CPUf,
    281     WIDE_0f,
    282     WIDE_1f,
    283     STATIC_BIT_0f,
    284     STATIC_BIT_1f,
    285     HITSAf,
    286     HITDAf,
    287     LOCAL_SAf,
    288     L2__SIRIUS_Q_TAGf,
    289     L2__EH_TAG_TYPEf,
    290     L2__EH_TMf,
    291     L2__EH_QUEUE_TAGf,
    292 };
    293 
    294 static soc_field_t _bcm_tr3_ext_l2_entry_1_field_memacc_map[_BCM_TR3_L2_MEMACC_NUM] = {
    295     INVALIDf,
    296     INVALIDf,
    297     FREEf,
    298     KEY_TYPEf,
    299     INVALIDf,
    300     VLAN_IDf,
    301     VFIf,
    302     MAC_ADDRf,
    303     PORT_NUMf,
    304     TGIDf,
    305     INVALIDf,
    306     MODULE_IDf,
    307     DESTINATIONf,
    308     DEST_TYPEf,
    309     PENDINGf,
    310     LIMIT_COUNTEDf,
    311     REMOTEf,
    312     RPEf,
    313     PRIf,
    314     MAC_BLOCK_INDEXf,
    315     CLASS_IDf,
    316     CLASS_ID_FULLf,
    317     SCPf,
    318     INVALIDf,
    319     INVALIDf,
    320     INVALIDf,
    321     INVALIDf,
    322     INVALIDf,
    323     STATIC_BITf,
    324     INVALIDf,
    325     HITSAf,
    326     HITDAf,
    327     LOCAL_SAf,
    328     INVALIDf,
    329     INVALIDf,
    330     INVALIDf,
    331     INVALIDf,
    332 };
    333 
    334 static soc_field_t _bcm_tr3_ext_l2_entry_2_field_memacc_map[_BCM_TR3_L2_MEMACC_NUM] = {
    335     INVALIDf,
    336     INVALIDf,
    337     FREEf,
    338     KEY_TYPEf,
    339     INVALIDf,
    340     VLAN_IDf,
    341     VFIf,
    342     MAC_ADDRf,
    343     PORT_NUMf,
    344     TGIDf,
    345     INVALIDf,
    346     MODULE_IDf,
    347     DESTINATIONf,
    348     DEST_TYPEf,
    349     PENDINGf,
    350     LIMIT_COUNTEDf,
    351     REMOTEf,
    352     RPEf,
    353     PRIf,
    354     MAC_BLOCK_INDEXf,
    355     CLASS_IDf,
    356     CLASS_ID_FULLf,
    357     SCPf,
    358     SRC_DISCARDf,
    359     DST_DISCARDf,
    360     CPUf,
    361     INVALIDf,
    362     INVALIDf,
    363     STATIC_BITf,
    364     INVALIDf,
    365     HITSAf,
    366     HITDAf,
    367     LOCAL_SAf,
    368     SIRIUS_Q_TAGf,
    369     EH_TAG_TYPEf,
    370     EH_TMf,
    371     EH_QUEUE_TAGf,
    372 };
    373 
    374 static soc_field_t *_bcm_tr3_l2_field_memacc_maps[_BCM_TR3_L2_MEM_NUM] = {
    375     _bcm_tr3_l2_entry_1_field_memacc_map,
    376     _bcm_tr3_l2_entry_2_field_memacc_map,
    377     _bcm_tr3_ext_l2_entry_1_field_memacc_map,
    378     _bcm_tr3_ext_l2_entry_2_field_memacc_map,
    379 };
    380 
    381 static soc_memacc_t *_bcm_tr3_l2_memacc_list[BCM_MAX_NUM_UNITS][_BCM_TR3_L2_MEM_NUM];
    382 
    383 #define _BCM_TR3_L2_MEMACC(_unit_, _mem_type_, _memacc_type_) \
    384         &(_bcm_tr3_l2_memacc_list[_unit_][_BCM_TR3_L2_MEM_##_mem_type_] \
    385                 [_memacc_type_])
    386 
    387 #define _BCM_TR3_L2_FIELD_MEMACC(_unit_, _mem_type_, _field_type_) \
    388         &(_bcm_tr3_l2_memacc_list[_unit_][_BCM_TR3_L2_MEM_##_mem_type_] \
    389                 [_BCM_TR3_L2_MEMACC_##_field_type_])
    390 
    391 #define _BCM_TR3_L2_1_FIELD_MEMACC(_unit_, _field_type_) \
    392         &(_bcm_tr3_l2_memacc_list[_unit_][_BCM_TR3_L2_MEM_L2_ENTRY_1] \
    393                 [_BCM_TR3_L2_MEMACC_##_field_type_])
    394 
    395 #define _BCM_TR3_L2_1_FIELD32_MEMACC_GET(_unit_, _entry_, _field_type_) \
    396         soc_memacc_field32_get(_BCM_TR3_L2_1_FIELD_MEMACC(_unit_, \
    397                                                    _field_type_), _entry_)
    398 
    399 #define _BCM_TR3_L2_2_FIELD_MEMACC(_unit_, _field_type_) \
    400         &(_bcm_tr3_l2_memacc_list[_unit_][_BCM_TR3_L2_MEM_L2_ENTRY_2] \
    401                 [_BCM_TR3_L2_MEMACC_##_field_type_])
    402 
    403 #define _BCM_TR3_L2_2_FIELD32_MEMACC_GET(_unit_, _entry_, _field_type_) \
    404         soc_memacc_field32_get(_BCM_TR3_L2_2_FIELD_MEMACC(_unit_, \
    405                                                    _field_type_), _entry_)
    406 
    407 #define _BCM_TR3_EXT_L2_1_FIELD_MEMACC(_unit_, _field_type_) \
    408         &(_bcm_tr3_l2_memacc_list[_unit_][_BCM_TR3_L2_MEM_EXT_L2_ENTRY_1] \
    409                 [_BCM_TR3_L2_MEMACC_##_field_type_])
    410 
    411 #define _BCM_TR3_EXT_L2_1_FIELD32_MEMACC_GET(_unit_, _entry_, _field_type_) \
    412         soc_memacc_field32_get(_BCM_TR3_EXT_L2_1_FIELD_MEMACC(_unit_, \
    413                                                    _field_type_), _entry_)
    414 
    415 #define _BCM_TR3_EXT_L2_2_FIELD_MEMACC(_unit_, _field_type_) \
    416         &(_bcm_tr3_l2_memacc_list[_unit_][_BCM_TR3_L2_MEM_EXT_L2_ENTRY_2] \
    417                 [_BCM_TR3_L2_MEMACC_##_field_type_])
    418 
    419 #define _BCM_TR3_EXT_L2_2_FIELD32_MEMACC_GET(_unit_, _entry_, _field_type_) \
    420         soc_memacc_field32_get(_BCM_TR3_EXT_L2_2_FIELD_MEMACC(_unit_, \
    421                                                    _field_type_), _entry_)
    422 
    423 /****************************************************************
    424  *
    425  * L2 data definitions
    426  */
    427 #define _BCM_TR3_L2_CLASS_ID_REDUCED_MASK 0x3f
    428 
    429 typedef struct _bcm_tr3_l2_bookkeeping_s {
    430     uint16 *my_station_hash;      /* Hash values for MY STATION entries */
    431     my_station_tcam_entry_t *my_station_shadow;
    432     my_station_tcam_entry_t my_station_l3_mask;
    433     my_station_tcam_entry_t my_station_tunnel_mask;
    434 } _bcm_tr3_l2_bookkeeping_t;
    435 
    436 static _bcm_tr3_l2_bookkeeping_t  _bcm_tr3_l2_bk_info[BCM_MAX_NUM_UNITS] = {{ 0 }};
    437 
    438 #define L2_INFO(_unit_)   (&_bcm_tr3_l2_bk_info[_unit_])
    439 #define MY_STATION_HASH(_unit_, _index_) \
    440         (_bcm_tr3_l2_bk_info[_unit_].my_station_hash[_index_])
    441 
    442 /****************************************************************
    443  *
    444  * Misc definitions
    445  */
    446 #define _BCM_ALL_L2X_MEM_LOCK(unit) \
    447         SOC_L2X_MEM_LOCK(unit); \
    448         if (soc_feature(unit, soc_feature_esm_support)) { \
    449             SOC_EXT_L2X_MEM_LOCK(unit); \
    450         }
    451 
    452 #define _BCM_ALL_L2X_MEM_UNLOCK(unit) \
    453         if (soc_feature(unit, soc_feature_esm_support)) { \
    454             SOC_EXT_L2X_MEM_UNLOCK(unit); \
    455         } \
    456         SOC_L2X_MEM_UNLOCK(unit);
    457 
    458 #define _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv) \
    459         if (!BCM_SUCCESS(rv)) { \
    460             if (soc_feature(unit, soc_feature_esm_support)) { \
    461                 SOC_EXT_L2X_MEM_UNLOCK(unit); \
    462             } \
    463             SOC_L2X_MEM_UNLOCK(unit); \
    464             return rv; \
    465         }
    466 
    467 /****************************************************************
    468  *
    469  * Debug L2 counts
    470  */
    471 /* Definition for extern variable '_l2_addr_counts' */
    472 l2_count_data_t _l2_addr_counts;
    473 
    474 STATIC int 
    475 _bcm_tr3_l2_replace(int unit, uint32 flags, bcm_l2_addr_t *match_addr, 
    476                     bcm_module_t new_module, bcm_port_t new_port, 
    477                     bcm_trunk_t new_trunk);
    478 
    479 /*
    480  * Function:
    481  *      _bcm_tr3_l2_memacc_init
    482  * Description:
    483  *      Initialize the memory accelerators for the L2 tables enabled
    484  *      on this device variation.
    485  * Parameters:
    486  *      unit - StrataSwitch unit number.
    487  */
    488 
    489 STATIC int
    490 _bcm_tr3_l2_memacc_init(int unit)
    491 {
    492     int alloc_size, rv = BCM_E_NONE;
    493     soc_field_t *memacc_map;
    494     soc_memacc_t *memacc_list;
    495     int mem_idx, mam_ix, memacc_map_size = _BCM_TR3_L2_MEMACC_NUM;
    496 
    497     alloc_size = (memacc_map_size * sizeof(soc_memacc_t));
    498 
    499     for (mem_idx = _BCM_TR3_L2_MEM_L2_ENTRY_1;
    500          mem_idx < _BCM_TR3_L2_MEM_NUM;
    501          mem_idx++) {
    502         if (0 == (_BCM_TR3_L2_SELECT_ALL(unit) & (1 << mem_idx))) {
    503             /* Table not enabled in this configuration */
    504             continue;
    505         }
    506 
    507         _bcm_tr3_l2_memacc_list[unit][mem_idx] =
    508             sal_alloc(alloc_size, "L2 tables memacc data");
    509         if (NULL == _bcm_tr3_l2_memacc_list[unit][mem_idx]) {
    510             rv = BCM_E_MEMORY;
    511             break;
    512         }
    513 
    514         memacc_map = _bcm_tr3_l2_field_memacc_maps[mem_idx];
    515         memacc_list = _bcm_tr3_l2_memacc_list[unit][mem_idx];
    516 
    517         for (mam_ix = 0; mam_ix < memacc_map_size; mam_ix++) {
    518             if (INVALIDf == memacc_map[mam_ix]) {
    519                 SOC_MEMACC_INVALID_SET(&(memacc_list[mam_ix]));
    520                 continue;
    521             }
    522             rv = soc_memacc_init(unit, _bcm_tr3_l2_mems[mem_idx],
    523                                  memacc_map[mam_ix],
    524                                  &(memacc_list[mam_ix]));
    525             if (BCM_FAILURE(rv)) {
    526                 break;
    527             }
    528         }
    529 
    530         if (BCM_FAILURE(rv)) {
    531             break;
    532         }
    533     }
    534 
    535     return rv;
    536 }
    537 
    538 typedef struct _bcm_tr3_l2_valid_memacc_s {
    539     soc_memacc_t *valid;
    540     soc_memacc_t *key_type;
    541     soc_memacc_t *free;
    542     soc_memacc_t *wide;
    543 } _bcm_tr3_l2_valid_memacc_t;
    544 
    545 /*
    546  * Function:
    547  *     _bcm_tr3_l2_entry_traverse_valid
    548  * Description:
    549  *      Check if given traversed L2 entry is Valid
    550  * Parameters:
    551  *      memacc_list L2 memory accessors pre-loaded
    552  *      l2_entry    L2 entry read from HW
    553  *      valid       (OUT) Entry valid indicator
    554  * Return:
    555  *     BCM_E_XXX
    556  */
    557 int 
    558 _bcm_tr3_l2_entry_traverse_valid(_bcm_tr3_l2_valid_memacc_t *memacc_list,
    559                                  uint32 *l2_entry, int *valid)
    560 {
    561     uint32  fval = 0;
    562     int     key_type;
    563 
    564     if ((NULL == l2_entry) || (NULL == valid) || (NULL == memacc_list)) {
    565         return BCM_E_PARAM;
    566     }
    567 
    568     if (NULL != memacc_list->valid) {
    569         fval = soc_memacc_field32_get(memacc_list->valid, l2_entry);
    570 
    571         if (fval && memacc_list->key_type) {
    572             key_type =
    573                 soc_memacc_field32_get(memacc_list->key_type, l2_entry);
    574             if ((SOC_MEM_KEY_L2_ENTRY_1_L2_VFI != key_type) &&
    575                 (SOC_MEM_KEY_L2_ENTRY_1_L2_BRIDGE != key_type) &&
    576                  (SOC_MEM_KEY_L2_ENTRY_2_L2_VFI != key_type) &&
    577                  (SOC_MEM_KEY_L2_ENTRY_2_L2_BRIDGE != key_type)) {
    578                 /* Skip non-bridge/VFI L2 entries */
    579                 fval = 0;
    580             }
    581         }
    582     } else if (NULL != memacc_list->free) {
    583         fval = !soc_memacc_field32_get(memacc_list->free, l2_entry);
    584     }
    585 
    586     *valid = fval ? TRUE : FALSE;
    587 
    588     return (BCM_E_NONE);
    589 }
    590 
    591 /*
    592  * Function:
    593  *     _bcm_tr3_l2_traverse_mem
    594  * Description:
    595  *      Helper function to _bcm_tr3_l2_traverse to itterate over given
    596  *      memory and actually read the table and parse entries.
    597  * Parameters:
    598  *     unit         device number
    599  *     mem          L2 memory to read
    600  *     trav_st      Traverse structure with all the data.
    601  * Return:
    602  *     BCM_E_XXX
    603  */
    604 int 
    605 _bcm_tr3_l2_traverse_mem(int unit, soc_mem_t mem,
    606                          _bcm_l2_traverse_t *trav_st)
    607 {
    608     /* Indexes to iterate over memories, chunks and entries */
    609     int             chnk_idx, ent_idx, chnk_idx_max, mem_idx_max;
    610     int             buf_size, valid, chunksize, chnk_end;
    611     /* Buffer to store chunk of L2 table we currently work on */
    612     uint32          *l2_tbl_chnk;
    613     uint32          *l2_entry;
    614     int             rv = BCM_E_NONE;
    615     uint32          l2_entry_2[SOC_MAX_MEM_WORDS];
    616     uint32          *l2_src[4] = {0};
    617     _bcm_tr3_l2_valid_memacc_t l2_trav_memaccs;
    618     
    619     if (!soc_mem_index_count(unit, mem)) {
    620         return BCM_E_NONE;
    621     }
    622 
    623     chunksize = soc_property_get(unit, spn_L2DELETE_CHUNKS,
    624                                  L2_MEM_CHUNKS_DEFAULT);
    625 
    626     buf_size = 4 * SOC_MAX_MEM_FIELD_WORDS * chunksize;
    627     l2_tbl_chnk = soc_cm_salloc(unit, buf_size, "l2 traverse");
    628     if (NULL == l2_tbl_chnk) {
    629         return BCM_E_MEMORY;
    630     }
    631 
    632     switch (mem) {
    633     case L2_ENTRY_1m:
    634         l2_trav_memaccs.valid = _BCM_TR3_L2_MEMACC(unit, L2_ENTRY_1,
    635                                                    _BCM_TR3_L2_MEMACC_VALID);
    636         l2_trav_memaccs.key_type = _BCM_TR3_L2_MEMACC(unit, L2_ENTRY_1,
    637                                          _BCM_TR3_L2_MEMACC_KEY_TYPE);
    638         l2_trav_memaccs.free = NULL;
    639         l2_trav_memaccs.wide = _BCM_TR3_L2_MEMACC(unit, L2_ENTRY_1,
    640                                          _BCM_TR3_L2_MEMACC_WIDE);
    641         break;
    642     case EXT_L2_ENTRY_1m:
    643         l2_trav_memaccs.valid = NULL;
    644         l2_trav_memaccs.key_type = NULL;
    645         l2_trav_memaccs.free = _BCM_TR3_L2_MEMACC(unit, EXT_L2_ENTRY_1,
    646                                                   _BCM_TR3_L2_MEMACC_FREE);
    647         l2_trav_memaccs.wide = NULL;
    648         break;
    649     case EXT_L2_ENTRY_2m:
    650         l2_trav_memaccs.valid = NULL;
    651         l2_trav_memaccs.key_type = NULL;
    652         l2_trav_memaccs.free = _BCM_TR3_L2_MEMACC(unit, EXT_L2_ENTRY_2,
    653                                                   _BCM_TR3_L2_MEMACC_FREE);
    654         l2_trav_memaccs.wide = NULL;
    655         break;
    656     default:
    657         return BCM_E_INTERNAL;
    658     }
    659 
    660     mem_idx_max = soc_mem_index_max(unit, mem);
    661     for (chnk_idx = soc_mem_index_min(unit, mem); chnk_idx <= mem_idx_max; 
    662          chnk_idx += chunksize) {
    663         sal_memset((void *)l2_tbl_chnk, 0, buf_size);
    664 
    665         chnk_idx_max = 
    666             ((chnk_idx + chunksize) < mem_idx_max) ? 
    667             (chnk_idx + chunksize - 1) : mem_idx_max;
    668 
    669         soc_mem_lock(unit, mem);
    670         rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY,
    671                                 chnk_idx, chnk_idx_max, l2_tbl_chnk);
    672         soc_mem_unlock(unit, mem);
    673         if (SOC_FAILURE(rv)) {
    674             break;
    675         }
    676         chnk_end = (chnk_idx_max - chnk_idx);
    677         for (ent_idx = 0 ; ent_idx <= chnk_end; ent_idx ++) {
    678             l2_entry = 
    679                 soc_mem_table_idx_to_pointer(unit, mem, uint32 *, 
    680                                              l2_tbl_chnk, ent_idx);
    681             rv = _bcm_tr3_l2_entry_traverse_valid(&l2_trav_memaccs,
    682                                                   l2_entry, &valid);
    683             if (BCM_FAILURE(rv)) {
    684                 break;
    685             }
    686 
    687             if (FALSE == valid) {
    688                 continue;
    689             }
    690 
    691             if ((NULL != l2_trav_memaccs.wide) &&
    692                 (0 != soc_memacc_field32_get(l2_trav_memaccs.wide,
    693                                              l2_entry))) {
    694                 /* The first element of an L2_ENTRY_2 entry detected */
    695                 l2_src[0] = l2_entry;
    696                 l2_src[1] = soc_mem_table_idx_to_pointer(unit, mem, uint32 *, 
    697                                              l2_tbl_chnk, ent_idx + 1);
    698 
    699                 soc_mem_base_to_wide_entry_conv(unit, L2_ENTRY_2m,
    700                                                 L2_ENTRY_1m,
    701                                                 l2_entry_2, l2_src,
    702                                                 TYPE_1_TO_TYPE_2);
    703 
    704                 trav_st->data = l2_entry_2;
    705                 trav_st->mem = L2_ENTRY_2m;
    706                 trav_st->mem_idx = (chnk_idx + ent_idx) / 2;
    707                 ent_idx++;
    708             } else {
    709                 trav_st->data = l2_entry;
    710                 trav_st->mem = mem;
    711                 trav_st->mem_idx = chnk_idx + ent_idx;
    712             }
    713             rv = trav_st->int_cb(unit, (void *)trav_st);
    714             if (BCM_FAILURE(rv)) {
    715                 break;
    716             }
    717         }
    718         if (BCM_FAILURE(rv)) {
    719             break;
    720         }
    721     }
    722     soc_cm_sfree(unit, l2_tbl_chnk);
    723     return rv;        
    724 }
    725 
    726 /*
    727  * Function:
    728  *     _bcm_tr3_l2_traverse
    729  * Description:
    730  *      Helper function to bcm_tr3_l2_traverse to itterate over tables 
    731  *      and actually read the momery
    732  * Parameters:
    733  *     unit         device number
    734  *     trav_st      Traverse structure with all the data.
    735  * Return:
    736  *     BCM_E_XXX
    737  */
    738 int 
    739 _bcm_tr3_l2_traverse(int unit, _bcm_l2_traverse_t *trav_st)
    740 {
    741     BCM_IF_ERROR_RETURN
    742         (_bcm_tr3_l2_traverse_mem(unit, L2_ENTRY_1m, trav_st));
    743 
    744     if (soc_feature(unit, soc_feature_esm_support)) {
    745         BCM_IF_ERROR_RETURN
    746             (_bcm_tr3_l2_traverse_mem(unit, EXT_L2_ENTRY_1m, trav_st));
    747         BCM_IF_ERROR_RETURN
    748             (_bcm_tr3_l2_traverse_mem(unit, EXT_L2_ENTRY_2m, trav_st));
    749     }
    750 
    751     return BCM_E_NONE;
    752 }
    753 
    754 #ifdef BCM_WARM_BOOT_SUPPORT
    755 int
    756 _bcm_tr3_l2_reload_mbi_cb(int unit, void *trav_st)
    757 {
    758     int                 mb_index;
    759     _bcm_l2_traverse_t *trv = (_bcm_l2_traverse_t *)trav_st;
    760     _bcm_tr3_mac_block_info_t *mbi = trv->user_data;
    761 
    762     trv = (_bcm_l2_traverse_t *)trav_st;
    763 
    764     switch(trv->mem) {
    765     case L2_ENTRY_1m:
    766         mb_index = _BCM_TR3_L2_1_FIELD32_MEMACC_GET(unit, trv->data,
    767                                                     MAC_BLOCK_INDEX);
    768         break;
    769     case L2_ENTRY_2m:
    770         mb_index = _BCM_TR3_L2_2_FIELD32_MEMACC_GET(unit, trv->data,
    771                                                     MAC_BLOCK_INDEX);
    772         break;
    773     case EXT_L2_ENTRY_1m:
    774         mb_index = _BCM_TR3_EXT_L2_1_FIELD32_MEMACC_GET(unit, trv->data,
    775                                                         MAC_BLOCK_INDEX);
    776         break;
    777     case EXT_L2_ENTRY_2m:
    778         mb_index = _BCM_TR3_EXT_L2_1_FIELD32_MEMACC_GET(unit, trv->data,
    779                                                         MAC_BLOCK_INDEX);
    780         break;
    781     default:
    782         return BCM_E_INTERNAL;
    783     }
    784 
    785     mbi[mb_index].ref_count++;
    786     return BCM_E_NONE;
    787 }
    788 
    789 /*
    790  * Function:
    791  *      _bcm_tr3_l2_reload_mbi
    792  * Description:
    793  *      Load MAC block info from hardware into software data structures.
    794  * Parameters:
    795  *      unit - StrataSwitch unit number.
    796  */
    797 
    798 STATIC int
    799 _bcm_tr3_l2_reload_mbi(int unit)
    800 {
    801     _bcm_tr3_mac_block_info_t *mbi = _tr3_mbi_entries[unit];
    802     mac_block_entry_t   mbe;
    803     int                 mb_index;
    804     pbmp_t              mb_pbmp;
    805     _bcm_l2_traverse_t  trav_st;
    806 
    807     /*
    808      * Refresh MAC Block information from the hardware tables.
    809      */
    810 
    811     for (mb_index = 0; mb_index < _tr3_mbi_num[unit]; mb_index++) {
    812         SOC_IF_ERROR_RETURN
    813             (READ_MAC_BLOCKm(unit, MEM_BLOCK_ANY, mb_index, &mbe));
    814 
    815         SOC_PBMP_CLEAR(mb_pbmp);
    816 
    817         SOC_PBMP_WORD_SET(mb_pbmp, 0, soc_MAC_BLOCKm_field32_get(unit,
    818                              &mbe, MAC_BLOCK_MASK_W0f));
    819         SOC_PBMP_WORD_SET(mb_pbmp, 1, soc_MAC_BLOCKm_field32_get(unit,
    820                              &mbe, MAC_BLOCK_MASK_W1f));
    821         BCM_PBMP_ASSIGN(mbi[mb_index].mb_pbmp, mb_pbmp);
    822     }
    823 
    824     if (!SOC_CONTROL(unit)->l2x_group_enable) {
    825         sal_memset(&trav_st, 0, sizeof(_bcm_l2_traverse_t));
    826     
    827         trav_st.user_cb = NULL;
    828         trav_st.user_data = mbi;
    829         trav_st.int_cb = _bcm_tr3_l2_reload_mbi_cb;
    830         BCM_IF_ERROR_RETURN(_bcm_tr3_l2_traverse(unit, &trav_st));
    831     }
    832 
    833     return BCM_E_NONE;
    834 }
    835 #endif /* BCM_WARM_BOOT_SUPPORT */
    836 
    837 /*
    838  * Function:
    839  *      _bcm_tr3_l2_mbi_init
    840  * Purpose:
    841  *      Initialize BCM L2 MAC block index data.
    842  * Parameters:
    843  *      unit - (IN) Unit number.
    844  * Returns:
    845  *      BCM_E_xxx
    846  * Notes:
    847  */
    848 int 
    849 _bcm_tr3_l2_mbi_init(int unit)
    850 {
    851     if (_tr3_mbi_entries[unit] != NULL) {
    852         sal_free(_tr3_mbi_entries[unit]);
    853         _tr3_mbi_entries[unit] = NULL;
    854     }
    855 
    856     _tr3_mbi_num[unit] = soc_mem_index_count(unit, MAC_BLOCKm);
    857     _tr3_mbi_entries[unit] = sal_alloc(_tr3_mbi_num[unit] *
    858                                    sizeof(_bcm_tr3_mac_block_info_t),
    859                                    "BCM L2X MAC blocking info");
    860     if (!_tr3_mbi_entries[unit]) {
    861         return BCM_E_MEMORY;
    862     }
    863 
    864     sal_memset(_tr3_mbi_entries[unit], 0,
    865                _tr3_mbi_num[unit] * sizeof(_bcm_tr3_mac_block_info_t));
    866 
    867 #ifdef BCM_WARM_BOOT_SUPPORT
    868     if (SOC_WARM_BOOT(unit)) {
    869         BCM_IF_ERROR_RETURN(_bcm_tr3_l2_reload_mbi(unit));
    870     }
    871 #endif /* BCM_WARM_BOOT_SUPPORT */
    872 
    873     return BCM_E_NONE;
    874 }
    875 
    876 /*
    877  * Function:
    878  *      _bcm_tr3_mac_block_insert
    879  * Purpose:
    880  *      Find or create a MAC_BLOCK table entry matching the given bitmap.
    881  * Parameters:
    882  *      unit - Unit number
    883  *      mb_pbmp - egress port bitmap for source MAC blocking
    884  *      mb_index - (OUT) Index of MAC_BLOCK table with bitmap.
    885  * Returns:
    886  *      BCM_E_NONE              Success
    887  *      BCM_E_INTERNAL          Chip access failure
    888  *      BCM_E_RESOURCE          No more MAC_BLOCK entries available
    889  *      BCM_E_PARAM             Bad bitmap supplied
    890  */
    891 STATIC int
    892 _bcm_tr3_mac_block_insert(int unit, bcm_pbmp_t mb_pbmp, int *mb_index)
    893 {
    894     int cur_index = 0;
    895     _bcm_tr3_mac_block_info_t *mbi = _tr3_mbi_entries[unit];
    896     mac_block_entry_t mbe;
    897     bcm_pbmp_t temp_pbmp;
    898 
    899     /* Check for reasonable pbmp */
    900     BCM_PBMP_ASSIGN(temp_pbmp, mb_pbmp);
    901     BCM_PBMP_AND(temp_pbmp, PBMP_ALL(unit));
    902     if (BCM_PBMP_NEQ(mb_pbmp, temp_pbmp)) {
    903         return BCM_E_PARAM;
    904     }
    905 
    906     for (cur_index = 0; cur_index < _tr3_mbi_num[unit]; cur_index++) {
    907         if (BCM_PBMP_EQ(mbi[cur_index].mb_pbmp, mb_pbmp)) {
    908             mbi[cur_index].ref_count++;
    909             *mb_index = cur_index;
    910             return BCM_E_NONE;
    911         }
    912     }
    913 
    914     /* Not in table already, see if any space free */
    915     for (cur_index = 1; cur_index < _tr3_mbi_num[unit]; cur_index++) {
    916         if (mbi[cur_index].ref_count == 0) {
    917             /* Attempt insert */
    918             sal_memset(&mbe, 0, sizeof(mac_block_entry_t));
    919 
    920             soc_mem_pbmp_field_set(unit, MAC_BLOCKm, &mbe, MAC_BLOCK_MASKf,
    921                                    &mb_pbmp); 
    922             SOC_IF_ERROR_RETURN(WRITE_MAC_BLOCKm(unit, MEM_BLOCK_ALL,
    923                                                  cur_index, &mbe));
    924             mbi[cur_index].ref_count++;
    925             BCM_PBMP_ASSIGN(mbi[cur_index].mb_pbmp, mb_pbmp);
    926             *mb_index = cur_index;
    927             return BCM_E_NONE;
    928         }
    929     }
    930 
    931     /* Didn't find a free slot, out of table space */
    932     return BCM_E_RESOURCE;
    933 }
    934 
    935 /*
    936  * Function:
    937  *      _bcm_tr3_mac_block_delete
    938  * Purpose:
    939  *      Remove reference to MAC_BLOCK table entry matching the given bitmap.
    940  * Parameters:
    941  *      unit - Unit number
    942  *      mb_index - Index of MAC_BLOCK table with bitmap.
    943  */
    944 STATIC void
    945 _bcm_tr3_mac_block_delete(int unit, int mb_index)
    946 {
    947     if (_tr3_mbi_entries[unit][mb_index].ref_count > 0) {
    948         _tr3_mbi_entries[unit][mb_index].ref_count--;
    949     } else if (mb_index) {
    950         
    951         /* Someone reran init without flushing the L2 table */
    952     } /* else mb_index = 0, as expected for learning */
    953 }
    954 
    955 /*
    956  * Function:
    957  *      _bcm_tr3_l2hw_entries_field32_set
    958  * Purpose:
    959  *      Set a field32 value for a Triumph3 L2 entry collection
    960  * Parameters:
    961  *      unit        Unit number
    962  *      l2_entries  (IN/OUT) Triumph3 L2 entries structure
    963  *      l2_field    Memacc type
    964  *      val         Field value to set
    965  */
    966 void
    967 _bcm_tr3_l2hw_entries_field32_set(int unit,
    968                                   _bcm_tr3_l2_entries_t *l2_entries,
    969                                   _bcm_tr3_l2_memacc_type_t l2_field,
    970                                   uint32 val)
    971 {
    972     soc_memacc_t *memacc;
    973 
    974     if (l2_entries->entry_flags & _BCM_TR3_L2_SELECT_L2_ENTRY_1) {
    975         /* L2_ENTRY_1 */
    976         memacc = _BCM_TR3_L2_MEMACC(unit, L2_ENTRY_1, l2_field);
    977         if (SOC_MEMACC_VALID(memacc)) {
    978             soc_memacc_field32_set(memacc, &(l2_entries->l2_entry_1), val);
    979         }
    980     }
    981     if (l2_entries->entry_flags & _BCM_TR3_L2_SELECT_L2_ENTRY_2) {
    982         /* L2_ENTRY_2 */
    983         memacc = _BCM_TR3_L2_MEMACC(unit, L2_ENTRY_2, l2_field);
    984         if (SOC_MEMACC_VALID(memacc)) {
    985             soc_memacc_field32_set(memacc, &(l2_entries->l2_entry_2), val);
    986         }
    987     }
    988     if (l2_entries->entry_flags & _BCM_TR3_L2_SELECT_EXT_L2_ENTRY_1) {
    989         /* EXT_L2_ENTRY_1 */
    990         memacc = _BCM_TR3_L2_MEMACC(unit, EXT_L2_ENTRY_1, l2_field);
    991         if (SOC_MEMACC_VALID(memacc)) {
    992             soc_memacc_field32_set(memacc,
    993                                    &(l2_entries->ext_l2_entry_1), val);
    994         }
    995     }
    996     if (l2_entries->entry_flags & _BCM_TR3_L2_SELECT_EXT_L2_ENTRY_2) {
    997         /* EXT_L2_ENTRY_2 */
    998         memacc = _BCM_TR3_L2_MEMACC(unit, EXT_L2_ENTRY_2, l2_field);
    999         if (SOC_MEMACC_VALID(memacc)) {
   1000             soc_memacc_field32_set(memacc,
   1001                                    &(l2_entries->ext_l2_entry_2), val);
   1002         }
   1003     }
   1004 }
   1005 
   1006 /*
   1007  * Function:
   1008  *      _bcm_tr3_l2hw_entries_field32_get
   1009  * Purpose:
   1010  *      Get a field32 value from a Triumph3 L2 entry collection
   1011  * Parameters:
   1012  *      unit        Unit number
   1013  *      l2_entries  Triumph3 L2 entries structure
   1014  *      l2_field    
   1015  */
   1016 uint32
   1017 _bcm_tr3_l2hw_entries_field32_get(int unit,
   1018                                   _bcm_tr3_l2_entries_t *l2_entries,
   1019                                   _bcm_tr3_l2_memacc_type_t l2_field)
   1020 {
   1021     soc_memacc_t *memacc;
   1022 
   1023     if (l2_entries->entry_flags & _BCM_TR3_L2_SELECT_L2_ENTRY_1) {
   1024         /* L2_ENTRY_1 */
   1025         memacc = _BCM_TR3_L2_MEMACC(unit, L2_ENTRY_1, l2_field);
   1026         if (SOC_MEMACC_VALID(memacc)) {
   1027             return soc_memacc_field32_get(memacc, &(l2_entries->l2_entry_1));
   1028         }
   1029     } else if (l2_entries->entry_flags & _BCM_TR3_L2_SELECT_L2_ENTRY_2) {
   1030         /* L2_ENTRY_2 */
   1031         memacc = _BCM_TR3_L2_MEMACC(unit, L2_ENTRY_2, l2_field);
   1032         if (SOC_MEMACC_VALID(memacc)) {
   1033             return soc_memacc_field32_get(memacc, &(l2_entries->l2_entry_2));
   1034         }
   1035     } else if (l2_entries->entry_flags & _BCM_TR3_L2_SELECT_EXT_L2_ENTRY_1) {
   1036         /* EXT_L2_ENTRY_1 */
   1037         memacc = _BCM_TR3_L2_MEMACC(unit, EXT_L2_ENTRY_1, l2_field);
   1038         if (SOC_MEMACC_VALID(memacc)) {
   1039             return soc_memacc_field32_get(memacc,
   1040                                           &(l2_entries->ext_l2_entry_1));
   1041         }
   1042     } else if (l2_entries->entry_flags & _BCM_TR3_L2_SELECT_EXT_L2_ENTRY_2) {
   1043         /* L2_ENTRY_2 */
   1044         memacc = _BCM_TR3_L2_MEMACC(unit, EXT_L2_ENTRY_2, l2_field);
   1045         if (SOC_MEMACC_VALID(memacc)) {
   1046             return soc_memacc_field32_get(memacc,
   1047                                           &(l2_entries->ext_l2_entry_2));
   1048         }
   1049     }
   1050 
   1051     return 0;
   1052 }
   1053 
   1054 /*
   1055  * Function:
   1056  *      _bcm_tr3_l2api_to_l2hw
   1057  * Purpose:
   1058  *      Convert an L2 API data structure to a Triumph3 L2 entry collection
   1059  * Parameters:
   1060  *      unit        Unit number
   1061  *      l2_entries  (OUT) Triumph3 L2 entries structure
   1062  *      l2addr      L2 API data structure
   1063  *      key_only    Only construct key portion
   1064  */
   1065 int
   1066 _bcm_tr3_l2api_to_l2hw(int unit, _bcm_tr3_l2_entries_t *l2_entries,
   1067                        bcm_l2_addr_t *l2addr, int key_only)
   1068 {
   1069     int is_vfi = FALSE;
   1070     bcm_vlan_t vid, vlan_vfi;
   1071     _bcm_tr3_l2_memacc_type_t field_type;
   1072     soc_memacc_t *memacc;
   1073     uint32 field_val;
   1074     int pri_field_len;
   1075     int max_pri;
   1076 
   1077     pri_field_len = soc_mem_field_length(unit, L2_ENTRY_1m, PRIf);
   1078     max_pri = (1 << pri_field_len) - 1;
   1079 
   1080     /* Allow the maximum priority as per the device table support */
   1081     if ((l2addr->cos_dst < BCM_PRIO_MIN) || (l2addr->cos_dst > max_pri)) {
   1082             return BCM_E_PARAM;
   1083     }
   1084 
   1085     /*  BCM_L2_MIRROR is not supported starting from Triumph */
   1086     if (l2addr->flags & BCM_L2_MIRROR) {
   1087         return BCM_E_PARAM;
   1088     }
   1089 
   1090     /* Setting both flags is not a valid configuration. */
   1091     if ((l2addr->flags & BCM_L2_LEARN_LIMIT_EXEMPT) &&
   1092         (l2addr->flags & BCM_L2_LEARN_LIMIT_EXEMPT_LOCAL)) {
   1093         return BCM_E_PARAM;
   1094     }
   1095 
   1096     vlan_vfi = vid = l2addr->vid;
   1097     if (_BCM_VPN_VFI_IS_SET(vid)) {
   1098         is_vfi = TRUE;
   1099         _BCM_VPN_GET(vlan_vfi, _BCM_VPN_TYPE_VFI, vid);
   1100     }
   1101 
   1102     field_type = _BCM_TR3_L2_MEMACC_VLAN_ID;
   1103     if (is_vfi) {
   1104         field_type = _BCM_TR3_L2_MEMACC_VFI;
   1105     } else if (!_BCM_VPN_VFI_IS_SET(vid)) {
   1106         VLAN_CHK_ID(unit, vid);
   1107     }
   1108 
   1109     if (is_vfi || !_BCM_VPN_VFI_IS_SET(vid)) {
   1110         /* VLAN field, all desired entries */
   1111         _bcm_tr3_l2hw_entries_field32_set(unit, l2_entries,
   1112                                           field_type, vlan_vfi);
   1113         /* The key types are different per entry type,
   1114          * so handle individually here */
   1115         if (_BCM_TR3_L2_MEM_TYPE_VALID(l2_entries, L2_ENTRY_1)) {
   1116             /* L2_ENTRY_1 */
   1117             field_val = is_vfi ?
   1118                 SOC_MEM_KEY_L2_ENTRY_1_L2_VFI :
   1119                 SOC_MEM_KEY_L2_ENTRY_1_L2_BRIDGE;
   1120             memacc = _BCM_TR3_L2_MEMACC(unit, L2_ENTRY_1,
   1121                                         _BCM_TR3_L2_MEMACC_KEY_TYPE);
   1122             soc_memacc_field32_set(memacc, &(l2_entries->l2_entry_1), 
   1123                                    field_val);
   1124         }
   1125         if (_BCM_TR3_L2_MEM_TYPE_VALID(l2_entries, L2_ENTRY_2)) {
   1126             /* L2_ENTRY_2 */
   1127             field_val = is_vfi ?
   1128                 SOC_MEM_KEY_L2_ENTRY_2_L2_VFI :
   1129                 SOC_MEM_KEY_L2_ENTRY_2_L2_BRIDGE;
   1130             memacc = _BCM_TR3_L2_MEMACC(unit, L2_ENTRY_2,
   1131                                         _BCM_TR3_L2_MEMACC_KEY_TYPE);
   1132             soc_memacc_field32_set(memacc, &(l2_entries->l2_entry_2), 
   1133                                    field_val);
   1134             memacc = _BCM_TR3_L2_MEMACC(unit, L2_ENTRY_2,
   1135                                         _BCM_TR3_L2_MEMACC_KEY_TYPE_1);
   1136             soc_memacc_field32_set(memacc, &(l2_entries->l2_entry_2), 
   1137                                    field_val);
   1138         }
   1139         if (_BCM_TR3_L2_MEM_TYPE_VALID(l2_entries, EXT_L2_ENTRY_1)) {
   1140             /* EXT_L2_ENTRY_1 */
   1141             field_val = is_vfi ?
   1142                 SOC_MEM_KEY_EXT_L2_ENTRY_1_L2_VFI :
   1143                 SOC_MEM_KEY_EXT_L2_ENTRY_1_L2_BRIDGE;
   1144             memacc = _BCM_TR3_L2_MEMACC(unit, EXT_L2_ENTRY_1,
   1145                                         _BCM_TR3_L2_MEMACC_KEY_TYPE);
   1146             soc_memacc_field32_set(memacc, &(l2_entries->ext_l2_entry_1), 
   1147                                    field_val);
   1148         }
   1149         if (_BCM_TR3_L2_MEM_TYPE_VALID(l2_entries, EXT_L2_ENTRY_2)) {
   1150             /* EXT_L2_ENTRY_2 */
   1151             field_val = is_vfi ?
   1152                 SOC_MEM_KEY_EXT_L2_ENTRY_2_L2_VFI :
   1153                 SOC_MEM_KEY_EXT_L2_ENTRY_2_L2_BRIDGE;
   1154             memacc = _BCM_TR3_L2_MEMACC(unit, EXT_L2_ENTRY_2,
   1155                                         _BCM_TR3_L2_MEMACC_KEY_TYPE);
   1156             soc_memacc_field32_set(memacc, &(l2_entries->ext_l2_entry_2), 
   1157                                    field_val);
   1158         }
   1159     }
   1160 
   1161     /* MAC address has individual macros, so handle here */
   1162     field_type = _BCM_TR3_L2_MEMACC_MAC_ADDR;
   1163     if (l2_entries->entry_flags & _BCM_TR3_L2_SELECT_L2_ENTRY_1) {
   1164         memacc = _BCM_TR3_L2_MEMACC(unit, L2_ENTRY_1,
   1165                                     _BCM_TR3_L2_MEMACC_MAC_ADDR);
   1166         soc_memacc_mac_addr_set(memacc, &(l2_entries->l2_entry_1), 
   1167                                 l2addr->mac);
   1168     }
   1169     if (l2_entries->entry_flags & _BCM_TR3_L2_SELECT_L2_ENTRY_2) {
   1170         memacc = _BCM_TR3_L2_MEMACC(unit, L2_ENTRY_2,
   1171                                     _BCM_TR3_L2_MEMACC_MAC_ADDR);
   1172         soc_memacc_mac_addr_set(memacc, &(l2_entries->l2_entry_2), 
   1173                                 l2addr->mac);
   1174     }
   1175     if (l2_entries->entry_flags & _BCM_TR3_L2_SELECT_EXT_L2_ENTRY_1) {
   1176         memacc = _BCM_TR3_L2_MEMACC(unit, EXT_L2_ENTRY_1,
   1177                                     _BCM_TR3_L2_MEMACC_MAC_ADDR);
   1178         soc_memacc_mac_addr_set(memacc, &(l2_entries->ext_l2_entry_1), 
   1179                                 l2addr->mac);
   1180     }
   1181     if (l2_entries->entry_flags & _BCM_TR3_L2_SELECT_EXT_L2_ENTRY_2) {
   1182         memacc = _BCM_TR3_L2_MEMACC(unit, EXT_L2_ENTRY_2,
   1183                                     _BCM_TR3_L2_MEMACC_MAC_ADDR);
   1184         soc_memacc_mac_addr_set(memacc, &(l2_entries->ext_l2_entry_2), 
   1185                                 l2addr->mac);
   1186     }
   1187 
   1188     /* At this point, we've set the bridge/VFI key info ISM or ESM entries.
   1189      * We can use these to search for any existing entry of this key.
   1190      */
   1191     if (key_only) {
   1192         return BCM_E_NONE;
   1193     }
   1194 
   1195     if (BCM_MAC_IS_MCAST(l2addr->mac)) {
   1196         if (l2addr->l2mc_group < 0) {
   1197             return BCM_E_PARAM;
   1198         }
   1199         if (_BCM_MULTICAST_IS_VPLS(l2addr->l2mc_group) ||
   1200             _BCM_MULTICAST_IS_MIM(l2addr->l2mc_group) ||
   1201             _BCM_MULTICAST_IS_WLAN(l2addr->l2mc_group) ||
   1202             _BCM_MULTICAST_IS_VLAN(l2addr->l2mc_group) ||
   1203             _BCM_MULTICAST_IS_NIV(l2addr->l2mc_group) ||
   1204             _BCM_MULTICAST_IS_L2GRE(l2addr->l2mc_group) ||
   1205             _BCM_MULTICAST_IS_SUBPORT(l2addr->l2mc_group) ||
   1206             _BCM_MULTICAST_IS_EXTENDER(l2addr->l2mc_group)) {
   1207             _bcm_tr3_l2hw_entries_field32_set(unit, l2_entries,
   1208                           _BCM_TR3_L2_MEMACC_DEST_TYPE, 0x3);
   1209         }
   1210 
   1211         if (_BCM_MULTICAST_IS_SET(l2addr->l2mc_group)) {
   1212             _bcm_tr3_l2hw_entries_field32_set(unit, l2_entries,
   1213                           _BCM_TR3_L2_MEMACC_DESTINATION,
   1214                                  _BCM_MULTICAST_ID_GET(l2addr->l2mc_group));
   1215         } else {
   1216             _bcm_tr3_l2hw_entries_field32_set(unit, l2_entries,
   1217                           _BCM_TR3_L2_MEMACC_L2MC_PTR,
   1218                                               l2addr->l2mc_group);
   1219         }
   1220     } else {
   1221         bcm_port_t      port = -1;
   1222         bcm_trunk_t     tgid = BCM_TRUNK_INVALID;
   1223         bcm_module_t    modid = -1;
   1224         int             gport_id = -1;
   1225 
   1226         if (BCM_GPORT_IS_SET(l2addr->port)) {
   1227             _bcm_l2_gport_params_t  g_params;
   1228 
   1229             if (BCM_GPORT_IS_BLACK_HOLE(l2addr->port)) {
   1230                 /* Must use an extended entry for this property */
   1231                 l2_entries->entry_flags &= _BCM_TR3_L2_SELECT_EXTENDED;
   1232                 _bcm_tr3_l2hw_entries_field32_set(unit, l2_entries,
   1233                               _BCM_TR3_L2_MEMACC_SRC_DISCARD, 1);
   1234             } else {
   1235                 /*
   1236                  * The SRC_DISCARD field only exists in some entry types,
   1237                  * was cleared with the init of the entries structure
   1238                  * when this was called.
   1239                  */
   1240                 BCM_IF_ERROR_RETURN
   1241                     (_bcm_esw_l2_gport_parse(unit, l2addr, &g_params));
   1242 
   1243                 switch (g_params.type) {
   1244                 case _SHR_GPORT_TYPE_TRUNK:
   1245                     tgid = g_params.param0;
   1246                     break;
   1247                 case  _SHR_GPORT_TYPE_MODPORT:
   1248                     port = g_params.param0;
   1249                     modid = g_params.param1;
   1250                     break;
   1251                 case _SHR_GPORT_TYPE_LOCAL_CPU:
   1252                     port = g_params.param0;
   1253                     BCM_IF_ERROR_RETURN
   1254                         (bcm_esw_stk_my_modid_get(unit, &modid));
   1255                     break;
   1256                 case _SHR_GPORT_TYPE_SUBPORT_GROUP:
   1257                     gport_id = g_params.param0;
   1258                     break;
   1259                 case _SHR_GPORT_TYPE_SUBPORT_PORT:
   1260                     gport_id = g_params.param0;
   1261                     break;
   1262                 case _SHR_GPORT_TYPE_MPLS_PORT:
   1263                     gport_id = g_params.param0;
   1264                     break;
   1265                 case _SHR_GPORT_TYPE_MIM_PORT:
   1266                 case _SHR_GPORT_TYPE_WLAN_PORT:
   1267                 case _SHR_GPORT_TYPE_VLAN_PORT:
   1268                 case _SHR_GPORT_TYPE_NIV_PORT:
   1269                 case _SHR_GPORT_TYPE_TRILL_PORT:
   1270                 case _SHR_GPORT_TYPE_L2GRE_PORT:
   1271                 case _SHR_GPORT_TYPE_VXLAN_PORT:
   1272                 case _SHR_GPORT_TYPE_EXTENDER_PORT:
   1273                     gport_id = g_params.param0;
   1274                     break;
   1275                 default:
   1276                     return BCM_E_PORT;
   1277                 }
   1278             }
   1279         } else if (l2addr->flags & BCM_L2_TRUNK_MEMBER) {
   1280             tgid = l2addr->tgid;
   1281 
   1282         } else {
   1283             PORT_DUALMODID_VALID(unit, l2addr->port);
   1284             BCM_IF_ERROR_RETURN(
   1285                 _bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_SET,
   1286                                        l2addr->modid, l2addr->port,
   1287                                        &modid, &port));
   1288             /* Check parameters */
   1289             if (!SOC_MODID_ADDRESSABLE(unit, modid)) {
   1290                 return BCM_E_BADID;
   1291             }
   1292             if (!SOC_PORT_ADDRESSABLE(unit, port)) {
   1293                 return BCM_E_PORT;
   1294             }
   1295         }
   1296 
   1297         /* Setting l2_entries fields according to parameters */
   1298         if ( BCM_TRUNK_INVALID != tgid) {
   1299             _bcm_tr3_l2hw_entries_field32_set(unit, l2_entries,
   1300                           _BCM_TR3_L2_MEMACC_DEST_TYPE, 0x1);
   1301             _bcm_tr3_l2hw_entries_field32_set(unit, l2_entries,
   1302                           _BCM_TR3_L2_MEMACC_TGID, tgid);
   1303             /*
   1304              * Note:  RTAG is ignored here.  Use bcm_trunk_psc_set to
   1305              * to set for a given trunk.
   1306              */
   1307             if (l2addr->flags & BCM_L2_REMOTE_TRUNK) {
   1308                 _bcm_tr3_l2hw_entries_field32_set(unit, l2_entries,
   1309                               _BCM_TR3_L2_MEMACC_REMOTE, 1);
   1310             }
   1311         } else if (-1 != port) {
   1312             /* DEST_TYPE field was cleared by calling function. */
   1313             _bcm_tr3_l2hw_entries_field32_set(unit, l2_entries,
   1314                           _BCM_TR3_L2_MEMACC_MODULE_ID, modid);
   1315             _bcm_tr3_l2hw_entries_field32_set(unit, l2_entries,
   1316                           _BCM_TR3_L2_MEMACC_PORT_NUM, port);
   1317         } else if (-1 != gport_id) {
   1318             _bcm_tr3_l2hw_entries_field32_set(unit, l2_entries,
   1319                           _BCM_TR3_L2_MEMACC_DEST_TYPE, 0x2);
   1320             _bcm_tr3_l2hw_entries_field32_set(unit, l2_entries,
   1321                            _BCM_TR3_L2_MEMACC_DESTINATION,
   1322                                               gport_id);
   1323         }
   1324     }
   1325 
   1326     field_type = _BCM_TR3_L2_MEMACC_CLASS_ID_FULL;
   1327     if (l2addr->flags & BCM_L2_SETPRI) {
   1328         _bcm_tr3_l2hw_entries_field32_set(unit, l2_entries,
   1329                                           _BCM_TR3_L2_MEMACC_RPE, 1);
   1330         if ((SOC_CONTROL(unit)->l2x_group_enable) &&
   1331             (l2addr->group != (l2addr->group &
   1332                                _BCM_TR3_L2_CLASS_ID_REDUCED_MASK))) {
   1333             /* The priority field is an overlay on the high bits of the
   1334              * class id, so we can't use the full size if RPE is set
   1335              * on the reduced entry size.  Must be extended entry now.
   1336              */
   1337             l2_entries->entry_flags &= _BCM_TR3_L2_SELECT_EXTENDED;
   1338         } else {
   1339             field_type = _BCM_TR3_L2_MEMACC_CLASS_ID;
   1340         }
   1341     }
   1342 
   1343     if (SOC_CONTROL(unit)->l2x_group_enable) {
   1344         _bcm_tr3_l2hw_entries_field32_set(unit, l2_entries,
   1345                                           field_type, l2addr->group);
   1346     } /* else MAC_BLOCK_INDEXf is handled in the add/remove functions below */
   1347 
   1348     if (l2addr->flags & BCM_L2_SETPRI) {
   1349         _bcm_tr3_l2hw_entries_field32_set(unit, l2_entries,
   1350                   _BCM_TR3_L2_MEMACC_PRI, l2addr->cos_dst);
   1351     }
   1352 
   1353     if (l2addr->flags & BCM_L2_COPY_TO_CPU) {
   1354         /* CPU bit is only in the extended entry format. */
   1355         l2_entries->entry_flags &= _BCM_TR3_L2_SELECT_EXTENDED;
   1356         _bcm_tr3_l2hw_entries_field32_set(unit, l2_entries,
   1357                       _BCM_TR3_L2_MEMACC_DST_CPU, 1);
   1358     }
   1359 
   1360     if (l2addr->flags & BCM_L2_DISCARD_DST) {
   1361         /* Destination discard bit is only in the extended entry format. */
   1362         l2_entries->entry_flags &= _BCM_TR3_L2_SELECT_EXTENDED;
   1363         _bcm_tr3_l2hw_entries_field32_set(unit, l2_entries,
   1364                       _BCM_TR3_L2_MEMACC_DST_DISCARD, 1);
   1365     }
   1366 
   1367     if (l2addr->flags & BCM_L2_DISCARD_SRC) {
   1368         /* Source discard bit is only in the extended entry format. */
   1369         l2_entries->entry_flags &= _BCM_TR3_L2_SELECT_EXTENDED;
   1370         _bcm_tr3_l2hw_entries_field32_set(unit, l2_entries,
   1371                       _BCM_TR3_L2_MEMACC_SRC_DISCARD, 1);
   1372     }
   1373 
   1374     if (l2addr->flags & BCM_L2_COS_SRC_PRI) {
   1375         _bcm_tr3_l2hw_entries_field32_set(unit, l2_entries,
   1376                       _BCM_TR3_L2_MEMACC_SCP, 1);
   1377     }
   1378 
   1379     if ((!(l2addr->flags & (BCM_L2_L3LOOKUP | BCM_L2_MCAST |
   1380                             BCM_L2_STATIC | BCM_L2_LEARN_LIMIT_EXEMPT))) || 
   1381         l2addr->flags & BCM_L2_LEARN_LIMIT) {
   1382         _bcm_tr3_l2hw_entries_field32_set(unit, l2_entries,
   1383                       _BCM_TR3_L2_MEMACC_LIMIT_COUNTED, 1);
   1384     }
   1385 
   1386     if (l2addr->flags & BCM_L2_PENDING) {
   1387         _bcm_tr3_l2hw_entries_field32_set(unit, l2_entries,
   1388                       _BCM_TR3_L2_MEMACC_PENDING, 1);
   1389     }
   1390 
   1391     /* If BCM_L2_DES_HIT is set, HITDA has to be set. But if only BCM_L2_HIT
   1392        is set, HITDA has to be set based on aging scheme */
   1393     if ((l2addr->flags & BCM_L2_DES_HIT) ||
   1394         (l2addr->flags & BCM_L2_HIT)) {
   1395         if ((!SOC_CONTROL(unit)->l2x_age_hitsa_only) ||
   1396             (l2addr->flags & BCM_L2_DES_HIT)) {
   1397             _bcm_tr3_l2hw_entries_field32_set(unit, l2_entries,
   1398                                               _BCM_TR3_L2_MEMACC_HITDA, 1);
   1399         }
   1400     }
   1401 
   1402     if ((l2addr->flags & BCM_L2_SRC_HIT) ||
   1403         (l2addr->flags & BCM_L2_HIT)) {
   1404         _bcm_tr3_l2hw_entries_field32_set(unit, l2_entries,
   1405                                           _BCM_TR3_L2_MEMACC_HITSA, 1);
   1406     }
   1407 
   1408     if (l2addr->flags & BCM_L2_LEARN_LIMIT_EXEMPT_LOCAL) {
   1409        _bcm_tr3_l2hw_entries_field32_set(unit, l2_entries,
   1410                                           _BCM_TR3_L2_MEMACC_REMOTE, 1);
   1411        _bcm_tr3_l2hw_entries_field32_set(unit, l2_entries,
   1412                                          _BCM_TR3_L2_MEMACC_LIMIT_COUNTED, 1);
   1413     }
   1414 
   1415     
   1416 
   1417     if (l2addr->flags & BCM_L2_STATIC) {
   1418         _bcm_tr3_l2hw_entries_field32_set(unit, l2_entries,
   1419                                           _BCM_TR3_L2_MEMACC_STATIC_BIT, 1);
   1420         if (l2_entries->entry_flags & _BCM_TR3_L2_SELECT_L2_ENTRY_2) {
   1421             memacc = _BCM_TR3_L2_MEMACC(unit, L2_ENTRY_2,
   1422                                         _BCM_TR3_L2_MEMACC_STATIC_BIT_1);
   1423             soc_memacc_field32_set(memacc, &(l2_entries->l2_entry_2), 1);
   1424         }
   1425     }
   1426 
   1427     if (l2_entries->entry_flags & _BCM_TR3_L2_SELECT_L2_ENTRY_1) {
   1428         memacc = _BCM_TR3_L2_MEMACC(unit, L2_ENTRY_1,
   1429                                     _BCM_TR3_L2_MEMACC_VALID);
   1430         soc_memacc_field32_set(memacc, &(l2_entries->l2_entry_1), 1);
   1431     }
   1432     if (l2_entries->entry_flags & _BCM_TR3_L2_SELECT_L2_ENTRY_2) {
   1433         memacc = _BCM_TR3_L2_MEMACC(unit, L2_ENTRY_2,
   1434                                     _BCM_TR3_L2_MEMACC_VALID);
   1435         soc_memacc_field32_set(memacc, &(l2_entries->l2_entry_2), 1);
   1436         memacc = _BCM_TR3_L2_MEMACC(unit, L2_ENTRY_2,
   1437                                     _BCM_TR3_L2_MEMACC_VALID_1);
   1438         soc_memacc_field32_set(memacc, &(l2_entries->l2_entry_2), 1);
   1439 
   1440         memacc = _BCM_TR3_L2_MEMACC(unit, L2_ENTRY_2,
   1441                                     _BCM_TR3_L2_MEMACC_WIDE);
   1442         soc_memacc_field32_set(memacc, &(l2_entries->l2_entry_2), 1);
   1443         memacc = _BCM_TR3_L2_MEMACC(unit, L2_ENTRY_2,
   1444                                     _BCM_TR3_L2_MEMACC_WIDE_1);
   1445         soc_memacc_field32_set(memacc, &(l2_entries->l2_entry_2), 1);
   1446     }
   1447 
   1448     /* EXT L2 tables use FREE field instead of VALID */
   1449     if (l2_entries->entry_flags & _BCM_TR3_L2_SELECT_EXT_L2_ENTRY_1) {
   1450         memacc = _BCM_TR3_L2_MEMACC(unit, EXT_L2_ENTRY_1,
   1451                                     _BCM_TR3_L2_MEMACC_FREE);
   1452         soc_memacc_field32_set(memacc, &(l2_entries->ext_l2_entry_1), 0);
   1453     }
   1454     if (l2_entries->entry_flags & _BCM_TR3_L2_SELECT_EXT_L2_ENTRY_2) {
   1455         memacc = _BCM_TR3_L2_MEMACC(unit, EXT_L2_ENTRY_2,
   1456                                     _BCM_TR3_L2_MEMACC_FREE);
   1457         soc_memacc_field32_set(memacc, &(l2_entries->ext_l2_entry_2), 0);
   1458     }
   1459 
   1460     if (0 == l2_entries->entry_flags) {
   1461         /* We couldn't find a memory which can satisfy the requested
   1462          * L2 addr specification.
   1463          */
   1464         return BCM_E_PARAM;
   1465     }
   1466 
   1467     return BCM_E_NONE;
   1468 }
   1469 
   1470 /*
   1471  * Function:
   1472  *      _bcm_tr3_l2_from_l2_1
   1473  * Purpose:
   1474  *      Convert an L2_ENTRY_1 to an L2 API data structure
   1475 
   1476  * Parameters:
   1477  *      unit         Unit number
   1478  *      l2addr       (OUT) L2 API data structure
   1479  *      L2_entry_1 L2_ENTRY_1 hardware entry
   1480  */
   1481 int
   1482 _bcm_tr3_l2_from_l2_1(int unit, bcm_l2_addr_t *l2addr,
   1483                       l2_entry_1_entry_t *l2_entry_1)
   1484 {
   1485     _bcm_gport_dest_t       dest;
   1486     int                     mb_index;
   1487     bcm_module_t            mod;
   1488     bcm_port_t              port;
   1489     soc_memacc_t            *memacc;
   1490     int                     isGport = 0;
   1491 #if defined(INCLUDE_L3)
   1492     int vfi;
   1493 #endif
   1494     sal_memset(l2addr, 0, sizeof(*l2addr));
   1495 
   1496     if (_BCM_TR3_L2_1_FIELD32_MEMACC_GET(unit, l2_entry_1, KEY_TYPE) ==
   1497         SOC_MEM_KEY_L2_ENTRY_1_L2_VFI) {
   1498 #if defined(INCLUDE_L3)
   1499          vfi = _BCM_TR3_L2_1_FIELD32_MEMACC_GET(unit, l2_entry_1, VFI);
   1500          /* VPLS or MIM VPN */
   1501          if (_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeMpls)) {
   1502               _BCM_MPLS_VPN_SET(l2addr->vid, _BCM_MPLS_VPN_TYPE_VPLS, vfi);
   1503          } else  if (_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeMim)) {
   1504               _BCM_MIM_VPN_SET(l2addr->vid, _BCM_MIM_VPN_TYPE_MIM, vfi);
   1505          } else  if (_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeL2Gre)) {
   1506               BCM_IF_ERROR_RETURN(
   1507                    _bcm_tr3_l2gre_vpn_get(unit, vfi, &l2addr->vid));
   1508          }
   1509 #endif
   1510     } else {
   1511          l2addr->vid =
   1512              _BCM_TR3_L2_1_FIELD32_MEMACC_GET(unit, l2_entry_1, VLAN_ID);
   1513     }
   1514 
   1515     memacc = _BCM_TR3_L2_MEMACC(unit, L2_ENTRY_1,
   1516                                 _BCM_TR3_L2_MEMACC_MAC_ADDR);
   1517     soc_memacc_mac_addr_get(memacc, l2_entry_1, l2addr->mac);
   1518 
   1519     _bcm_gport_dest_t_init(&dest);
   1520 #if defined(INCLUDE_L3)
   1521     if (_BCM_TR3_L2_1_FIELD32_MEMACC_GET(unit, l2_entry_1,
   1522                                          DEST_TYPE) == 0x2) {
   1523          int vp;
   1524 
   1525          vp = _BCM_TR3_L2_1_FIELD32_MEMACC_GET(unit, l2_entry_1,
   1526                                                DESTINATION);
   1527          if (_BCM_TR3_L2_1_FIELD32_MEMACC_GET(unit, l2_entry_1,
   1528                                               KEY_TYPE) ==
   1529              SOC_MEM_KEY_L2_ENTRY_1_L2_VFI) {
   1530               /* MPLS/MiM virtual port unicast */
   1531               if (_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) {
   1532                    dest.mpls_id = vp;
   1533                    dest.gport_type = _SHR_GPORT_TYPE_MPLS_PORT;
   1534                    isGport=1;
   1535               } else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeMim)) {
   1536                    dest.mim_id = vp;
   1537                    dest.gport_type = _SHR_GPORT_TYPE_MIM_PORT;
   1538                    isGport=1;
   1539               } else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeL2Gre)) {
   1540                    dest.l2gre_id= vp;
   1541                    dest.gport_type = _SHR_GPORT_TYPE_L2GRE_PORT;
   1542                    isGport=1;
   1543               } else {
   1544                     /* L2 entries with Stale VPN */
   1545                     dest.gport_type = BCM_GPORT_INVALID;
   1546                     isGport=0;
   1547               }
   1548          } else {
   1549               /* Subport/WLAN unicast */
   1550               if (_bcm_vp_used_get(unit, vp, _bcmVpTypeSubport)) {
   1551                    dest.subport_id = vp;
   1552                    dest.gport_type = _SHR_GPORT_TYPE_SUBPORT_GROUP;
   1553                    isGport=1;
   1554               } else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeWlan)) {
   1555                    dest.wlan_id = vp;
   1556                    dest.gport_type = _SHR_GPORT_TYPE_WLAN_PORT;
   1557                    isGport=1;
   1558               } else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeVlan)) {
   1559                    dest.vlan_vp_id = vp;
   1560                    dest.gport_type = _SHR_GPORT_TYPE_VLAN_PORT;
   1561                    isGport=1;
   1562               } else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeTrill)) {
   1563                     dest.trill_id  = vp;
   1564                     dest.gport_type = _SHR_GPORT_TYPE_TRILL_PORT;
   1565                     isGport=1;
   1566               } else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeNiv)) {
   1567                     dest.niv_id = vp;
   1568                     dest.gport_type = _SHR_GPORT_TYPE_NIV_PORT;
   1569                     isGport=1;
   1570               } else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeExtender)) {
   1571                     dest.extender_id = vp;
   1572                     dest.gport_type = _SHR_GPORT_TYPE_EXTENDER_PORT;
   1573                     isGport=1;
   1574               } else {
   1575                     /* L2 entries with Stale Gport */
   1576                     dest.gport_type = BCM_GPORT_INVALID;
   1577                     isGport=0;
   1578               }
   1579          }
   1580     } else {
   1581 #endif /* INCLUDE_L3 */
   1582         BCM_IF_ERROR_RETURN
   1583             (bcm_esw_switch_control_get(unit, bcmSwitchUseGport, &isGport));
   1584         if (_BCM_TR3_L2_1_FIELD32_MEMACC_GET(unit, l2_entry_1,
   1585                                          DEST_TYPE) == 0x1) {
   1586             int psc = 0;
   1587             l2addr->tgid =
   1588                 _BCM_TR3_L2_1_FIELD32_MEMACC_GET(unit, l2_entry_1, TGID);
   1589             bcm_esw_trunk_psc_get(unit, l2addr->tgid, &psc);
   1590             dest.tgid = l2addr->tgid;
   1591             dest.gport_type = _SHR_GPORT_TYPE_TRUNK;
   1592 
   1593             l2addr->flags |= BCM_L2_TRUNK_MEMBER;
   1594             if (_BCM_TR3_L2_1_FIELD32_MEMACC_GET(unit, l2_entry_1,
   1595                                                  REMOTE)) {
   1596                 l2addr->flags |= BCM_L2_REMOTE_TRUNK;
   1597             }
   1598         } else {
   1599             if (BCM_MAC_IS_MCAST(l2addr->mac)) {
   1600                 l2addr->flags |= BCM_L2_MCAST;
   1601                 l2addr->l2mc_group =
   1602                     _BCM_TR3_L2_1_FIELD32_MEMACC_GET(unit, l2_entry_1,
   1603                                                      L2MC_PTR);
   1604                 if (_BCM_TR3_L2_2_FIELD32_MEMACC_GET(unit, l2_entry_1, KEY_TYPE) ==
   1605                     SOC_MEM_KEY_L2_ENTRY_1_L2_VFI) {
   1606 #if defined(INCLUDE_L3)
   1607                     vfi = _BCM_TR3_L2_1_FIELD32_MEMACC_GET(unit, l2_entry_1, VFI);
   1608                     if (_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeMpls)) {
   1609                          _BCM_MULTICAST_GROUP_SET(l2addr->l2mc_group,
   1610                                 _BCM_MULTICAST_TYPE_VPLS, l2addr->l2mc_group);
   1611                     } else
   1612 #endif /* INCLUDE_L3 */
   1613                     {
   1614                          _BCM_MULTICAST_GROUP_SET(l2addr->l2mc_group,
   1615                                 _BCM_MULTICAST_TYPE_MIM, l2addr->l2mc_group);
   1616                     }
   1617                 }
   1618                 isGport = 0;
   1619             } else {
   1620                 mod = _BCM_TR3_L2_1_FIELD32_MEMACC_GET(unit, l2_entry_1,
   1621                                                        MODULE_ID);
   1622                 port = _BCM_TR3_L2_1_FIELD32_MEMACC_GET(unit, l2_entry_1,
   1623                                                         PORT_NUM);
   1624                 BCM_IF_ERROR_RETURN
   1625                     (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET,
   1626                                              mod, port, &mod, &port));
   1627                 l2addr->modid = mod;
   1628                 l2addr->port = port;
   1629                 dest.port = l2addr->port;
   1630                 dest.modid = l2addr->modid;
   1631                 dest.gport_type = _SHR_GPORT_TYPE_MODPORT;
   1632             }
   1633         }
   1634 #if defined(INCLUDE_L3)
   1635     }
   1636 #endif /* INCLUDE_L3 */
   1637 
   1638     if (isGport) {
   1639          BCM_IF_ERROR_RETURN
   1640              (_bcm_esw_gport_construct(unit, &dest, &l2addr->port));
   1641     }
   1642 
   1643     if (_BCM_TR3_L2_1_FIELD32_MEMACC_GET(unit, l2_entry_1, RPE)) {
   1644         l2addr->flags |= BCM_L2_SETPRI;
   1645         l2addr->cos_dst =
   1646             _BCM_TR3_L2_1_FIELD32_MEMACC_GET(unit, l2_entry_1, PRI);
   1647     }
   1648     l2addr->cos_src = l2addr->cos_dst;
   1649 
   1650     if (SOC_CONTROL(unit)->l2x_group_enable) {
   1651         if (l2addr->flags & BCM_L2_SETPRI) {
   1652             l2addr->group =
   1653                 _BCM_TR3_L2_1_FIELD32_MEMACC_GET(unit, l2_entry_1,
   1654                                                  CLASS_ID);
   1655         } else {
   1656             /* Use extended field name when available for non-RPE case. */
   1657             l2addr->group = 
   1658                 _BCM_TR3_L2_1_FIELD32_MEMACC_GET(unit, l2_entry_1,
   1659                                                  CLASS_ID_FULL);
   1660         }
   1661     } else {
   1662         mb_index =
   1663             _BCM_TR3_L2_1_FIELD32_MEMACC_GET(unit, l2_entry_1,
   1664                                              MAC_BLOCK_INDEX);
   1665         if (mb_index) {
   1666             BCM_PBMP_ASSIGN(l2addr->block_bitmap,
   1667                             _tr3_mbi_entries[unit][mb_index].mb_pbmp);
   1668         }
   1669     }
   1670 
   1671     if (_BCM_TR3_L2_1_FIELD32_MEMACC_GET(unit, l2_entry_1, SCP)) {
   1672         l2addr->flags |= BCM_L2_COS_SRC_PRI;
   1673     }
   1674 
   1675     if (_BCM_TR3_L2_1_FIELD32_MEMACC_GET(unit, l2_entry_1, PENDING)) {
   1676         l2addr->flags |= BCM_L2_PENDING;
   1677     }
   1678 
   1679     if (_BCM_TR3_L2_1_FIELD32_MEMACC_GET(unit, l2_entry_1, STATIC_BIT)) {
   1680         l2addr->flags |= BCM_L2_STATIC;
   1681     }
   1682 
   1683     if (_BCM_TR3_L2_1_FIELD32_MEMACC_GET(unit, l2_entry_1, HITDA)) {
   1684         l2addr->flags |= BCM_L2_DES_HIT;
   1685         if (!SOC_CONTROL(unit)->l2x_age_hitsa_only) {
   1686             l2addr->flags |= BCM_L2_HIT;
   1687         }
   1688     }
   1689 
   1690     if (_BCM_TR3_L2_1_FIELD32_MEMACC_GET(unit, l2_entry_1, HITSA)) {
   1691         l2addr->flags |= BCM_L2_SRC_HIT;
   1692         l2addr->flags |= BCM_L2_HIT;
   1693     }
   1694 
   1695     if (_BCM_TR3_L2_1_FIELD32_MEMACC_GET(unit, l2_entry_1, LOCAL_SA)) {
   1696         l2addr->flags |= BCM_L2_NATIVE;
   1697     }
   1698 
   1699     if ((!(l2addr->flags & BCM_L2_STATIC)) || 
   1700         l2addr->flags & BCM_L2_LEARN_LIMIT ) {
   1701         if (!_BCM_TR3_L2_1_FIELD32_MEMACC_GET(unit, l2_entry_1,
   1702                                               LIMIT_COUNTED)) {
   1703             l2addr->flags |= BCM_L2_LEARN_LIMIT_EXEMPT;
   1704         }
   1705     }
   1706 
   1707     if (_BCM_TR3_L2_1_FIELD32_MEMACC_GET(unit, l2_entry_1, REMOTE)) {
   1708        l2addr->flags |= BCM_L2_LEARN_LIMIT_EXEMPT_LOCAL;
   1709     }
   1710 
   1711     return BCM_E_NONE;
   1712 }
   1713 
   1714 /*
   1715  * Function:
   1716  *      _bcm_tr3_l2_from_l2_2
   1717  * Purpose:
   1718  *      Convert an L2_ENTRY_2 to an L2 API data structure
   1719 
   1720  * Parameters:
   1721  *      unit         Unit number
   1722  *      l2addr       (OUT) L2 API data structure
   1723  *      l2_entry_2   L2_ENTRY_2 hardware entry
   1724  */
   1725 int
   1726 _bcm_tr3_l2_from_l2_2(int unit, bcm_l2_addr_t *l2addr,
   1727                       l2_entry_2_entry_t *l2_entry_2)
   1728 {
   1729     _bcm_gport_dest_t       dest;
   1730     int                     mb_index;
   1731     bcm_module_t            mod;
   1732     bcm_port_t              port;
   1733     soc_memacc_t            *memacc;
   1734     int  isGport = 0;
   1735 #if defined(INCLUDE_L3)
   1736     int vfi;
   1737 #endif 
   1738     sal_memset(l2addr, 0, sizeof(*l2addr));
   1739 
   1740     if (_BCM_TR3_L2_2_FIELD32_MEMACC_GET(unit, l2_entry_2, KEY_TYPE) ==
   1741         SOC_MEM_KEY_L2_ENTRY_2_L2_VFI) {
   1742 #if defined(INCLUDE_L3)
   1743          vfi = _BCM_TR3_L2_2_FIELD32_MEMACC_GET(unit, l2_entry_2, VFI);
   1744          /* VPLS or MIM VPN */
   1745          if (_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeMpls)) {
   1746               _BCM_MPLS_VPN_SET(l2addr->vid, _BCM_MPLS_VPN_TYPE_VPLS, vfi);
   1747          } else  if (_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeMim)) {
   1748               _BCM_MIM_VPN_SET(l2addr->vid, _BCM_MIM_VPN_TYPE_MIM, vfi);
   1749          } else  if (_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeL2Gre)) {
   1750               BCM_IF_ERROR_RETURN(
   1751                    _bcm_tr3_l2gre_vpn_get(unit, vfi, &l2addr->vid));
   1752          }
   1753 
   1754 #endif
   1755     } else {
   1756          l2addr->vid =
   1757              _BCM_TR3_L2_2_FIELD32_MEMACC_GET(unit, l2_entry_2, VLAN_ID);
   1758     }
   1759 
   1760     memacc = _BCM_TR3_L2_MEMACC(unit, L2_ENTRY_2,
   1761                                 _BCM_TR3_L2_MEMACC_MAC_ADDR);
   1762     soc_memacc_mac_addr_get(memacc, l2_entry_2, l2addr->mac);
   1763 
   1764     _bcm_gport_dest_t_init(&dest);
   1765 #if defined(INCLUDE_L3)
   1766     if (_BCM_TR3_L2_2_FIELD32_MEMACC_GET(unit, l2_entry_2,
   1767                                          DEST_TYPE) == 0x2) {
   1768          int vp;
   1769 
   1770          vp = _BCM_TR3_L2_2_FIELD32_MEMACC_GET(unit, l2_entry_2,
   1771                                                DESTINATION);
   1772          if (_BCM_TR3_L2_2_FIELD32_MEMACC_GET(unit, l2_entry_2,
   1773                                               KEY_TYPE) ==
   1774              SOC_MEM_KEY_L2_ENTRY_2_L2_VFI) {
   1775               /* MPLS/MiM virtual port unicast */
   1776               if (_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) {
   1777                    dest.mpls_id = vp;
   1778                    dest.gport_type = _SHR_GPORT_TYPE_MPLS_PORT;
   1779                    isGport=1;
   1780               } else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeMim)) {
   1781                    dest.mim_id = vp;
   1782                    dest.gport_type = _SHR_GPORT_TYPE_MIM_PORT;
   1783                    isGport=1;
   1784               } else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeL2Gre)) {
   1785                    dest.mim_id = vp;
   1786                    dest.gport_type = _SHR_GPORT_TYPE_L2GRE_PORT;
   1787                    isGport=1;
   1788               } else {
   1789                     /* L2 entries with Stale VPN */
   1790                     dest.gport_type = BCM_GPORT_INVALID;
   1791                     isGport=0;
   1792               }
   1793          } else {
   1794               /* Subport/WLAN unicast */
   1795               if (_bcm_vp_used_get(unit, vp, _bcmVpTypeSubport)) {
   1796                    dest.subport_id = vp;
   1797                    dest.gport_type = _SHR_GPORT_TYPE_SUBPORT_GROUP;
   1798                    isGport=1;
   1799               } else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeWlan)) {
   1800                    dest.wlan_id = vp;
   1801                    dest.gport_type = _SHR_GPORT_TYPE_WLAN_PORT;
   1802                    isGport=1;
   1803               } else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeVlan)) {
   1804                    dest.vlan_vp_id = vp;
   1805                    dest.gport_type = _SHR_GPORT_TYPE_VLAN_PORT;
   1806                    isGport=1;
   1807               } else {
   1808                     /* L2 entries with Stale Gport */
   1809                     dest.gport_type = BCM_GPORT_INVALID;
   1810                     isGport=0;
   1811               }
   1812          }
   1813     } else {
   1814 #endif /* INCLUDE_L3 */
   1815         BCM_IF_ERROR_RETURN
   1816             (bcm_esw_switch_control_get(unit, bcmSwitchUseGport, &isGport));
   1817         if (_BCM_TR3_L2_2_FIELD32_MEMACC_GET(unit, l2_entry_2,
   1818                                          DEST_TYPE) == 0x1) {
   1819             int psc = 0;
   1820             l2addr->tgid =
   1821                 _BCM_TR3_L2_2_FIELD32_MEMACC_GET(unit, l2_entry_2, TGID);
   1822             bcm_esw_trunk_psc_get(unit, l2addr->tgid, &psc);
   1823             dest.tgid = l2addr->tgid;
   1824             dest.gport_type = _SHR_GPORT_TYPE_TRUNK;
   1825 
   1826             l2addr->flags |= BCM_L2_TRUNK_MEMBER;
   1827             if (_BCM_TR3_L2_2_FIELD32_MEMACC_GET(unit, l2_entry_2,
   1828                                                  REMOTE)) {
   1829                 l2addr->flags |= BCM_L2_REMOTE_TRUNK;
   1830             }
   1831         } else {
   1832             if (BCM_MAC_IS_MCAST(l2addr->mac)) {
   1833                 l2addr->flags |= BCM_L2_MCAST;
   1834                 l2addr->l2mc_group =
   1835                     _BCM_TR3_L2_2_FIELD32_MEMACC_GET(unit, l2_entry_2,
   1836                                                      L2MC_PTR);
   1837                 if (_BCM_TR3_L2_2_FIELD32_MEMACC_GET(unit, l2_entry_2, KEY_TYPE) ==
   1838                     SOC_MEM_KEY_L2_ENTRY_2_L2_VFI) {
   1839 #if defined(INCLUDE_L3)
   1840                     vfi = _BCM_TR3_L2_1_FIELD32_MEMACC_GET(unit, l2_entry_2, VFI);
   1841                     if (_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeMpls)) {
   1842                          _BCM_MULTICAST_GROUP_SET(l2addr->l2mc_group,
   1843                                 _BCM_MULTICAST_TYPE_VPLS, l2addr->l2mc_group);
   1844                     } else
   1845 #endif /* INCLUDE_L3 */
   1846                     {
   1847                          _BCM_MULTICAST_GROUP_SET(l2addr->l2mc_group,
   1848                                 _BCM_MULTICAST_TYPE_MIM, l2addr->l2mc_group);
   1849                     }
   1850                 }    
   1851                 isGport = 0;
   1852             } else {
   1853                 mod = _BCM_TR3_L2_2_FIELD32_MEMACC_GET(unit, l2_entry_2,
   1854                                                        MODULE_ID);
   1855                 port = _BCM_TR3_L2_2_FIELD32_MEMACC_GET(unit, l2_entry_2,
   1856                                                         PORT_NUM);
   1857                 BCM_IF_ERROR_RETURN
   1858                     (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET,
   1859                                              mod, port, &mod, &port));
   1860                 l2addr->modid = mod;
   1861                 l2addr->port = port;
   1862                 dest.port = l2addr->port;
   1863                 dest.modid = l2addr->modid;
   1864                 dest.gport_type = _SHR_GPORT_TYPE_MODPORT;
   1865             }
   1866         }
   1867 #if defined(INCLUDE_L3)
   1868     }
   1869 #endif /* INCLUDE_L3 */
   1870 
   1871     if (isGport) {
   1872          BCM_IF_ERROR_RETURN
   1873              (_bcm_esw_gport_construct(unit, &dest, &l2addr->port));
   1874     }
   1875 
   1876     if (_BCM_TR3_L2_2_FIELD32_MEMACC_GET(unit, l2_entry_2, RPE)) {
   1877         l2addr->flags |= BCM_L2_SETPRI;
   1878         l2addr->cos_dst =
   1879             _BCM_TR3_L2_2_FIELD32_MEMACC_GET(unit, l2_entry_2, PRI);
   1880     }
   1881     l2addr->cos_src = l2addr->cos_dst;
   1882 
   1883     if (SOC_CONTROL(unit)->l2x_group_enable) {
   1884         l2addr->group = 
   1885             _BCM_TR3_L2_2_FIELD32_MEMACC_GET(unit, l2_entry_2,
   1886                                              CLASS_ID_FULL);
   1887     } else {
   1888         mb_index =
   1889             _BCM_TR3_L2_2_FIELD32_MEMACC_GET(unit, l2_entry_2,
   1890                                              MAC_BLOCK_INDEX);
   1891         if (mb_index) {
   1892             BCM_PBMP_ASSIGN(l2addr->block_bitmap,
   1893                             _tr3_mbi_entries[unit][mb_index].mb_pbmp);
   1894         }
   1895     }
   1896 
   1897     if (_BCM_TR3_L2_2_FIELD32_MEMACC_GET(unit, l2_entry_2, DST_CPU)) {
   1898         l2addr->flags |= BCM_L2_COPY_TO_CPU;
   1899     }
   1900 
   1901     if (_BCM_TR3_L2_2_FIELD32_MEMACC_GET(unit, l2_entry_2, DST_DISCARD)) {
   1902         l2addr->flags |= BCM_L2_DISCARD_DST;
   1903     }
   1904 
   1905     if (_BCM_TR3_L2_2_FIELD32_MEMACC_GET(unit, l2_entry_2, SRC_DISCARD)) {
   1906         l2addr->flags |= BCM_L2_DISCARD_SRC;
   1907     }
   1908 
   1909     if (_BCM_TR3_L2_2_FIELD32_MEMACC_GET(unit, l2_entry_2, SCP)) {
   1910         l2addr->flags |= BCM_L2_COS_SRC_PRI;
   1911     }
   1912 
   1913     if (_BCM_TR3_L2_2_FIELD32_MEMACC_GET(unit, l2_entry_2, PENDING)) {
   1914         l2addr->flags |= BCM_L2_PENDING;
   1915     }
   1916 
   1917     if (_BCM_TR3_L2_2_FIELD32_MEMACC_GET(unit, l2_entry_2, STATIC_BIT)) {
   1918         l2addr->flags |= BCM_L2_STATIC;
   1919     }
   1920 
   1921     if (_BCM_TR3_L2_2_FIELD32_MEMACC_GET(unit, l2_entry_2, HITDA)) {
   1922         l2addr->flags |= BCM_L2_DES_HIT;
   1923         if (!SOC_CONTROL(unit)->l2x_age_hitsa_only) {
   1924             l2addr->flags |= BCM_L2_HIT;
   1925         }
   1926     }
   1927 
   1928     if (_BCM_TR3_L2_2_FIELD32_MEMACC_GET(unit, l2_entry_2, HITSA)) {
   1929         l2addr->flags |= BCM_L2_SRC_HIT;
   1930         l2addr->flags |= BCM_L2_HIT;
   1931     }
   1932     
   1933     if (_BCM_TR3_L2_2_FIELD32_MEMACC_GET(unit, l2_entry_2, LOCAL_SA)) {
   1934         l2addr->flags |= BCM_L2_NATIVE;
   1935     }
   1936 
   1937     if ((!(l2addr->flags & BCM_L2_STATIC)) || 
   1938         l2addr->flags & BCM_L2_LEARN_LIMIT ) {
   1939         if (!_BCM_TR3_L2_2_FIELD32_MEMACC_GET(unit, l2_entry_2,
   1940                                               LIMIT_COUNTED)) {
   1941             l2addr->flags |= BCM_L2_LEARN_LIMIT_EXEMPT;
   1942         }
   1943     }
   1944 
   1945     if (_BCM_TR3_L2_2_FIELD32_MEMACC_GET(unit, l2_entry_2, REMOTE)) {
   1946         l2addr->flags |= BCM_L2_LEARN_LIMIT_EXEMPT_LOCAL;
   1947     }
   1948 
   1949     
   1950 
   1951     return BCM_E_NONE;
   1952 }
   1953 
   1954 /*
   1955  * Function:
   1956  *      _bcm_tr3_l2_from_ext_l2_1
   1957  * Purpose:
   1958  *      Convert an EXT_L2_ENTRY_1 to an L2 API data structure
   1959 
   1960  * Parameters:
   1961  *      unit         Unit number
   1962  *      l2addr       (OUT) L2 API data structure
   1963  *      ext_l2_entry_1 EXT_L2_ENTRY_1 hardware entry
   1964  */
   1965 int
   1966 _bcm_tr3_l2_from_ext_l2_1(int unit, bcm_l2_addr_t *l2addr,
   1967                           ext_l2_entry_1_entry_t *ext_l2_entry_1)
   1968 {
   1969     _bcm_gport_dest_t       dest;
   1970     int                     mb_index;
   1971     bcm_module_t            mod;
   1972     bcm_port_t              port;
   1973     soc_memacc_t            *memacc;
   1974     int  isGport = 0;
   1975 #if defined(INCLUDE_L3)
   1976     int vfi;
   1977 #endif 
   1978     sal_memset(l2addr, 0, sizeof(*l2addr));
   1979 
   1980     if (_BCM_TR3_EXT_L2_1_FIELD32_MEMACC_GET(unit, ext_l2_entry_1,
   1981                                              KEY_TYPE) ==
   1982         SOC_MEM_KEY_EXT_L2_ENTRY_1_L2_VFI) {
   1983 #if defined(INCLUDE_L3)
   1984         vfi = _BCM_TR3_EXT_L2_1_FIELD32_MEMACC_GET(unit, ext_l2_entry_1,
   1985                                                    VFI);
   1986          /* VPLS or MIM VPN */
   1987          if (_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeMpls)) {
   1988               _BCM_MPLS_VPN_SET(l2addr->vid, _BCM_MPLS_VPN_TYPE_VPLS, vfi);
   1989          } else  if (_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeMim)) {
   1990               _BCM_MIM_VPN_SET(l2addr->vid, _BCM_MIM_VPN_TYPE_MIM, vfi);
   1991          } else  if (_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeL2Gre)) {
   1992               BCM_IF_ERROR_RETURN(
   1993                    _bcm_tr3_l2gre_vpn_get(unit, vfi, &l2addr->vid));
   1994          }
   1995 #endif
   1996     } else {
   1997          l2addr->vid =
   1998              _BCM_TR3_EXT_L2_1_FIELD32_MEMACC_GET(unit, ext_l2_entry_1,
   1999                                                   VLAN_ID);
   2000     }
   2001 
   2002     memacc = _BCM_TR3_L2_MEMACC(unit, EXT_L2_ENTRY_1,
   2003                                 _BCM_TR3_L2_MEMACC_MAC_ADDR);
   2004     soc_memacc_mac_addr_get(memacc, ext_l2_entry_1, l2addr->mac);
   2005 
   2006     _bcm_gport_dest_t_init(&dest);
   2007 #if defined(INCLUDE_L3)
   2008     if (_BCM_TR3_EXT_L2_1_FIELD32_MEMACC_GET(unit, ext_l2_entry_1,
   2009                                              DEST_TYPE) == 0x2) {
   2010         int vp;
   2011 
   2012         vp = _BCM_TR3_EXT_L2_1_FIELD32_MEMACC_GET(unit, ext_l2_entry_1,
   2013                                                   DESTINATION);
   2014         if (_BCM_TR3_EXT_L2_1_FIELD32_MEMACC_GET(unit, ext_l2_entry_1,
   2015                                                  KEY_TYPE) ==
   2016             SOC_MEM_KEY_EXT_L2_ENTRY_1_L2_VFI) {
   2017             /* MPLS/MiM virtual port unicast */
   2018             if (_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) {
   2019                 dest.mpls_id = vp;
   2020                 dest.gport_type = _SHR_GPORT_TYPE_MPLS_PORT;
   2021                 isGport=1;
   2022             } else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeMim)) {
   2023                 dest.mim_id = vp;
   2024                 dest.gport_type = _SHR_GPORT_TYPE_MIM_PORT;
   2025                 isGport=1;
   2026             } else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeL2Gre)) {
   2027                 dest.l2gre_id= vp;
   2028                 dest.gport_type = _SHR_GPORT_TYPE_L2GRE_PORT;
   2029                 isGport=1;
   2030             } else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeVxlan)) {
   2031                 dest.vxlan_id= vp;
   2032                 dest.gport_type = _SHR_GPORT_TYPE_VXLAN_PORT;
   2033                 isGport=1;
   2034             } else {
   2035                 /* L2 entries with Stale VPN */
   2036                 dest.gport_type = BCM_GPORT_INVALID;
   2037                 isGport=0;
   2038             }
   2039        } else {
   2040             /* Subport/WLAN unicast */
   2041             if (_bcm_vp_used_get(unit, vp, _bcmVpTypeSubport)) {
   2042                 dest.subport_id = vp;
   2043                 dest.gport_type = _SHR_GPORT_TYPE_SUBPORT_GROUP;
   2044                 isGport=1;
   2045             } else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeWlan)) {
   2046                 dest.wlan_id = vp;
   2047                 dest.gport_type = _SHR_GPORT_TYPE_WLAN_PORT;
   2048                 isGport=1;
   2049             } else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeVlan)) {
   2050                 dest.vlan_vp_id = vp;
   2051                 dest.gport_type = _SHR_GPORT_TYPE_VLAN_PORT;
   2052                 isGport=1;
   2053             } else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeTrill)) {
   2054                 dest.trill_id  = vp;
   2055                 dest.gport_type = _SHR_GPORT_TYPE_TRILL_PORT;
   2056                 isGport=1;
   2057             } else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeNiv)) {
   2058                 dest.niv_id = vp;
   2059                 dest.gport_type = _SHR_GPORT_TYPE_NIV_PORT;
   2060                 isGport=1;
   2061             } else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeExtender)) {
   2062                 dest.extender_id = vp;
   2063                 dest.gport_type = _SHR_GPORT_TYPE_EXTENDER_PORT;
   2064                 isGport=1;
   2065             } else {
   2066                 /* L2 entries with Stale VPN */
   2067                 dest.gport_type = BCM_GPORT_INVALID;
   2068                 isGport=0;
   2069            }
   2070        }
   2071     } else {
   2072 #endif /* INCLUDE_L3 */
   2073         if (_BCM_TR3_EXT_L2_1_FIELD32_MEMACC_GET(unit, ext_l2_entry_1,
   2074                                                  DEST_TYPE) == 0x1) {
   2075             int psc = 0;
   2076             l2addr->tgid =
   2077                 _BCM_TR3_EXT_L2_1_FIELD32_MEMACC_GET(unit, ext_l2_entry_1,
   2078                                                      TGID);
   2079             bcm_esw_trunk_psc_get(unit, l2addr->tgid, &psc);
   2080             dest.tgid = l2addr->tgid;
   2081             dest.gport_type = _SHR_GPORT_TYPE_TRUNK;
   2082 
   2083             l2addr->flags |= BCM_L2_TRUNK_MEMBER;
   2084             if (_BCM_TR3_EXT_L2_1_FIELD32_MEMACC_GET(unit, ext_l2_entry_1,
   2085                                                      REMOTE)) {
   2086                 l2addr->flags |= BCM_L2_REMOTE_TRUNK;
   2087             }
   2088         } else {
   2089             mod = _BCM_TR3_EXT_L2_1_FIELD32_MEMACC_GET(unit, ext_l2_entry_1,
   2090                                       MODULE_ID);
   2091             port = _BCM_TR3_EXT_L2_1_FIELD32_MEMACC_GET(unit, ext_l2_entry_1,
   2092                                        PORT_NUM);
   2093             BCM_IF_ERROR_RETURN
   2094                 (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET,
   2095                                          mod, port, &mod, &port));
   2096             l2addr->modid = mod;
   2097             l2addr->port = port;
   2098             dest.port = l2addr->port;
   2099             dest.modid = l2addr->modid;
   2100             dest.gport_type = _SHR_GPORT_TYPE_MODPORT;
   2101         }
   2102         BCM_IF_ERROR_RETURN
   2103             (bcm_esw_switch_control_get(unit, bcmSwitchUseGport, &isGport));
   2104 #if defined(INCLUDE_L3)
   2105     }
   2106 #endif /* INCLUDE_L3 */
   2107 
   2108     if (isGport) {
   2109          BCM_IF_ERROR_RETURN
   2110              (_bcm_esw_gport_construct(unit, &dest, &l2addr->port));
   2111     }
   2112 
   2113     if (_BCM_TR3_EXT_L2_1_FIELD32_MEMACC_GET(unit, ext_l2_entry_1, RPE)) {
   2114         l2addr->flags |= BCM_L2_SETPRI;
   2115         l2addr->cos_dst =
   2116             _BCM_TR3_EXT_L2_1_FIELD32_MEMACC_GET(unit, ext_l2_entry_1, 
   2117                                                  PRI);
   2118     }
   2119     l2addr->cos_src = l2addr->cos_dst;
   2120 
   2121     if (SOC_CONTROL(unit)->l2x_group_enable) {
   2122         if (l2addr->flags & BCM_L2_SETPRI) {
   2123             l2addr->group =
   2124                 _BCM_TR3_EXT_L2_1_FIELD32_MEMACC_GET(unit, ext_l2_entry_1,
   2125                                                      CLASS_ID);
   2126         } else {
   2127             l2addr->group =
   2128                 _BCM_TR3_EXT_L2_1_FIELD32_MEMACC_GET(unit, ext_l2_entry_1,
   2129                                                      CLASS_ID_FULL);
   2130         }
   2131     } else {
   2132         mb_index =
   2133             _BCM_TR3_EXT_L2_1_FIELD32_MEMACC_GET(unit, ext_l2_entry_1,
   2134                                                  MAC_BLOCK_INDEX);
   2135         if (mb_index) {
   2136             BCM_PBMP_ASSIGN(l2addr->block_bitmap,
   2137                             _tr3_mbi_entries[unit][mb_index].mb_pbmp);
   2138         }
   2139     }
   2140 
   2141     if (_BCM_TR3_EXT_L2_1_FIELD32_MEMACC_GET(unit, ext_l2_entry_1, SCP)) {
   2142         l2addr->flags |= BCM_L2_COS_SRC_PRI;
   2143     }
   2144 
   2145     if (_BCM_TR3_EXT_L2_1_FIELD32_MEMACC_GET(unit, ext_l2_entry_1,
   2146                                              PENDING)) {
   2147         l2addr->flags |= BCM_L2_PENDING;
   2148     }
   2149 
   2150     if (_BCM_TR3_EXT_L2_1_FIELD32_MEMACC_GET(unit, ext_l2_entry_1,
   2151                                              STATIC_BIT)) {
   2152         l2addr->flags |= BCM_L2_STATIC;
   2153     }
   2154 
   2155     if (_BCM_TR3_EXT_L2_1_FIELD32_MEMACC_GET(unit, ext_l2_entry_1,
   2156                                              HITDA)) {
   2157         l2addr->flags |= BCM_L2_DES_HIT;
   2158         if (!SOC_CONTROL(unit)->l2x_age_hitsa_only) {
   2159             l2addr->flags |= BCM_L2_HIT;
   2160         }
   2161     }
   2162 
   2163     if (_BCM_TR3_EXT_L2_1_FIELD32_MEMACC_GET(unit, ext_l2_entry_1,
   2164                                              HITSA)) {
   2165         l2addr->flags |= BCM_L2_SRC_HIT;
   2166         l2addr->flags |= BCM_L2_HIT;
   2167     }
   2168 
   2169     if (_BCM_TR3_EXT_L2_1_FIELD32_MEMACC_GET(unit, ext_l2_entry_1,
   2170                                              LOCAL_SA)) {
   2171         l2addr->flags |= BCM_L2_NATIVE;
   2172     }
   2173     
   2174     if ((!(l2addr->flags & BCM_L2_STATIC)) || 
   2175         l2addr->flags & BCM_L2_LEARN_LIMIT) {
   2176         if (!_BCM_TR3_EXT_L2_1_FIELD32_MEMACC_GET(unit, ext_l2_entry_1,
   2177                                                   LIMIT_COUNTED)) {
   2178             l2addr->flags |= BCM_L2_LEARN_LIMIT_EXEMPT;
   2179         }
   2180     }
   2181 
   2182     if (_BCM_TR3_EXT_L2_1_FIELD32_MEMACC_GET(unit, ext_l2_entry_1,
   2183                                              REMOTE)) {
   2184         l2addr->flags |= BCM_L2_LEARN_LIMIT_EXEMPT_LOCAL;
   2185     }
   2186 
   2187     return BCM_E_NONE;
   2188 }
   2189 
   2190 /*
   2191  * Function:
   2192  *      _bcm_tr3_l2_from_ext_l2_2
   2193  * Purpose:
   2194  *      Convert an EXT_L2_ENTRY_2 to an L2 API data structure
   2195 
   2196  * Parameters:
   2197  *      unit         Unit number
   2198  *      l2addr       (OUT) L2 API data structure
   2199  *      ext_l2_entry_2 EXT_L2_ENTRY_2 hardware entry
   2200  */
   2201 int
   2202 _bcm_tr3_l2_from_ext_l2_2(int unit, bcm_l2_addr_t *l2addr,
   2203                           ext_l2_entry_2_entry_t *ext_l2_entry_2)
   2204 {
   2205     _bcm_gport_dest_t       dest;
   2206     int                     mb_index;
   2207     bcm_module_t            mod;
   2208     bcm_port_t              port;
   2209     soc_memacc_t            *memacc;
   2210     int  isGport = 0;
   2211 #if defined(INCLUDE_L3)
   2212     int vfi;
   2213 #endif
   2214     sal_memset(l2addr, 0, sizeof(*l2addr));
   2215 
   2216      if (_BCM_TR3_EXT_L2_2_FIELD32_MEMACC_GET(unit, ext_l2_entry_2,
   2217                                               KEY_TYPE) ==
   2218          SOC_MEM_KEY_EXT_L2_ENTRY_2_L2_VFI) {
   2219 #if defined(INCLUDE_L3)
   2220          vfi = _BCM_TR3_EXT_L2_2_FIELD32_MEMACC_GET(unit, ext_l2_entry_2,
   2221                                                     VFI);
   2222          /* VPLS or MIM VPN */
   2223          if (_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeMpls)) {
   2224               _BCM_MPLS_VPN_SET(l2addr->vid, _BCM_MPLS_VPN_TYPE_VPLS, vfi);
   2225          } else  if (_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeMim)) {
   2226               _BCM_MIM_VPN_SET(l2addr->vid, _BCM_MIM_VPN_TYPE_MIM, vfi);
   2227          } else  if (_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeL2Gre)) {
   2228               BCM_IF_ERROR_RETURN(
   2229                    _bcm_tr3_l2gre_vpn_get(unit, vfi, &l2addr->vid));
   2230          }
   2231 #endif
   2232     } else {
   2233          l2addr->vid =
   2234              _BCM_TR3_EXT_L2_2_FIELD32_MEMACC_GET(unit, ext_l2_entry_2,
   2235                                                   VLAN_ID);
   2236     }
   2237 
   2238     memacc = _BCM_TR3_L2_MEMACC(unit, EXT_L2_ENTRY_2,
   2239                                 _BCM_TR3_L2_MEMACC_MAC_ADDR);
   2240     soc_memacc_mac_addr_get(memacc, ext_l2_entry_2, l2addr->mac);
   2241 
   2242     _bcm_gport_dest_t_init(&dest);
   2243 #if defined(INCLUDE_L3)
   2244     if (soc_mem_field32_get(unit, EXT_L2_ENTRY_2m,
   2245                             ext_l2_entry_2, DEST_TYPEf) == 0x2) {
   2246          int vp;
   2247 
   2248          vp = _BCM_TR3_EXT_L2_2_FIELD32_MEMACC_GET(unit, ext_l2_entry_2,
   2249                                                    DESTINATION);
   2250          if (_BCM_TR3_EXT_L2_2_FIELD32_MEMACC_GET(unit, ext_l2_entry_2,
   2251                                                   KEY_TYPE) ==
   2252              SOC_MEM_KEY_EXT_L2_ENTRY_2_L2_VFI) {
   2253               /* MPLS/MiM virtual port unicast */
   2254               if (_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) {
   2255                    dest.mpls_id = vp;
   2256                    dest.gport_type = _SHR_GPORT_TYPE_MPLS_PORT;
   2257                    isGport=1;
   2258               } else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeMim)) {
   2259                    dest.mim_id = vp;
   2260                    dest.gport_type = _SHR_GPORT_TYPE_MIM_PORT;
   2261                    isGport=1;
   2262               } else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeL2Gre)) {
   2263                    dest.mim_id = vp;
   2264                    dest.gport_type = _SHR_GPORT_TYPE_L2GRE_PORT;
   2265                    isGport=1;
   2266               } else {
   2267                     /* L2 entries with Stale VPN */
   2268                     dest.gport_type = BCM_GPORT_INVALID;
   2269                     isGport=0;
   2270               }
   2271          } else {
   2272               /* Subport/WLAN unicast */
   2273               if (_bcm_vp_used_get(unit, vp, _bcmVpTypeSubport)) {
   2274                    dest.subport_id = vp;
   2275                    dest.gport_type = _SHR_GPORT_TYPE_SUBPORT_GROUP;
   2276                    isGport=1;
   2277               } else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeWlan)) {
   2278                    dest.wlan_id = vp;
   2279                    dest.gport_type = _SHR_GPORT_TYPE_WLAN_PORT;
   2280                    isGport=1;
   2281               } else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeVlan)) {
   2282                    dest.vlan_vp_id = vp;
   2283                    dest.gport_type = _SHR_GPORT_TYPE_VLAN_PORT;
   2284                    isGport=1;
   2285               } else {
   2286                    return BCM_E_INTERNAL; /* Cannot reach here */
   2287               }
   2288          }
   2289     } else {
   2290 #endif /* INCLUDE_L3 */
   2291         if (_BCM_TR3_EXT_L2_2_FIELD32_MEMACC_GET(unit, ext_l2_entry_2,
   2292                                                  DEST_TYPE) == 0x1) {
   2293             int psc = 0;
   2294             l2addr->tgid =
   2295                 _BCM_TR3_EXT_L2_2_FIELD32_MEMACC_GET(unit, ext_l2_entry_2,
   2296                                                      TGID);
   2297             bcm_esw_trunk_psc_get(unit, l2addr->tgid, &psc);
   2298             dest.tgid = l2addr->tgid;
   2299             dest.gport_type = _SHR_GPORT_TYPE_TRUNK;
   2300 
   2301             l2addr->flags |= BCM_L2_TRUNK_MEMBER;
   2302             if (_BCM_TR3_EXT_L2_2_FIELD32_MEMACC_GET(unit, ext_l2_entry_2,
   2303                                     REMOTE)) {
   2304                 l2addr->flags |= BCM_L2_REMOTE_TRUNK;
   2305             }
   2306         } else {
   2307             mod =
   2308                 _BCM_TR3_EXT_L2_2_FIELD32_MEMACC_GET(unit, ext_l2_entry_2,
   2309                                                      MODULE_ID);
   2310             port =
   2311                 _BCM_TR3_EXT_L2_2_FIELD32_MEMACC_GET(unit, ext_l2_entry_2,
   2312                                                      PORT_NUM);
   2313             BCM_IF_ERROR_RETURN
   2314                 (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET,
   2315                                          mod, port, &mod, &port));
   2316             l2addr->modid = mod;
   2317             l2addr->port = port;
   2318             dest.port = l2addr->port;
   2319             dest.modid = l2addr->modid;
   2320             dest.gport_type = _SHR_GPORT_TYPE_MODPORT;
   2321         }
   2322         BCM_IF_ERROR_RETURN
   2323             (bcm_esw_switch_control_get(unit, bcmSwitchUseGport, &isGport));
   2324 #if defined(INCLUDE_L3)
   2325     }
   2326 #endif /* INCLUDE_L3 */
   2327 
   2328     if (isGport) {
   2329          BCM_IF_ERROR_RETURN
   2330              (_bcm_esw_gport_construct(unit, &dest, &l2addr->port));
   2331     }
   2332 
   2333     if (_BCM_TR3_EXT_L2_2_FIELD32_MEMACC_GET(unit, ext_l2_entry_2, RPE)) {
   2334         l2addr->flags |= BCM_L2_SETPRI;
   2335         l2addr->cos_dst =
   2336             _BCM_TR3_EXT_L2_2_FIELD32_MEMACC_GET(unit, ext_l2_entry_2, PRI);
   2337     }
   2338     l2addr->cos_src = l2addr->cos_dst;
   2339 
   2340     if (SOC_CONTROL(unit)->l2x_group_enable) {
   2341         l2addr->group =
   2342             _BCM_TR3_EXT_L2_2_FIELD32_MEMACC_GET(unit, ext_l2_entry_2, 
   2343                                                  CLASS_ID_FULL);
   2344     } else {
   2345         mb_index =
   2346             _BCM_TR3_EXT_L2_2_FIELD32_MEMACC_GET(unit, ext_l2_entry_2, 
   2347                                                  MAC_BLOCK_INDEX);
   2348         if (mb_index) {
   2349             BCM_PBMP_ASSIGN(l2addr->block_bitmap,
   2350                             _tr3_mbi_entries[unit][mb_index].mb_pbmp);
   2351         }
   2352     }
   2353 
   2354     if (_BCM_TR3_EXT_L2_2_FIELD32_MEMACC_GET(unit, ext_l2_entry_2,
   2355                                              DST_CPU)) {
   2356         l2addr->flags |= BCM_L2_COPY_TO_CPU;
   2357     }
   2358 
   2359     if (_BCM_TR3_EXT_L2_2_FIELD32_MEMACC_GET(unit, ext_l2_entry_2,
   2360                                              DST_DISCARD)) {
   2361         l2addr->flags |= BCM_L2_DISCARD_DST;
   2362     }
   2363 
   2364     if (_BCM_TR3_EXT_L2_2_FIELD32_MEMACC_GET(unit, ext_l2_entry_2,
   2365                                              SRC_DISCARD)) {
   2366         l2addr->flags |= BCM_L2_DISCARD_SRC;
   2367     }
   2368 
   2369     if (_BCM_TR3_EXT_L2_2_FIELD32_MEMACC_GET(unit, ext_l2_entry_2,
   2370                                              SCP)) {
   2371         l2addr->flags |= BCM_L2_COS_SRC_PRI;
   2372     }
   2373 
   2374     if (_BCM_TR3_EXT_L2_2_FIELD32_MEMACC_GET(unit, ext_l2_entry_2,
   2375                                              PENDING)) {
   2376         l2addr->flags |= BCM_L2_PENDING;
   2377     }
   2378 
   2379     if (_BCM_TR3_EXT_L2_2_FIELD32_MEMACC_GET(unit, ext_l2_entry_2,
   2380                                              STATIC_BIT)) {
   2381         l2addr->flags |= BCM_L2_STATIC;
   2382     }
   2383 
   2384     if (_BCM_TR3_EXT_L2_2_FIELD32_MEMACC_GET(unit, ext_l2_entry_2,
   2385                                              HITDA)) {
   2386         l2addr->flags |= BCM_L2_DES_HIT;
   2387         if (!SOC_CONTROL(unit)->l2x_age_hitsa_only) {
   2388             l2addr->flags |= BCM_L2_HIT;
   2389         }
   2390     }
   2391 
   2392     if (_BCM_TR3_EXT_L2_2_FIELD32_MEMACC_GET(unit, ext_l2_entry_2,
   2393                                              HITSA)) {
   2394         l2addr->flags |= BCM_L2_SRC_HIT;
   2395         l2addr->flags |= BCM_L2_HIT;
   2396     }
   2397 
   2398     if (_BCM_TR3_EXT_L2_2_FIELD32_MEMACC_GET(unit, ext_l2_entry_2,
   2399                                              LOCAL_SA)) {
   2400         l2addr->flags |= BCM_L2_NATIVE;
   2401     }
   2402 
   2403     if ((!(l2addr->flags & BCM_L2_STATIC)) || 
   2404         l2addr->flags & BCM_L2_LEARN_LIMIT ) {
   2405         if (!_BCM_TR3_EXT_L2_2_FIELD32_MEMACC_GET(unit, ext_l2_entry_2,
   2406                                                   LIMIT_COUNTED)) {
   2407             l2addr->flags |= BCM_L2_LEARN_LIMIT_EXEMPT;
   2408         }
   2409     }
   2410 
   2411     if (_BCM_TR3_EXT_L2_2_FIELD32_MEMACC_GET(unit, ext_l2_entry_2,
   2412                                              REMOTE)) {
   2413         l2addr->flags |= BCM_L2_LEARN_LIMIT_EXEMPT_LOCAL;
   2414     }
   2415 
   2416     return BCM_E_NONE;
   2417 }
   2418 
   2419 /*
   2420  * Function:
   2421  *      _bcm_tr3_l2api_from_l2hw
   2422  * Purpose:
   2423  *      Convert an EXT_L2_ENTRY_2 to an L2 API data structure
   2424 
   2425  * Parameters:
   2426  *      unit         Unit number
   2427  *      l2addr       (OUT) L2 API data structure
   2428  *      l2_entries  Triumph3 L2 entries structure
   2429  *
   2430  * Note:
   2431  *      The l2_entries structure should only have one valid entry.
   2432  */
   2433 int
   2434 _bcm_tr3_l2api_from_l2hw(int unit, bcm_l2_addr_t *l2addr,
   2435                         _bcm_tr3_l2_entries_t *l2_entries)
   2436 {
   2437     if (l2_entries->entry_flags & _BCM_TR3_L2_SELECT_L2_ENTRY_1) {
   2438         /* L2_ENTRY_1 */
   2439         return _bcm_tr3_l2_from_l2_1(unit, l2addr, &(l2_entries->l2_entry_1));
   2440     }
   2441     if (l2_entries->entry_flags & _BCM_TR3_L2_SELECT_L2_ENTRY_2) {
   2442         /* L2_ENTRY_2 */
   2443         return _bcm_tr3_l2_from_l2_2(unit, l2addr, &(l2_entries->l2_entry_2));
   2444     }
   2445     if (l2_entries->entry_flags & _BCM_TR3_L2_SELECT_EXT_L2_ENTRY_1) {
   2446         /* EXT_L2_ENTRY_1 */
   2447         return _bcm_tr3_l2_from_ext_l2_1(unit, l2addr,
   2448                                          &(l2_entries->ext_l2_entry_1));
   2449     }
   2450     if (l2_entries->entry_flags & _BCM_TR3_L2_SELECT_EXT_L2_ENTRY_2) {
   2451         /* L2_ENTRY_2 */
   2452         return _bcm_tr3_l2_from_ext_l2_2(unit, l2addr,
   2453                                          &(l2_entries->ext_l2_entry_2));
   2454     }
   2455     return BCM_E_NOT_FOUND;  
   2456 }
   2457 
   2458 /*
   2459  * Function:
   2460  *      _bcm_tr3_l2_entries_lookup
   2461  * Purpose:
   2462  *      Serach for an L2 entry specified in an L2 entries structure
   2463 
   2464  * Parameters:
   2465  *      unit         Unit number
   2466  *      l2_entries   (IN) Triumph3 L2 entries structure (search keys)
   2467  *      l2_entries_lookup  (OUT) Triumph3 L2 entries structure (match return)
   2468  */
   2469 int
   2470 _bcm_tr3_l2_entries_lookup(int unit, _bcm_tr3_l2_entries_t *l2_entries,
   2471                            _bcm_tr3_l2_entries_t *l2_entries_lookup)
   2472 {
   2473     int l2_index, rv = BCM_E_NOT_FOUND;
   2474 
   2475     if (l2_entries->entry_flags & _BCM_TR3_L2_SELECT_L2_ENTRY_1) {
   2476         rv = soc_mem_generic_lookup(unit, L2_ENTRY_1m, MEM_BLOCK_ANY,
   2477                                     _BCM_TR3_L2_MEM_BANKS_ALL,
   2478                                     &(l2_entries->l2_entry_1),
   2479                                     &(l2_entries_lookup->l2_entry_1), &l2_index);
   2480 
   2481         if (BCM_FAILURE(rv) && (BCM_E_NOT_FOUND != rv)) {
   2482             return rv;
   2483         } else if (BCM_SUCCESS(rv)) {
   2484             /* Found in L2_ENTRY_1 */
   2485             l2_entries_lookup->entry_flags = _BCM_TR3_L2_SELECT_L2_ENTRY_1;
   2486         } /* else not found */
   2487     }
   2488 
   2489     if ((BCM_E_NOT_FOUND == rv) &&
   2490         (l2_entries->entry_flags & _BCM_TR3_L2_SELECT_L2_ENTRY_2)) {
   2491         rv = soc_mem_generic_lookup(unit, L2_ENTRY_2m, MEM_BLOCK_ANY,
   2492                                     _BCM_TR3_L2_MEM_BANKS_ALL,
   2493                                     &(l2_entries->l2_entry_2),
   2494                                     &(l2_entries_lookup->l2_entry_2),
   2495                                     &l2_index);
   2496 
   2497         if (BCM_FAILURE(rv) && rv != BCM_E_NOT_FOUND) {
   2498             return rv;
   2499         } else if (BCM_SUCCESS(rv)) {
   2500             /* Found in L2_ENTRY_2 */
   2501             l2_entries_lookup->entry_flags = _BCM_TR3_L2_SELECT_L2_ENTRY_2;
   2502         } /* else not found */
   2503     }
   2504 
   2505     if ((BCM_E_NOT_FOUND == rv) &&
   2506         (l2_entries->entry_flags & _BCM_TR3_L2_SELECT_EXT_L2_ENTRY_1)) {
   2507         rv = soc_mem_generic_lookup(unit, EXT_L2_ENTRY_1m, MEM_BLOCK_ANY,
   2508                                     _BCM_TR3_L2_MEM_BANKS_ALL,
   2509                                     &(l2_entries->ext_l2_entry_1),
   2510                                     &(l2_entries_lookup->ext_l2_entry_1),
   2511                                     &l2_index);
   2512 
   2513         if (BCM_FAILURE(rv) && rv != BCM_E_NOT_FOUND) {
   2514             return rv;
   2515         } else if (BCM_SUCCESS(rv)) {
   2516             /* Found in EXT_L2_ENTRY_1 */
   2517             l2_entries_lookup->entry_flags =
   2518                 _BCM_TR3_L2_SELECT_EXT_L2_ENTRY_1;
   2519         } /* else not found */
   2520     }
   2521 
   2522     if ((BCM_E_NOT_FOUND == rv) &&
   2523         (l2_entries->entry_flags & _BCM_TR3_L2_SELECT_EXT_L2_ENTRY_2)) {
   2524         rv = soc_mem_generic_lookup(unit, EXT_L2_ENTRY_2m, MEM_BLOCK_ANY,
   2525                                     _BCM_TR3_L2_MEM_BANKS_ALL,
   2526                                     &(l2_entries->ext_l2_entry_2),
   2527                                     &(l2_entries_lookup->ext_l2_entry_2),
   2528                                     &l2_index);
   2529 
   2530         if (BCM_FAILURE(rv) && rv != BCM_E_NOT_FOUND) {
   2531             return rv;
   2532         } else if (BCM_SUCCESS(rv)) {
   2533             /* Found in EXT_L2_ENTRY_2 */
   2534             l2_entries_lookup->entry_flags =
   2535                 _BCM_TR3_L2_SELECT_EXT_L2_ENTRY_2;
   2536         } /* else not found */
   2537     }
   2538 
   2539     return rv;
   2540 }
   2541 
   2542 /*
   2543  * Function:
   2544  *      _bcm_tr3_l2_entries_delete
   2545  * Purpose:
   2546  *      Delete an L2 entry specified in an L2 entries structure
   2547 
   2548  * Parameters:
   2549  *      unit         Unit number
   2550  *      l2_entries  Triumph3 L2 entries structure
   2551  *
   2552  * Note:
   2553  *      The l2_entries structure should only have one valid entry.
   2554  */
   2555 int
   2556 _bcm_tr3_l2_entries_delete(int unit, _bcm_tr3_l2_entries_t *l2_entries)
   2557 {
   2558     int rv, mb_index = 0;
   2559     int l2_index;    
   2560     soc_control_t *soc = SOC_CONTROL(unit);
   2561     SOC_L2_DEL_SYNC_LOCK(soc);
   2562     /* The entry changed tables on update, so remove the old entry */
   2563     if (l2_entries->entry_flags & _BCM_TR3_L2_SELECT_L2_ENTRY_1) {
   2564         rv = soc_mem_search(unit, L2_ENTRY_1m, MEM_BLOCK_ANY, &l2_index,
   2565                             (void *)&(l2_entries->l2_entry_1),
   2566                             (void *)&(l2_entries->l2_entry_1), 0);
   2567         if (BCM_SUCCESS(rv)) {
   2568             rv = soc_mem_delete_return_old(unit, L2_ENTRY_1m, MEM_BLOCK_ANY,
   2569                                            (void *)&(l2_entries->l2_entry_1),
   2570                                            (void *)&(l2_entries->l2_entry_1));
   2571             if (BCM_SUCCESS(rv)) {
   2572                 rv = soc_tr3_l2x_sync_delete(unit, L2_ENTRY_1m,
   2573                                              (uint32 *)&(l2_entries->l2_entry_1),
   2574                                              l2_index,0);
   2575             }
   2576         }
   2577     } else if (l2_entries->entry_flags & _BCM_TR3_L2_SELECT_L2_ENTRY_2) {
   2578         rv = soc_mem_search(unit, L2_ENTRY_2m, MEM_BLOCK_ANY, &l2_index,
   2579                             (void *)&(l2_entries->l2_entry_2),
   2580                             (void *)&(l2_entries->l2_entry_2), 0);
   2581         if (BCM_SUCCESS(rv)) {
   2582             rv = soc_mem_delete_return_old(unit, L2_ENTRY_2m, MEM_BLOCK_ANY,
   2583                                            (void *)&(l2_entries->l2_entry_2),
   2584                                            (void *)&(l2_entries->l2_entry_2));
   2585             if (BCM_SUCCESS(rv)) {
   2586                 rv = soc_tr3_l2x_sync_delete(unit, L2_ENTRY_2m,
   2587                                              (uint32 *)&(l2_entries->l2_entry_2),
   2588                                              l2_index, 0);
   2589             }
   2590         }
   2591     } else if (l2_entries->entry_flags & _BCM_TR3_L2_SELECT_EXT_L2_ENTRY_1) {
   2592         rv = soc_mem_search(unit, EXT_L2_ENTRY_1m, MEM_BLOCK_ANY, &l2_index,
   2593                             (void *)&(l2_entries->ext_l2_entry_1),
   2594                             (void *)&(l2_entries->ext_l2_entry_1), 0);
   2595         if (BCM_SUCCESS(rv)) {
   2596             rv = soc_mem_delete_return_old(unit, EXT_L2_ENTRY_1m,
   2597                                            MEM_BLOCK_ANY,
   2598                                            (void *)&(l2_entries->ext_l2_entry_1),
   2599                                            (void *)&(l2_entries->ext_l2_entry_1));
   2600             if (BCM_SUCCESS(rv)) {
   2601                 rv = soc_tr3_l2x_sync_delete(unit, EXT_L2_ENTRY_1m,
   2602                                              (uint32 *)&(l2_entries->ext_l2_entry_1),
   2603                                              l2_index, 0);
   2604             }
   2605         }
   2606     } else if (l2_entries->entry_flags & _BCM_TR3_L2_SELECT_EXT_L2_ENTRY_2) {
   2607         rv = soc_mem_search(unit, EXT_L2_ENTRY_2m, MEM_BLOCK_ANY, &l2_index,
   2608                             (void *)&(l2_entries->ext_l2_entry_2),
   2609                             (void *)&(l2_entries->ext_l2_entry_2), 0);
   2610         if (BCM_SUCCESS(rv)) {
   2611             rv = soc_mem_delete_return_old(unit, EXT_L2_ENTRY_2m,
   2612                                            MEM_BLOCK_ANY,
   2613                                            (void *)&(l2_entries->ext_l2_entry_2),
   2614                                            (void *)&(l2_entries->ext_l2_entry_2));
   2615             if (BCM_SUCCESS(rv)) {
   2616                 rv = soc_tr3_l2x_sync_delete(unit, EXT_L2_ENTRY_2m,
   2617                                              (uint32 *)&(l2_entries->ext_l2_entry_2),
   2618                                              l2_index, 0);
   2619             }
   2620         }
   2621     } else {
   2622         SOC_L2_DEL_SYNC_UNLOCK(soc);
   2623         /* This should have been caught earlier. */
   2624         return BCM_E_INTERNAL;
   2625     }
   2626     SOC_L2_DEL_SYNC_UNLOCK(soc);
   2627     if (BCM_SUCCESS(rv)) {
   2628         /* Delete the MAC_BLOCK reference, if appropriate */
   2629         if (!SOC_L2X_GROUP_ENABLE_GET(unit)) {
   2630             mb_index = _bcm_tr3_l2hw_entries_field32_get(unit,
   2631                                                          l2_entries,
   2632                                  _BCM_TR3_L2_MEMACC_MAC_BLOCK_INDEX);
   2633             _bcm_tr3_mac_block_delete(unit, mb_index);
   2634         }
   2635     }
   2636 
   2637     return rv;
   2638 }
   2639 
   2640 #ifdef BCM_KATANA2_SUPPORT 
   2641 STATIC int 
   2642 _kt2_l2_delete_all_by_hw(int unit, int vfi, uint32 replace_flags) 
   2643 { 
   2644     int rv = BCM_E_NONE; 
   2645     sal_usecs_t start_time; 
   2646     int diff_time; 
   2647     uint32 rval; 
   2648     int field_len; 
   2649     l2x_entry_t l2x_entry; 
   2650     uint32 l2_bulk_match_mask[SOC_MAX_MEM_FIELD_WORDS] = {0};
   2651     uint32 l2_bulk_match_data[SOC_MAX_MEM_FIELD_WORDS] = {0};
   2652     bcm_mac_t mac_data;
   2653     uint8 static_bit_val = 0;
   2654 
   2655     sal_memset(&l2x_entry, 0, sizeof(l2x_entry)); 
   2656 
   2657     soc_mem_field32_set(unit, L2Xm, &l2x_entry, VALIDf, 1); 
   2658            
   2659     field_len = soc_mem_field_length(unit, L2Xm, KEY_TYPEf); 
   2660     soc_mem_field32_set(unit, L2Xm, &l2x_entry, KEY_TYPEf, 
   2661                         (1 << field_len) - 1); 
   2662 
   2663     /* Match for STATIC_BIT in the Mask */
   2664     if ((replace_flags & BCM_L2_REPLACE_DYNAMIC) ||
   2665         (replace_flags & BCM_L2_REPLACE_MATCH_STATIC)) {
   2666         soc_mem_field32_set(unit, L2Xm, &l2x_entry, STATIC_BITf, 1);
   2667     }
   2668 
   2669     /* Match for Unicast or Multicast Mac in the Mask */
   2670     sal_memset(&mac_data, 0x00, sizeof(mac_data));
   2671     if ((replace_flags & BCM_L2_REPLACE_MATCH_UC) ||
   2672         (replace_flags & BCM_L2_REPLACE_MATCH_MC)) {
   2673 
   2674         mac_data[0] = 0x01;
   2675         if (vfi <= 0) {
   2676             soc_mem_mac_addr_set(unit, L2Xm, &l2x_entry, L2__MAC_ADDRf,
   2677                                                               mac_data);
   2678         } else {
   2679             soc_mem_mac_addr_set(unit, L2Xm, &l2x_entry, VFI__MAC_ADDRf,
   2680                                                               mac_data);
   2681         }
   2682     }
   2683 
   2684     sal_memcpy(l2_bulk_match_mask, &l2x_entry,
   2685                sizeof(l2_bulk_match_mask_entry_t));
   2686     _BCM_ALL_L2X_MEM_LOCK(unit);
   2687     /*Set match mask*/
   2688     rv = WRITE_L2_BULK_MATCH_MASKm(unit, MEM_BLOCK_ALL, 0, l2_bulk_match_mask);
   2689     _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv);
   2690 
   2691     /* Ensure that STATIC_BIT is set in data as per flag */
   2692     static_bit_val = 0;
   2693     if ((replace_flags & BCM_L2_REPLACE_DYNAMIC) ||
   2694         (replace_flags & BCM_L2_REPLACE_MATCH_STATIC)) {
   2695 
   2696         if (replace_flags & BCM_L2_REPLACE_MATCH_STATIC) {
   2697             static_bit_val = 1;
   2698         }
   2699         soc_mem_field32_set(unit, L2Xm, &l2x_entry, STATIC_BITf,
   2700                                                  static_bit_val);
   2701     }
   2702 
   2703     /* Ensure that Bit 40 is set in data as per flag */
   2704     sal_memset(&mac_data, 0x00, sizeof(mac_data));
   2705     if ((replace_flags & BCM_L2_REPLACE_MATCH_UC) ||
   2706         (replace_flags & BCM_L2_REPLACE_MATCH_MC)) {
   2707 
   2708         if (replace_flags & BCM_L2_REPLACE_MATCH_MC) {
   2709             mac_data[0] = 0x01;
   2710         }
   2711         if (vfi <= 0) {
   2712             soc_mem_mac_addr_set(unit, L2Xm, &l2x_entry, L2__MAC_ADDRf,
   2713                                                               mac_data);
   2714         } else {
   2715             soc_mem_mac_addr_set(unit, L2Xm, &l2x_entry, VFI__MAC_ADDRf,
   2716                                                                mac_data);
   2717         }
   2718     }
   2719     
   2720     if (vfi <= 0) { 
   2721         soc_mem_field32_set(unit, L2Xm, &l2x_entry, KEY_TYPEf, 
   2722                             KT2_L2_HASH_KEY_TYPE_BRIDGE);
   2723     }
   2724 
   2725     sal_memcpy(l2_bulk_match_data, &l2x_entry,
   2726                sizeof(l2_bulk_match_data_entry_t));
   2727     /*Set match data*/
   2728     rv = WRITE_L2_BULK_MATCH_DATAm(unit, MEM_BLOCK_ALL, 0, l2_bulk_match_data);
   2729     _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv);
   2730   
   2731     rv = READ_L2_BULK_CONTROLr(unit, &rval); 
   2732     _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv); 
   2733     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, L2_MOD_FIFO_RECORDf, 0); 
   2734     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ACTIONf, 1); 
   2735     rv = WRITE_L2_BULK_CONTROLr(unit, rval); 
   2736     _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv); 
   2737                      
   2738     /* Delete entries for KT2_L2_HASH_KEY_TYPE_BRIDGE */ 
   2739     if (vfi <= 0) { 
   2740         start_time = sal_time_usecs(); 
   2741         diff_time = 0; 
   2742         rv = soc_tr3_l2_port_age(unit, L2_BULK_CONTROLr, INVALIDr); 
   2743         diff_time = SAL_USECS_SUB(sal_time_usecs(), start_time); 
   2744         _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv); 
   2745         LOG_VERBOSE(BSL_LS_SOC_COMMON,(BSL_META_U(unit, 
   2746                     "Time taken for bulk del L2_ENTRY_L2_BRIDGE: %d\n"), 
   2747                     diff_time)); 
   2748     } else { 
   2749         /* Delete entries for KT2_L2_HASH_KEY_TYPE_VFI */ 
   2750         soc_mem_field32_set(unit, L2Xm, &l2x_entry, KEY_TYPEf, 
   2751                             KT2_L2_HASH_KEY_TYPE_VFI); 
   2752 
   2753         sal_memcpy(l2_bulk_match_data, &l2x_entry,
   2754                    sizeof(l2_bulk_match_data_entry_t));
   2755         /*Set match data*/
   2756         rv = WRITE_L2_BULK_MATCH_DATAm(unit, MEM_BLOCK_ALL, 0,
   2757                                        l2_bulk_match_data);
   2758         _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv);
   2759         
   2760         start_time = sal_time_usecs(); 
   2761         diff_time = 0; 
   2762         rv = soc_tr3_l2_port_age(unit, L2_BULK_CONTROLr, INVALIDr); 
   2763         diff_time = SAL_USECS_SUB(sal_time_usecs(), start_time); 
   2764         _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv); 
   2765         LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit, 
   2766                     "Time taken for bulk del L2_ENTRY_L2_VFI: %d\n"), 
   2767                     diff_time)); 
   2768     }
   2769     /* Clear parity status on L2 bulk operation */
   2770     BCM_IF_ERROR_RETURN
   2771        (soc_reg_field32_modify(unit, L2_BULK_CONTROLr,
   2772                                REG_PORT_ANY, STARTf, 0));
   2773     BCM_IF_ERROR_RETURN
   2774         (soc_reg_field32_modify(unit, L2_BULK_CONTROLr,
   2775                                 REG_PORT_ANY, COMPLETEf, 0));
   2776     _BCM_ALL_L2X_MEM_UNLOCK(unit);
   2777     return rv; 
   2778 } 
   2779 #endif /* BCM_KATANA2_SUPPORT */
   2780 
   2781 STATIC int
   2782 _tr3_l2_delete_all_by_hw(int unit, int vfi, uint32 replace_flags)
   2783 {
   2784     int rv = BCM_E_NONE;
   2785     sal_usecs_t start_time;
   2786     int diff_time;        
   2787     uint32 rval;
   2788     int field_len;
   2789     l2_bulk_entry_t l2_bulk;
   2790     l2_entry_1_entry_t l2_entry_1;
   2791     l2_entry_2_entry_t l2_entry_2;
   2792     ext_l2_entry_1_entry_t ext_l2_entry_1;
   2793     ext_l2_entry_2_entry_t ext_l2_entry_2;
   2794     int ext_l2;
   2795     bcm_mac_t mac_data;
   2796     uint8 static_bit_val = 0;
   2797 
   2798     sal_memset(&l2_entry_1, 0, sizeof(l2_entry_1));
   2799     sal_memset(&l2_entry_2, 0, sizeof(l2_entry_2));
   2800     
   2801     /* First work on L2_ENTRY_1 */
   2802     soc_mem_field32_set(unit, L2_ENTRY_1m, &l2_entry_1, VALIDf, 1);
   2803     soc_mem_field32_set(unit, L2_ENTRY_1m, &l2_entry_1, WIDEf, 1);
   2804     
   2805     field_len = soc_mem_field_length(unit, L2_ENTRY_1m, KEY_TYPEf);
   2806     soc_mem_field32_set(unit, L2_ENTRY_1m, &l2_entry_1, KEY_TYPEf,
   2807                         (1 << field_len) - 1);
   2808 
   2809     /* Match for STATIC_BIT in the Mask */
   2810     if ((replace_flags & BCM_L2_REPLACE_DYNAMIC) ||
   2811         (replace_flags & BCM_L2_REPLACE_MATCH_STATIC)) {
   2812         soc_mem_field32_set(unit, L2_ENTRY_1m, &l2_entry_1, STATIC_BITf, 1);
   2813     }
   2814 
   2815     /* Match for Unicast/Multicast Mac in the Mask */
   2816     sal_memset(&mac_data, 0x00, sizeof(mac_data));
   2817     if ((replace_flags & BCM_L2_REPLACE_MATCH_UC) ||
   2818         (replace_flags & BCM_L2_REPLACE_MATCH_MC)) {
   2819 
   2820         mac_data[0] = 0x01;
   2821         if (vfi <= 0) {
   2822             soc_mem_mac_addr_set(unit, L2_ENTRY_1m, &l2_entry_1, L2__MAC_ADDRf,
   2823                                                                       mac_data);
   2824         } else {
   2825             soc_mem_mac_addr_set(unit, L2_ENTRY_1m, &l2_entry_1, VFI__MAC_ADDRf,
   2826                                                                       mac_data);
   2827         }
   2828     }
   2829 
   2830     sal_memcpy(&l2_bulk, &l2_entry_1, sizeof(l2_entry_1));
   2831     _BCM_ALL_L2X_MEM_LOCK(unit);
   2832     /* Set match mask */
   2833     /* Index 1 points to L2_BULK_MATCH_MASK address in L2_BULK table */
   2834     rv = WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 1, &l2_bulk);
   2835     _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv);
   2836     soc_mem_field32_set(unit, L2_ENTRY_1m, &l2_entry_1, WIDEf, 0);
   2837 
   2838     /* Ensure that STATIC_BIT is set as per flag in data */
   2839     static_bit_val = 0;
   2840     if ((replace_flags & BCM_L2_REPLACE_DYNAMIC) ||
   2841         (replace_flags & BCM_L2_REPLACE_MATCH_STATIC)) {
   2842 
   2843         if (replace_flags & BCM_L2_REPLACE_MATCH_STATIC) {
   2844             static_bit_val = 1;
   2845         }
   2846         soc_mem_field32_set(unit, L2_ENTRY_1m, &l2_entry_1, STATIC_BITf,
   2847                                                          static_bit_val);
   2848     }
   2849 
   2850     /* Ensure that Bit 40 is set as per flag in data */
   2851     sal_memset(&mac_data, 0x00, sizeof(mac_data));
   2852     if ((replace_flags & BCM_L2_REPLACE_MATCH_UC) ||
   2853         (replace_flags & BCM_L2_REPLACE_MATCH_MC)) {
   2854 
   2855         if (replace_flags & BCM_L2_REPLACE_MATCH_MC) {
   2856             mac_data[0]=0x01;
   2857         }
   2858         if (vfi <= 0) {
   2859             soc_mem_mac_addr_set(unit, L2_ENTRY_1m, &l2_entry_1, L2__MAC_ADDRf,
   2860                                                                       mac_data);
   2861         } else {
   2862             soc_mem_mac_addr_set(unit, L2_ENTRY_1m, &l2_entry_1, VFI__MAC_ADDRf,
   2863                                                                        mac_data);
   2864         }
   2865     }
   2866 
   2867     if (vfi <= 0) {
   2868         soc_mem_field32_set(unit, L2_ENTRY_1m, &l2_entry_1, KEY_TYPEf, 
   2869                             SOC_MEM_KEY_L2_ENTRY_1_L2_BRIDGE);
   2870     }
   2871     sal_memcpy(&l2_bulk, &l2_entry_1, sizeof(l2_entry_1));
   2872     /* Set match data */
   2873     /* Index 0 points to L2_BULK_MATCH_DATA address in L2_BULK table */
   2874     rv = WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 0, &l2_bulk);
   2875     _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv);
   2876     rv = READ_L2_BULK_CONTROLr(unit, &rval);
   2877     _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv);
   2878     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, L2_MOD_FIFO_RECORDf, 0);
   2879     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ACTIONf, 1);
   2880     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, BURST_ENTRIESf, 
   2881                       _SOC_TR3_L2_BULK_BURST_MAX);
   2882     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ENTRY_WIDTHf, 0);
   2883     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, NUM_ENTRIESf, 
   2884                       soc_mem_index_count(unit, L2_ENTRY_1m));
   2885     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, EXTERNAL_L2_ENTRYf, 0);
   2886     rv = WRITE_L2_BULK_CONTROLr(unit, rval);
   2887     _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv);
   2888     if (vfi <= 0) {
   2889         start_time = sal_time_usecs();
   2890         diff_time = 0;    
   2891         /* Delete entries for SOC_MEM_KEY_L2_ENTRY_1_L2_BRIDGE */ 
   2892         rv = soc_tr3_l2_port_age(unit, L2_BULK_CONTROLr, INVALIDr);
   2893         diff_time = SAL_USECS_SUB(sal_time_usecs(), start_time);
   2894         _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv);
   2895         LOG_VERBOSE(BSL_LS_SOC_COMMON,
   2896                     (BSL_META_U(unit,
   2897                                 "Time taken for bulk del L2_ENTRY_1_L2_BRIDGE: %d\n"), 
   2898                      diff_time));
   2899     } else {
   2900         soc_mem_field32_set(unit, L2_ENTRY_1m, &l2_entry_1, KEY_TYPEf, 
   2901                             SOC_MEM_KEY_L2_ENTRY_1_L2_VFI);
   2902         sal_memcpy(&l2_bulk, &l2_entry_1, sizeof(l2_entry_1));
   2903         /* Set match data */
   2904         rv = WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 0, &l2_bulk);
   2905         _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv);
   2906         start_time = sal_time_usecs();
   2907         diff_time = 0;
   2908         /* Delete entries for SOC_MEM_KEY_L2_ENTRY_1_L2_VFI */
   2909         rv = soc_tr3_l2_port_age(unit, L2_BULK_CONTROLr, INVALIDr);
   2910         diff_time = SAL_USECS_SUB(sal_time_usecs(), start_time);
   2911         _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv);
   2912         LOG_VERBOSE(BSL_LS_SOC_COMMON,
   2913                     (BSL_META_U(unit,
   2914                                 "Time taken for bulk del L2_ENTRY_1_L2_VFI: %d\n"), 
   2915                      diff_time));
   2916     }
   2917     /* Then work on L2_ENTRY_2 */
   2918     soc_mem_field32_set(unit, L2_ENTRY_2m, &l2_entry_2, VALID_0f, 1);
   2919     soc_mem_field32_set(unit, L2_ENTRY_2m, &l2_entry_2, VALID_1f, 1);
   2920     soc_mem_field32_set(unit, L2_ENTRY_2m, &l2_entry_2, WIDE_0f, 1);
   2921     soc_mem_field32_set(unit, L2_ENTRY_2m, &l2_entry_2, WIDE_1f, 1);
   2922     field_len = soc_mem_field_length(unit, L2_ENTRY_2m, KEY_TYPE_0f);
   2923     soc_mem_field32_set(unit, L2_ENTRY_2m, &l2_entry_2, KEY_TYPE_0f,
   2924                         (1 << field_len) - 1);
   2925     soc_mem_field32_set(unit, L2_ENTRY_2m, &l2_entry_2, KEY_TYPE_1f,
   2926                         (1 << field_len) - 1);
   2927 
   2928     /* Match for STATIC_BIT in the Mask */
   2929     if ((replace_flags & BCM_L2_REPLACE_DYNAMIC) ||
   2930         (replace_flags & BCM_L2_REPLACE_MATCH_STATIC)) {
   2931         soc_mem_field32_set(unit, L2_ENTRY_2m, &l2_entry_2, STATIC_BIT_0f, 1);
   2932         soc_mem_field32_set(unit, L2_ENTRY_2m, &l2_entry_2, STATIC_BIT_1f, 1);
   2933     }
   2934 
   2935     /* Match for Unicast/Multicast Mac in the Mask */
   2936     sal_memset(&mac_data, 0x00, sizeof(mac_data));
   2937     if ((replace_flags & BCM_L2_REPLACE_MATCH_UC) ||
   2938         (replace_flags & BCM_L2_REPLACE_MATCH_MC)) {
   2939 
   2940         mac_data[0] = 0x01;
   2941         if (vfi <= 0) {
   2942             soc_mem_mac_addr_set(unit, L2_ENTRY_2m, &l2_entry_2, L2__MAC_ADDRf,
   2943                                                                       mac_data);
   2944         } else {
   2945             soc_mem_mac_addr_set(unit, L2_ENTRY_2m, &l2_entry_2, VFI__MAC_ADDRf,
   2946                                                                       mac_data);
   2947         }
   2948     }
   2949 
   2950     sal_memcpy(&l2_bulk, &l2_entry_2, sizeof(l2_entry_2));
   2951     /* Set match mask */
   2952     rv = WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 1, &l2_bulk);
   2953     _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv);
   2954     if (vfi <= 0) {
   2955         soc_mem_field32_set(unit, L2_ENTRY_2m, &l2_entry_2, KEY_TYPE_0f, 
   2956                                 SOC_MEM_KEY_L2_ENTRY_2_L2_BRIDGE);
   2957         soc_mem_field32_set(unit, L2_ENTRY_2m, &l2_entry_2, KEY_TYPE_1f, 
   2958                                 SOC_MEM_KEY_L2_ENTRY_2_L2_BRIDGE);
   2959     }
   2960 
   2961     /* Ensure that STATIC_BIT is set as per flag in data */
   2962     static_bit_val = 0;
   2963     if ((replace_flags & BCM_L2_REPLACE_DYNAMIC) ||
   2964         (replace_flags & BCM_L2_REPLACE_MATCH_STATIC)) {
   2965 
   2966         if (replace_flags & BCM_L2_REPLACE_MATCH_STATIC) {
   2967             static_bit_val = 1;
   2968         }
   2969         soc_mem_field32_set(unit, L2_ENTRY_2m, &l2_entry_2, STATIC_BIT_0f,
   2970                                                            static_bit_val);
   2971         soc_mem_field32_set(unit, L2_ENTRY_2m, &l2_entry_2, STATIC_BIT_1f,
   2972                                                            static_bit_val);
   2973     }
   2974 
   2975     /* Ensure that Bit 40 is set as per flag in data */
   2976     sal_memset(&mac_data, 0x00, sizeof(mac_data));
   2977     if ((replace_flags & BCM_L2_REPLACE_MATCH_UC) ||
   2978         (replace_flags & BCM_L2_REPLACE_MATCH_MC)) {
   2979 
   2980         if (replace_flags & BCM_L2_REPLACE_MATCH_MC) {
   2981             mac_data[0]=0x01;
   2982         }
   2983         if (vfi <= 0) {
   2984             soc_mem_mac_addr_set(unit, L2_ENTRY_2m, &l2_entry_2, L2__MAC_ADDRf,
   2985                                                                       mac_data);
   2986         } else {
   2987             soc_mem_mac_addr_set(unit, L2_ENTRY_2m, &l2_entry_2, VFI__MAC_ADDRf,
   2988                                                                       mac_data);
   2989         }
   2990     }
   2991 
   2992     sal_memcpy(&l2_bulk, &l2_entry_2, sizeof(l2_entry_2));
   2993     /* Set match data */
   2994     rv = WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 0, &l2_bulk);
   2995     _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv);
   2996     rv = READ_L2_BULK_CONTROLr(unit, &rval);
   2997     _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv);
   2998     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ENTRY_WIDTHf, 1);
   2999     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, NUM_ENTRIESf, 
   3000                       soc_mem_index_count(unit, L2_ENTRY_2m));
   3001     rv = WRITE_L2_BULK_CONTROLr(unit, rval);
   3002     _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv);
   3003     if (vfi <= 0) {
   3004         /* Set the Key type match */
   3005         SOC_IF_ERROR_RETURN(READ_L2_BULK_KEY_TYPE_PORT_Ar(unit, &rval));
   3006         soc_reg_field_set(unit, L2_BULK_KEY_TYPE_PORT_Ar, &rval,
   3007                           KEY_TYPEf, SOC_MEM_KEY_L2_ENTRY_2_L2_BRIDGE);
   3008         SOC_IF_ERROR_RETURN(WRITE_L2_BULK_KEY_TYPE_PORT_Ar(unit, rval));
   3009         SOC_IF_ERROR_RETURN(READ_L2_BULK_KEY_TYPE_PORT_Br(unit, &rval));
   3010         soc_reg_field_set(unit, L2_BULK_KEY_TYPE_PORT_Br, &rval,
   3011                           KEY_TYPEf, SOC_MEM_KEY_L2_ENTRY_2_L2_BRIDGE);
   3012         SOC_IF_ERROR_RETURN(WRITE_L2_BULK_KEY_TYPE_PORT_Br(unit, rval));
   3013 
   3014         start_time = sal_time_usecs();
   3015         diff_time = 0;
   3016         /* Delete entries for SOC_MEM_KEY_L2_ENTRY_2_L2_BRIDGE */ 
   3017         rv = soc_tr3_l2_port_age(unit, L2_BULK_CONTROLr, INVALIDr);
   3018         diff_time = SAL_USECS_SUB(sal_time_usecs(), start_time);
   3019         
   3020         _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv);
   3021         LOG_VERBOSE(BSL_LS_SOC_COMMON,
   3022                     (BSL_META_U(unit,
   3023                                 "Time taken for bulk del L2_ENTRY_2_L2_BRIDGE: %d\n"), 
   3024                      diff_time));
   3025     } else {
   3026         soc_mem_field32_set(unit, L2_ENTRY_2m, &l2_entry_2, KEY_TYPE_0f, 
   3027                             SOC_MEM_KEY_L2_ENTRY_2_L2_VFI);
   3028         soc_mem_field32_set(unit, L2_ENTRY_2m, &l2_entry_2, KEY_TYPE_1f, 
   3029                             SOC_MEM_KEY_L2_ENTRY_2_L2_VFI);
   3030         sal_memcpy(&l2_bulk, &l2_entry_2, sizeof(l2_entry_2));
   3031         /* Set match data */
   3032         rv = WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 0, &l2_bulk);
   3033         _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv);
   3034         /* Set the Key type match */
   3035         SOC_IF_ERROR_RETURN(READ_L2_BULK_KEY_TYPE_PORT_Ar(unit, &rval));
   3036         soc_reg_field_set(unit, L2_BULK_KEY_TYPE_PORT_Ar, &rval,
   3037                           KEY_TYPEf, SOC_MEM_KEY_L2_ENTRY_2_L2_VFI);
   3038         SOC_IF_ERROR_RETURN(WRITE_L2_BULK_KEY_TYPE_PORT_Ar(unit, rval));
   3039         SOC_IF_ERROR_RETURN(READ_L2_BULK_KEY_TYPE_PORT_Br(unit, &rval));
   3040         soc_reg_field_set(unit, L2_BULK_KEY_TYPE_PORT_Br, &rval,
   3041                           KEY_TYPEf, SOC_MEM_KEY_L2_ENTRY_2_L2_VFI);
   3042         SOC_IF_ERROR_RETURN(WRITE_L2_BULK_KEY_TYPE_PORT_Br(unit, rval));
   3043 
   3044         start_time = sal_time_usecs();
   3045         diff_time = 0;
   3046         /* Delete entries for SOC_MEM_KEY_L2_ENTRY_2_L2_VFI */
   3047         rv = soc_tr3_l2_port_age(unit, L2_BULK_CONTROLr, INVALIDr);
   3048         diff_time = SAL_USECS_SUB(sal_time_usecs(), start_time);
   3049         LOG_VERBOSE(BSL_LS_SOC_COMMON,
   3050                     (BSL_META_U(unit,
   3051                                 "Time taken for bulk del L2_ENTRY_2_L2_VFI: %d\n"), 
   3052                      diff_time));
   3053     }
   3054     _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv);
   3055     
   3056     if (!soc_feature(unit, soc_feature_esm_support)) {
   3057         _BCM_ALL_L2X_MEM_UNLOCK(unit);
   3058         return rv;
   3059     }
   3060     ext_l2 = soc_property_get(unit, "EXT_L2_BULK_CLEAR", 0);
   3061     if (ext_l2 == 2) {
   3062         goto _ext_l2_2_bulk;
   3063     }
   3064     /* First work on EXT_L2_ENTRY_1 */
   3065     sal_memset(&ext_l2_entry_1, 0, sizeof(ext_l2_entry_1));
   3066     soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &ext_l2_entry_1, FREEf, 1);
   3067     if (vfi >= 0) {
   3068         field_len = soc_mem_field_length(unit, EXT_L2_ENTRY_1m, KEY_TYPEf);
   3069         soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &ext_l2_entry_1, KEY_TYPEf,
   3070                             (1 << field_len) - 1);
   3071     }
   3072 
   3073     /* Match for STATIC_BIT in the Mask */
   3074     if ((replace_flags & BCM_L2_REPLACE_DYNAMIC) ||
   3075         (replace_flags & BCM_L2_REPLACE_MATCH_STATIC)) {
   3076         soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &ext_l2_entry_1,
   3077                                                     STATIC_BITf, 1);
   3078     }
   3079 
   3080     /* Match for Unicast/Multicast Mac in the Mask */
   3081     sal_memset(&mac_data, 0x00, sizeof(mac_data));
   3082     if ((replace_flags & BCM_L2_REPLACE_MATCH_UC) ||
   3083         (replace_flags & BCM_L2_REPLACE_MATCH_MC)) {
   3084         mac_data[0] = 0x01;
   3085         soc_mem_mac_addr_set(unit, EXT_L2_ENTRY_1m, &ext_l2_entry_1, MAC_ADDRf,
   3086                                                                       mac_data);
   3087     }
   3088 
   3089     sal_memcpy(&l2_bulk, &ext_l2_entry_1, sizeof(ext_l2_entry_1));
   3090     /* Set match mask */
   3091     rv = WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 1, &l2_bulk);
   3092     _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv);
   3093     sal_memset(&l2_bulk, 0, sizeof(l2_bulk));
   3094     if (vfi <= 0) {
   3095         sal_memset(&ext_l2_entry_1, 0, sizeof(ext_l2_entry_1));
   3096         soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &ext_l2_entry_1, KEY_TYPEf, 
   3097                             SOC_MEM_KEY_EXT_L2_ENTRY_1_L2_BRIDGE);
   3098 
   3099         /* Ensure that STATIC_BIT is set as per flag in data */
   3100         static_bit_val = 0;
   3101         if ((replace_flags & BCM_L2_REPLACE_DYNAMIC) ||
   3102             (replace_flags & BCM_L2_REPLACE_MATCH_STATIC)) {
   3103 
   3104             if (replace_flags & BCM_L2_REPLACE_MATCH_STATIC) {
   3105                 static_bit_val = 1;
   3106             }
   3107             soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &ext_l2_entry_1,
   3108                                            STATIC_BITf, static_bit_val);
   3109         }
   3110 
   3111         /* Ensure that Bit 40 is set as per flag in data */
   3112         sal_memset(&mac_data, 0x00, sizeof(mac_data));
   3113         if ((replace_flags & BCM_L2_REPLACE_MATCH_UC) ||
   3114             (replace_flags & BCM_L2_REPLACE_MATCH_MC)) {
   3115 
   3116             if (replace_flags & BCM_L2_REPLACE_MATCH_MC) {
   3117                 mac_data[0]=0x01;
   3118             }
   3119             soc_mem_mac_addr_set(unit, EXT_L2_ENTRY_1m, &ext_l2_entry_1, MAC_ADDRf,
   3120                                                                           mac_data);
   3121         }
   3122         sal_memcpy(&l2_bulk, &ext_l2_entry_1, sizeof(ext_l2_entry_1));
   3123     }    
   3124     /* Set match data */
   3125     rv = WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 0, &l2_bulk);
   3126     _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv);
   3127     rv = READ_L2_BULK_CONTROLr(unit, &rval);
   3128     _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv);
   3129     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ACTIONf, 1);
   3130     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, BURST_ENTRIESf, 
   3131                       _SOC_TR3_L2_BULK_BURST_MAX);
   3132     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ENTRY_WIDTHf, 0);
   3133     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, NUM_ENTRIESf, 
   3134                       SOC_MEM_TR3_EXT_L2_MAX_ENTRIES);
   3135     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, EXTERNAL_L2_ENTRYf, 1);
   3136     rv = WRITE_L2_BULK_CONTROLr(unit, rval);
   3137     _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv);
   3138     if (vfi <= 0) {
   3139         /* Set the Key type match */
   3140         SOC_IF_ERROR_RETURN(READ_L2_BULK_KEY_TYPE_PORT_Ar(unit, &rval));
   3141         soc_reg_field_set(unit, L2_BULK_KEY_TYPE_PORT_Ar, &rval,
   3142                           KEY_TYPEf, SOC_MEM_KEY_EXT_L2_ENTRY_1_L2_BRIDGE);
   3143         SOC_IF_ERROR_RETURN(WRITE_L2_BULK_KEY_TYPE_PORT_Ar(unit, rval));
   3144         SOC_IF_ERROR_RETURN(READ_L2_BULK_KEY_TYPE_PORT_Br(unit, &rval));
   3145         soc_reg_field_set(unit, L2_BULK_KEY_TYPE_PORT_Br, &rval,
   3146                           KEY_TYPEf, SOC_MEM_KEY_EXT_L2_ENTRY_1_L2_BRIDGE);
   3147         SOC_IF_ERROR_RETURN(WRITE_L2_BULK_KEY_TYPE_PORT_Br(unit, rval));
   3148 
   3149         start_time = sal_time_usecs();
   3150         diff_time = 0;
   3151         /* Delete entries */ 
   3152         rv = soc_tr3_l2_port_age(unit, L2_BULK_CONTROLr, INVALIDr);
   3153         diff_time = SAL_USECS_SUB(sal_time_usecs(), start_time);
   3154         _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv);
   3155         LOG_VERBOSE(BSL_LS_SOC_COMMON,
   3156                     (BSL_META_U(unit,
   3157                                 "Time taken for bulk del EXT_L2_ENTRY_1: %d\n"), 
   3158                      diff_time));
   3159     } else {
   3160         soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &ext_l2_entry_1, KEY_TYPEf, 
   3161                             SOC_MEM_KEY_EXT_L2_ENTRY_1_L2_VFI);
   3162 
   3163         /* Ensure that STATIC_BIT is set as per flag in data */
   3164         static_bit_val = 0;
   3165         if ((replace_flags & BCM_L2_REPLACE_DYNAMIC) ||
   3166             (replace_flags & BCM_L2_REPLACE_MATCH_STATIC)) {
   3167 
   3168             if (replace_flags & BCM_L2_REPLACE_MATCH_STATIC) {
   3169                 static_bit_val = 1;
   3170             }
   3171             soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &ext_l2_entry_1,
   3172                                            STATIC_BITf, static_bit_val);
   3173         }
   3174 
   3175         /* Ensure that Bit 40 is set as per flag in data */
   3176         sal_memset(&mac_data, 0x00, sizeof(mac_data));
   3177         if ((replace_flags & BCM_L2_REPLACE_MATCH_UC) ||
   3178             (replace_flags & BCM_L2_REPLACE_MATCH_MC)) {
   3179 
   3180             if (replace_flags & BCM_L2_REPLACE_MATCH_MC) {
   3181                 mac_data[0]=0x01;
   3182             }
   3183             soc_mem_mac_addr_set(unit, EXT_L2_ENTRY_1m, &ext_l2_entry_1, MAC_ADDRf,
   3184                                                                           mac_data);
   3185         }
   3186         sal_memcpy(&l2_bulk, &ext_l2_entry_1, sizeof(ext_l2_entry_1));
   3187         /* Set match data */
   3188         rv = WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 0, &l2_bulk);
   3189         _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv);
   3190         /* Set the Key type match */
   3191         SOC_IF_ERROR_RETURN(READ_L2_BULK_KEY_TYPE_PORT_Ar(unit, &rval));
   3192         soc_reg_field_set(unit, L2_BULK_KEY_TYPE_PORT_Ar, &rval,
   3193                           KEY_TYPEf, SOC_MEM_KEY_EXT_L2_ENTRY_1_L2_VFI);
   3194         SOC_IF_ERROR_RETURN(WRITE_L2_BULK_KEY_TYPE_PORT_Ar(unit, rval));
   3195         SOC_IF_ERROR_RETURN(READ_L2_BULK_KEY_TYPE_PORT_Br(unit, &rval));
   3196         soc_reg_field_set(unit, L2_BULK_KEY_TYPE_PORT_Br, &rval,
   3197                           KEY_TYPEf, SOC_MEM_KEY_EXT_L2_ENTRY_1_L2_VFI);
   3198         SOC_IF_ERROR_RETURN(WRITE_L2_BULK_KEY_TYPE_PORT_Br(unit, rval));
   3199 
   3200         start_time = sal_time_usecs();
   3201         diff_time = 0;
   3202         /* Delete entries */ 
   3203         rv = soc_tr3_l2_port_age(unit, L2_BULK_CONTROLr, INVALIDr);
   3204         diff_time = SAL_USECS_SUB(sal_time_usecs(), start_time);
   3205         _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv);
   3206         LOG_VERBOSE(BSL_LS_SOC_COMMON,
   3207                     (BSL_META_U(unit,
   3208                                 "Time taken for bulk del EXT_L2_ENTRY_1: %d\n"), 
   3209                      diff_time));
   3210     }
   3211     rv = WRITE_ETU_EXT_L2_BULK_INFOr(unit, 0);
   3212     _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv);
   3213     /* Issue dummy op */
   3214     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ACTIONf, 0);
   3215     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ENTRY_WIDTHf, 0);
   3216     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, NUM_ENTRIESf, 1);
   3217     rv = WRITE_L2_BULK_CONTROLr(unit, rval);
   3218     _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv);
   3219     rv = soc_tr3_l2_port_age(unit, L2_BULK_CONTROLr, INVALIDr);
   3220     _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv);
   3221     rv = WRITE_ETU_EXT_L2_BULK_INFOr(unit, 0);
   3222     _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv);
   3223 
   3224 _ext_l2_2_bulk:
   3225     if (ext_l2 == 1) {
   3226         _BCM_ALL_L2X_MEM_UNLOCK(unit);
   3227         return rv;
   3228     }
   3229     /* Then work on EXT_L2_ENTRY_2 */
   3230     sal_memset(&ext_l2_entry_2, 0, sizeof(ext_l2_entry_2));
   3231     soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &ext_l2_entry_2, FREEf, 1);
   3232     if (vfi >= 0) {
   3233         field_len = soc_mem_field_length(unit, EXT_L2_ENTRY_2m, KEY_TYPEf);
   3234         soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &ext_l2_entry_2, KEY_TYPEf,
   3235                             (1 << field_len) - 1);
   3236     }
   3237 
   3238     /* Match for STATIC_BIT in the Mask */
   3239     if ((replace_flags & BCM_L2_REPLACE_DYNAMIC) ||
   3240         (replace_flags & BCM_L2_REPLACE_MATCH_STATIC)) {
   3241         soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &ext_l2_entry_2,
   3242                                                     STATIC_BITf, 1);
   3243     }
   3244 
   3245     /* Match for Unicast/Multicast Mac in the Mask */
   3246     sal_memset(&mac_data, 0x00, sizeof(mac_data));
   3247     if ((replace_flags & BCM_L2_REPLACE_MATCH_UC) ||
   3248         (replace_flags & BCM_L2_REPLACE_MATCH_MC)) {
   3249         mac_data[0] = 0x01;
   3250         soc_mem_mac_addr_set(unit, EXT_L2_ENTRY_2m, &ext_l2_entry_2, MAC_ADDRf,
   3251                                                                       mac_data);
   3252     }
   3253 
   3254     sal_memcpy(&l2_bulk, &ext_l2_entry_2, sizeof(ext_l2_entry_2));
   3255     /* Set match mask */
   3256     rv = WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 1, &l2_bulk);
   3257     sal_memset(&l2_bulk, 0, sizeof(l2_bulk));
   3258     _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv);
   3259     if (vfi <= 0) {
   3260         sal_memset(&ext_l2_entry_2, 0, sizeof(ext_l2_entry_2));
   3261         soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &ext_l2_entry_2, KEY_TYPEf, 
   3262                             SOC_MEM_KEY_EXT_L2_ENTRY_2_L2_BRIDGE);
   3263 
   3264         /* Ensure that STATIC_BIT is set as per flag in data */
   3265         static_bit_val = 0;
   3266         if ((replace_flags & BCM_L2_REPLACE_DYNAMIC) ||
   3267             (replace_flags & BCM_L2_REPLACE_MATCH_STATIC)) {
   3268 
   3269             if (replace_flags & BCM_L2_REPLACE_MATCH_STATIC) {
   3270                 static_bit_val = 1;
   3271             }
   3272             soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &ext_l2_entry_2,
   3273                     STATIC_BITf, static_bit_val);
   3274         }
   3275 
   3276         /* Ensure that Bit 40 is set as per flag in data */
   3277         sal_memset(&mac_data, 0x00, sizeof(mac_data));
   3278         if ((replace_flags & BCM_L2_REPLACE_MATCH_UC) ||
   3279             (replace_flags & BCM_L2_REPLACE_MATCH_MC)) {
   3280 
   3281             if (replace_flags & BCM_L2_REPLACE_MATCH_MC) {
   3282                 mac_data[0]=0x01;
   3283             }
   3284             soc_mem_mac_addr_set(unit, EXT_L2_ENTRY_2m, &ext_l2_entry_2, MAC_ADDRf,
   3285                                                                           mac_data);
   3286         }
   3287         sal_memcpy(&l2_bulk, &ext_l2_entry_2, sizeof(ext_l2_entry_2));
   3288     }
   3289     /* Set match data */
   3290     rv = WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 0, &l2_bulk);
   3291     _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv);
   3292     sal_memset(&l2_bulk, 0, sizeof(l2_bulk));
   3293     rv = READ_L2_BULK_CONTROLr(unit, &rval);
   3294     _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv);
   3295     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ACTIONf, 1);
   3296     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, BURST_ENTRIESf, 
   3297                       _SOC_TR3_L2_BULK_BURST_MAX);
   3298     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ENTRY_WIDTHf, 1);
   3299     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, NUM_ENTRIESf, 
   3300                       SOC_MEM_TR3_EXT_L2_MAX_ENTRIES);
   3301     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, EXTERNAL_L2_ENTRYf, 1);
   3302     rv = WRITE_L2_BULK_CONTROLr(unit, rval);
   3303     _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv);
   3304     if (vfi <= 0) {
   3305         /* Set the Key type match */
   3306         SOC_IF_ERROR_RETURN(READ_L2_BULK_KEY_TYPE_PORT_Ar(unit, &rval));
   3307         soc_reg_field_set(unit, L2_BULK_KEY_TYPE_PORT_Ar, &rval,
   3308                           KEY_TYPEf, SOC_MEM_KEY_EXT_L2_ENTRY_2_L2_BRIDGE);
   3309         SOC_IF_ERROR_RETURN(WRITE_L2_BULK_KEY_TYPE_PORT_Ar(unit, rval));
   3310         SOC_IF_ERROR_RETURN(READ_L2_BULK_KEY_TYPE_PORT_Br(unit, &rval));
   3311         soc_reg_field_set(unit, L2_BULK_KEY_TYPE_PORT_Br, &rval,
   3312                           KEY_TYPEf, SOC_MEM_KEY_EXT_L2_ENTRY_2_L2_BRIDGE);
   3313         SOC_IF_ERROR_RETURN(WRITE_L2_BULK_KEY_TYPE_PORT_Br(unit, rval));
   3314 
   3315         start_time = sal_time_usecs();
   3316         diff_time = 0;
   3317         /* Delete entries */ 
   3318         rv = soc_tr3_l2_port_age(unit, L2_BULK_CONTROLr, INVALIDr);
   3319         _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv);
   3320         diff_time = SAL_USECS_SUB(sal_time_usecs(), start_time);
   3321         LOG_VERBOSE(BSL_LS_SOC_COMMON,
   3322                     (BSL_META_U(unit,
   3323                                 "Time taken for bulk del EXT_L2_ENTRY_2: %d\n"), 
   3324                      diff_time));
   3325     } else {
   3326         soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &ext_l2_entry_2, KEY_TYPEf, 
   3327                             SOC_MEM_KEY_EXT_L2_ENTRY_2_L2_VFI);
   3328 
   3329         /* Ensure that STATIC_BIT is set as per flag in data */
   3330         static_bit_val = 0;
   3331         if ((replace_flags & BCM_L2_REPLACE_DYNAMIC) ||
   3332             (replace_flags & BCM_L2_REPLACE_MATCH_STATIC)) {
   3333 
   3334             if (replace_flags & BCM_L2_REPLACE_MATCH_STATIC) {
   3335                 static_bit_val = 1;
   3336             }
   3337             soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &ext_l2_entry_2,
   3338                     STATIC_BITf, static_bit_val);
   3339         }
   3340 
   3341         /* Ensure that Bit 40 is set as per flag in data */
   3342         sal_memset(&mac_data, 0x00, sizeof(mac_data));
   3343         if ((replace_flags & BCM_L2_REPLACE_MATCH_UC) ||
   3344             (replace_flags & BCM_L2_REPLACE_MATCH_MC)) {
   3345 
   3346             if (replace_flags & BCM_L2_REPLACE_MATCH_MC) {
   3347                 mac_data[0]=0x01;
   3348             }
   3349             soc_mem_mac_addr_set(unit, EXT_L2_ENTRY_2m, &ext_l2_entry_2, MAC_ADDRf,
   3350                                                                           mac_data);
   3351         }
   3352         sal_memcpy(&l2_bulk, &ext_l2_entry_2, sizeof(ext_l2_entry_2));
   3353         /* Set match data */
   3354         rv = WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 0, &l2_bulk);
   3355         _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv);
   3356         /* Set the Key type match */
   3357         SOC_IF_ERROR_RETURN(READ_L2_BULK_KEY_TYPE_PORT_Ar(unit, &rval));
   3358         soc_reg_field_set(unit, L2_BULK_KEY_TYPE_PORT_Ar, &rval,
   3359                           KEY_TYPEf, SOC_MEM_KEY_EXT_L2_ENTRY_2_L2_VFI);
   3360         SOC_IF_ERROR_RETURN(WRITE_L2_BULK_KEY_TYPE_PORT_Ar(unit, rval));
   3361         SOC_IF_ERROR_RETURN(READ_L2_BULK_KEY_TYPE_PORT_Br(unit, &rval));
   3362         soc_reg_field_set(unit, L2_BULK_KEY_TYPE_PORT_Br, &rval,
   3363                           KEY_TYPEf, SOC_MEM_KEY_EXT_L2_ENTRY_2_L2_VFI);
   3364         SOC_IF_ERROR_RETURN(WRITE_L2_BULK_KEY_TYPE_PORT_Br(unit, rval));
   3365 
   3366         start_time = sal_time_usecs();
   3367         diff_time = 0;
   3368         /* Delete entries */ 
   3369         rv = soc_tr3_l2_port_age(unit, L2_BULK_CONTROLr, INVALIDr);
   3370         diff_time = SAL_USECS_SUB(sal_time_usecs(), start_time);
   3371         _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv);
   3372         LOG_VERBOSE(BSL_LS_SOC_COMMON,
   3373                     (BSL_META_U(unit,
   3374                                 "Time taken for bulk del EXT_L2_ENTRY_2: %d\n"), 
   3375                      diff_time));
   3376     }
   3377     rv = WRITE_ETU_EXT_L2_BULK_INFOr(unit, 0);
   3378     /* Issue dummy op */
   3379     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ACTIONf, 0);
   3380     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ENTRY_WIDTHf, 0);
   3381     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, NUM_ENTRIESf, 1);
   3382     rv = WRITE_L2_BULK_CONTROLr(unit, rval);
   3383     _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv);
   3384     rv = soc_tr3_l2_port_age(unit, L2_BULK_CONTROLr, INVALIDr);
   3385     _BCM_IF_ERROR_ALL_L2X_UNLOCK_RETURN(rv);
   3386     rv = WRITE_ETU_EXT_L2_BULK_INFOr(unit, 0);
   3387     _BCM_ALL_L2X_MEM_UNLOCK(unit);
   3388 
   3389     return rv;
   3390 }
   3391 
   3392 /*
   3393  * Function:
   3394  *      _tr3_l2x_delete_all
   3395  * Purpose:
   3396  *      Clear the ISM L2 table by invalidating entries.
   3397  * Parameters:
   3398  *      unit - StrataSwitch unit #
   3399  * Returns:
   3400  *      SOC_E_XXX
   3401  */
   3402 
   3403 STATIC int
   3404 _tr3_l2x_delete_all(int unit)
   3405 {
   3406     int chnk_idx, ent_idx, chnk_idx_max, mem_idx_max;
   3407     int chunksize, chnk_end;
   3408     int index_min, wide_entry_half, clear_entry;
   3409     int rv = BCM_E_NONE;
   3410     int *buffer = NULL;
   3411     int mem_size;
   3412     int modified;
   3413     l2_entry_1_entry_t *l2_entry_1;
   3414     soc_memacc_t *memacc_valid, *memacc_key_type;
   3415     uint32 key_type;
   3416 
   3417     if(soc_property_get(unit, spn_MEM_CLEAR_HW_ACCELERATION, 1) && 
   3418        !SAL_BOOT_SIMULATION) {
   3419         return _tr3_l2_delete_all_by_hw(unit, -1, 0);
   3420     }
   3421 
   3422     chunksize = soc_property_get(unit, spn_L2DELETE_CHUNKS,
   3423                                  L2_MEM_CHUNKS_DEFAULT);
   3424 
   3425     index_min = soc_mem_index_min(unit, L2_ENTRY_1m);
   3426     mem_idx_max = soc_mem_index_max(unit, L2_ENTRY_1m); /* Current size */
   3427     mem_size = chunksize * sizeof(l2_entry_1_entry_t);
   3428     
   3429     buffer = soc_cm_salloc(unit, mem_size, "L2_ENTRY_1_delete");
   3430     if (NULL == buffer) {
   3431         return SOC_E_MEMORY;
   3432     }
   3433 
   3434     memacc_valid = _BCM_TR3_L2_MEMACC(unit, L2_ENTRY_1,
   3435                                       _BCM_TR3_L2_MEMACC_VALID);
   3436     memacc_key_type = _BCM_TR3_L2_MEMACC(unit, L2_ENTRY_1,
   3437                                          _BCM_TR3_L2_MEMACC_KEY_TYPE);
   3438 
   3439     soc_mem_lock(unit, L2_ENTRY_1m);
   3440     for (chnk_idx = index_min; chnk_idx <= mem_idx_max; chnk_idx += chunksize) {
   3441         chnk_idx_max = 
   3442             ((chnk_idx + chunksize) < mem_idx_max) ? 
   3443             (chnk_idx + chunksize - 1) : mem_idx_max;
   3444         rv = soc_mem_read_range(unit, L2_ENTRY_1m, MEM_BLOCK_ANY,
   3445                                 chnk_idx, chnk_idx_max, buffer);
   3446         if (SOC_FAILURE(rv)) {
   3447             break;
   3448         }
   3449         chnk_end = (chnk_idx_max - chnk_idx);
   3450         modified = FALSE;
   3451         wide_entry_half = FALSE;
   3452         for (ent_idx = 0 ; ent_idx <= chnk_end; ent_idx ++) {
   3453             l2_entry_1 =
   3454                 soc_mem_table_idx_to_pointer(unit, L2_ENTRY_1m,
   3455                                              l2_entry_1_entry_t *,
   3456                                              buffer, ent_idx);
   3457             if (wide_entry_half) {
   3458                 /* Clear the second half of a wide entry */
   3459                 sal_memcpy(l2_entry_1,
   3460                            soc_mem_entry_null(unit, L2_ENTRY_1m),
   3461                            sizeof(l2_entry_1_entry_t));
   3462                 wide_entry_half = FALSE;
   3463                 continue;
   3464             }
   3465 
   3466             if (!soc_memacc_field32_get(memacc_valid, l2_entry_1)) {
   3467                 continue;
   3468             }
   3469             key_type = soc_memacc_field32_get(memacc_key_type, l2_entry_1);
   3470 
   3471             
   3472             clear_entry = FALSE;
   3473             if ((SOC_MEM_KEY_L2_ENTRY_1_L2_BRIDGE == key_type) ||
   3474                 (SOC_MEM_KEY_L2_ENTRY_1_L2_VFI == key_type)) {
   3475                 clear_entry = TRUE;
   3476             }
   3477             if ((SOC_MEM_KEY_L2_ENTRY_2_L2_BRIDGE == key_type) ||
   3478                 (SOC_MEM_KEY_L2_ENTRY_2_L2_VFI == key_type)) {
   3479                 clear_entry = TRUE;
   3480                 wide_entry_half = TRUE;
   3481             }
   3482             if (clear_entry) {
   3483                 sal_memcpy(l2_entry_1,
   3484                            soc_mem_entry_null(unit, L2_ENTRY_1m),
   3485                            sizeof(l2_entry_1_entry_t));
   3486                 modified = TRUE;
   3487             }
   3488         }
   3489         if (!modified) {
   3490             continue;
   3491         }
   3492         rv = soc_mem_write_range(unit, L2_ENTRY_1m, MEM_BLOCK_ALL,
   3493                                  chnk_idx, chnk_idx_max, buffer);
   3494         if (SOC_FAILURE(rv)) {
   3495             break;
   3496         }
   3497     }
   3498     soc_cm_sfree(unit, buffer);
   3499 
   3500     soc_mem_unlock(unit, L2_ENTRY_1m);
   3501 
   3502     /* External memories don't need key_type checks, so use
   3503      * standard memory clear operation. */
   3504     if (soc_feature(unit, soc_feature_esm_support)) {
   3505         if (BCM_SUCCESS(rv)) {
   3506             rv = soc_mem_clear(unit, EXT_L2_ENTRY_1m, COPYNO_ALL, FALSE);
   3507         }
   3508         if (BCM_SUCCESS(rv)) {
   3509             rv = soc_mem_clear(unit, EXT_L2_ENTRY_2m, COPYNO_ALL, FALSE);
   3510         }
   3511     }
   3512 
   3513     if (SOC_CONTROL(unit)->arlShadow != NULL) {
   3514         sal_mutex_take(SOC_CONTROL(unit)->arlShadowMutex, sal_mutex_FOREVER);
   3515         (void) shr_avl_delete_all(SOC_CONTROL(unit)->arlShadow);
   3516         sal_mutex_give(SOC_CONTROL(unit)->arlShadowMutex);
   3517     }
   3518 
   3519     return rv;
   3520 }
   3521 
   3522 /*
   3523  * Function:
   3524  *      _bcm_tr3_l2_learn_limit_system_set
   3525  * Purpose:
   3526  *      Set MAC learn limit for a system 
   3527  * Parameters:
   3528  *      unit  - BCM unit number
   3529  *      flags - Action bitmask 
   3530  *      limit - System limit of MAC addresses to learn
   3531  *              Negative limit disables the check 
   3532  * Returns:
   3533  *      BCM_E_XXX
   3534  */
   3535 STATIC int
   3536 _bcm_tr3_l2_learn_limit_system_set(int unit, uint32 flags, int limit)
   3537 {
   3538     uint32 rval, orval, regval;
   3539     int tocpu, drop, enable;
   3540     
   3541     if (limit < 0) {
   3542         tocpu = 0;
   3543         drop = 0;
   3544         limit = BCM_MAC_LIMIT_MAX(unit);
   3545         enable = 0;
   3546     } else {
   3547         tocpu = flags & BCM_L2_LEARN_LIMIT_ACTION_CPU ? 1 : 0;
   3548         drop = flags & BCM_L2_LEARN_LIMIT_ACTION_DROP ? 1 : 0;
   3549         enable = 1;
   3550     }
   3551 
   3552     /* Starting from Triumph this flag is not supported */
   3553     if (flags & BCM_L2_LEARN_LIMIT_ACTION_PREFER) {
   3554         return BCM_E_PARAM;
   3555     }
   3556 
   3557     BCM_IF_ERROR_RETURN(READ_RSEL1_MISC_CONTROLr(unit, &regval));
   3558     soc_reg_field_set(unit, RSEL1_MISC_CONTROLr, &regval,
   3559                       MAC_LIMIT_ENABLEf, enable); 
   3560     BCM_IF_ERROR_RETURN(WRITE_RSEL1_MISC_CONTROLr(unit, regval));
   3561 
   3562     BCM_IF_ERROR_RETURN(READ_SYS_MAC_LIMIT_CONTROLr(unit, &rval));
   3563     orval = rval;
   3564     soc_reg_field_set(unit, SYS_MAC_LIMIT_CONTROLr, &rval, 
   3565                       SYS_OVER_LIMIT_TOCPUf, tocpu);
   3566     soc_reg_field_set(unit, SYS_MAC_LIMIT_CONTROLr, &rval,
   3567                       SYS_OVER_LIMIT_DROPf, drop);
   3568     soc_reg_field_set(unit, SYS_MAC_LIMIT_CONTROLr, &rval, SYS_LIMITf, limit);
   3569     /*
   3570      * Enable/Disable MAC limiting for internal L2 and also
   3571      * for external L2 if it is available.
   3572      */
   3573     soc_reg_field_set(unit, SYS_MAC_LIMIT_CONTROLr, &rval, 
   3574                       ENABLE_INTERNAL_L2_ENTRYf, enable);
   3575     if (soc_feature(unit, soc_feature_esm_support)) {
   3576         if ((SOC_MEM_IS_VALID(unit, EXT_L2_ENTRY_1m) &&
   3577              (0 < soc_mem_index_count(unit, EXT_L2_ENTRY_1m))) ||
   3578             ((SOC_MEM_IS_VALID(unit, EXT_L2_ENTRY_2m) &&
   3579              (0 < soc_mem_index_count(unit, EXT_L2_ENTRY_2m))))) {
   3580             soc_reg_field_set(unit, SYS_MAC_LIMIT_CONTROLr, &rval,
   3581                     ENABLE_EXTERNAL_L2_ENTRYf, enable);
   3582         }
   3583     }
   3584     if (rval != orval) {
   3585         BCM_IF_ERROR_RETURN(WRITE_SYS_MAC_LIMIT_CONTROLr(unit, rval));
   3586     }
   3587 
   3588     return BCM_E_NONE;
   3589 }
   3590 
   3591 /*
   3592  * Function:
   3593  *      _bcm_tr3_l2_learn_limit_init
   3594  * Purpose:
   3595  *      Init the system to support MAC learn limit
   3596  * Parameters:
   3597  *      unit  - BCM unit number
   3598  * Returns:
   3599  *      BCM_E_XXX
   3600  */
   3601 STATIC int
   3602 _bcm_tr3_l2_learn_limit_init(int unit)
   3603 {
   3604     int32 maxInitVal;
   3605     int rv, idx, idx_min, idx_max;
   3606     uint8 *port_or_trunk_mac_limit_buf = NULL;
   3607     uint8 *vlan_or_vfi_mac_limit_buf = NULL;
   3608     vlan_or_vfi_mac_limit_entry_t   *vlan_or_vfi_mac_limit_entry = NULL;
   3609     port_or_trunk_mac_limit_entry_t *port_or_trunk_mac_limit_entry = NULL;
   3610     maxInitVal = BCM_MAC_LIMIT_MAX(unit); 
   3611 
   3612     BCM_IF_ERROR_RETURN(_bcm_tr3_l2_learn_limit_system_set(unit, 0, -1));
   3613     BCM_IF_ERROR_RETURN
   3614         (soc_mem_clear(unit, PORT_OR_TRUNK_MAC_LIMITm, COPYNO_ALL, FALSE));
   3615     BCM_IF_ERROR_RETURN
   3616         (soc_mem_clear(unit, VLAN_OR_VFI_MAC_LIMITm, COPYNO_ALL, FALSE));
   3617 
   3618     /* PORT_OR_TRUNK_MAC_LIMIT table*/
   3619     port_or_trunk_mac_limit_buf = soc_cm_salloc(unit,
   3620                    SOC_MEM_TABLE_BYTES(unit,PORT_OR_TRUNK_MAC_LIMITm),
   3621                    "port_or_trunk");
   3622     if (port_or_trunk_mac_limit_buf == NULL) {
   3623         return BCM_E_MEMORY;
   3624     }
   3625 
   3626     idx_min = soc_mem_index_min(unit, PORT_OR_TRUNK_MAC_LIMITm); 
   3627     idx_max = soc_mem_index_max(unit, PORT_OR_TRUNK_MAC_LIMITm);
   3628     rv = soc_mem_read_range(unit, PORT_OR_TRUNK_MAC_LIMITm,
   3629                             MEM_BLOCK_ANY, idx_min, idx_max,
   3630                             port_or_trunk_mac_limit_buf);
   3631     
   3632     if (BCM_FAILURE(rv)) {
   3633         goto cleanup;
   3634     }
   3635 
   3636     for(idx = idx_min; idx<= idx_max; idx++) {
   3637         port_or_trunk_mac_limit_entry = 
   3638             soc_mem_table_idx_to_pointer(unit, PORT_OR_TRUNK_MAC_LIMITm,
   3639                                         port_or_trunk_mac_limit_entry_t *,
   3640                                         port_or_trunk_mac_limit_buf,
   3641                                         idx);
   3642         soc_PORT_OR_TRUNK_MAC_LIMITm_field32_set(unit,
   3643                             port_or_trunk_mac_limit_entry,
   3644                             LIMITf, maxInitVal);
   3645     }
   3646     rv = soc_mem_write_range(unit, PORT_OR_TRUNK_MAC_LIMITm, MEM_BLOCK_ALL,
   3647                              idx_min, idx_max, port_or_trunk_mac_limit_buf);
   3648     if (BCM_FAILURE(rv)) {
   3649         goto cleanup;
   3650     }
   3651         
   3652     /* VLAN_OR_VFI_MAC_LIMIT table*/
   3653     vlan_or_vfi_mac_limit_buf = soc_cm_salloc(unit,
   3654                    SOC_MEM_TABLE_BYTES(unit, VLAN_OR_VFI_MAC_LIMITm),
   3655                    "vlan_or_vfi");
   3656     if (vlan_or_vfi_mac_limit_buf == NULL) {
   3657         return BCM_E_MEMORY;
   3658     }
   3659        
   3660     idx_min = soc_mem_index_min(unit, VLAN_OR_VFI_MAC_LIMITm); 
   3661     idx_max = soc_mem_index_max(unit, VLAN_OR_VFI_MAC_LIMITm);
   3662     rv = soc_mem_read_range(unit, VLAN_OR_VFI_MAC_LIMITm,
   3663                             MEM_BLOCK_ANY, idx_min, idx_max,
   3664                             vlan_or_vfi_mac_limit_buf);
   3665     
   3666     if (BCM_FAILURE(rv)) {
   3667         goto cleanup;
   3668     }
   3669 
   3670     for(idx = idx_min; idx<= idx_max; idx++) {
   3671         vlan_or_vfi_mac_limit_entry = 
   3672             soc_mem_table_idx_to_pointer(unit, VLAN_OR_VFI_MAC_LIMITm,
   3673                                         vlan_or_vfi_mac_limit_entry_t *,
   3674                                         vlan_or_vfi_mac_limit_buf,
   3675                                         idx);
   3676         soc_PORT_OR_TRUNK_MAC_LIMITm_field32_set(unit,
   3677                             vlan_or_vfi_mac_limit_entry,
   3678                             LIMITf, maxInitVal);
   3679     }
   3680     rv = soc_mem_write_range(unit, VLAN_OR_VFI_MAC_LIMITm, MEM_BLOCK_ALL,
   3681                              idx_min, idx_max, vlan_or_vfi_mac_limit_buf);
   3682     if (BCM_FAILURE(rv)) {
   3683         goto cleanup;
   3684     }
   3685         
   3686 
   3687 cleanup:
   3688 
   3689     if (port_or_trunk_mac_limit_buf) {
   3690         soc_cm_sfree(unit, port_or_trunk_mac_limit_buf);
   3691     }
   3692 
   3693     if (vlan_or_vfi_mac_limit_buf) {
   3694         soc_cm_sfree(unit, vlan_or_vfi_mac_limit_buf);
   3695     }
   3696 
   3697     return rv;
   3698 }
   3699 
   3700 /*
   3701  * Function:
   3702  *      _bcm_tr3_l2_hash_dynamic_replace
   3703  * Purpose:
   3704  *      Given an L2 entries structure, search for dynamic entries to
   3705  *      eject in favor of the new entry.
   3706  * Parameters:
   3707  *      unit - (IN) Unit number.
   3708  *      l2_entries  (IN/OUT) Triumph3 L2 entries structure
   3709  * Returns:
   3710  *      BCM_E_xxx
   3711  * Notes:
   3712  *      In case new entry is double wide,we check for any dynamic narrow entries
   3713  *      which can be deleted or free, and then do an insert. del_low_idx and
   3714  *      del_high_idx are set if the entry is not free and has to be deleted
   3715  *      before insert.
   3716  */
   3717 int 
   3718 _bcm_tr3_l2_hash_dynamic_replace(int unit, _bcm_tr3_l2_entries_t *l2_entries)
   3719 {
   3720     uint32 *kt, valid;
   3721     void *entry;
   3722     int rv, rvt, base_index, l2_index=0, skip_entry;
   3723     int cf_hit, cf_unhit, narrow_avail = 0;
   3724     int del_low_idx = 0, del_high_idx = 0;
   3725     soc_mem_t mem;
   3726     soc_field_t ktf;
   3727     uint8 i, bidx, num_ent;
   3728     _soc_ism_mem_banks_t mem_banks;
   3729     soc_memacc_t *memacc;
   3730     bcm_mac_t mac;
   3731     uint32 l2_entry[SOC_MAX_MEM_WORDS], result, bucket_index;
   3732     uint32 key_type_1[] = {SOC_MEM_KEY_L2_ENTRY_1_L2_BRIDGE,
   3733                            SOC_MEM_KEY_L2_ENTRY_1_L2_VFI};
   3734     uint32 key_type_2[] = {SOC_MEM_KEY_L2_ENTRY_2_L2_BRIDGE,
   3735                            SOC_MEM_KEY_L2_ENTRY_2_L2_VFI};
   3736     int index_cache[_SOC_ISM_MAX_BANKS] = {-1};
   3737     
   3738     /* NOTE: Implementation assumes that enough criteria/info will be set 
   3739              in the bcm_l2_addr_t param to not have any ambiguity between
   3740              ENTRY_1 and ENTRY_2, i.e the following conditions would not
   3741              be true together */ 
   3742     if (l2_entries->entry_flags & _BCM_TR3_L2_SELECT_L2_ENTRY_1) {
   3743         mem = L2_ENTRY_1m;
   3744         entry = &l2_entries->l2_entry_1;
   3745         kt = key_type_1;
   3746         valid = VALIDf;
   3747         ktf = KEY_TYPEf;
   3748     } else if (l2_entries->entry_flags & _BCM_TR3_L2_SELECT_L2_ENTRY_2) {
   3749         mem = L2_ENTRY_2m;
   3750         entry = &l2_entries->l2_entry_2;
   3751         kt = key_type_2;
   3752         valid = VALID_0f;
   3753         ktf = KEY_TYPE_0f;
   3754     } else {
   3755         return BCM_E_PARAM;
   3756     }
   3757     rv = soc_ism_get_banks_for_mem(unit, mem, mem_banks.banks, 
   3758                                    mem_banks.bank_size, &mem_banks.count);
   3759     if (SOC_FAILURE(rv)) {
   3760         return BCM_E_INTERNAL;
   3761     }
   3762     if (mem_banks.count == 0) {
   3763         return BCM_E_NOT_FOUND;
   3764     }
   3765 
   3766     /* Don't let the table rearrange in the background */
   3767     BCM_IF_ERROR_RETURN(soc_l2x_freeze(unit));
   3768 
   3769     cf_hit = cf_unhit = -1;
   3770     SOC_L2X_MEM_LOCK(unit);
   3771     for (bidx = 0; bidx < mem_banks.count; bidx++) {
   3772         /* base index depends on the view, L2_ENTRY_1 or L2_ENTRY_2 */ 
   3773         rv = soc_generic_hash(unit, mem, entry,
   3774                               (uint32)1 << mem_banks.banks[bidx],
   3775                               0, &base_index, &result,
   3776                               &bucket_index, &num_ent);
   3777         if (SOC_FAILURE(rv)) {
   3778             rv = BCM_E_INTERNAL;
   3779             break;
   3780         }
   3781         /* Cache indexes for later use, based on the newer entry type*/
   3782         index_cache[bidx] = base_index;
   3783         for (i = 0; i < num_ent; i++ ) {
   3784             skip_entry = FALSE;
   3785             l2_index = base_index + i;
   3786             rv = soc_mem_read(unit, mem, COPYNO_ALL, l2_index, l2_entry);
   3787             if (SOC_FAILURE(rv)) {
   3788                 rv = BCM_E_MEMORY;
   3789                 break;
   3790             }
   3791             if (!soc_mem_field32_get(unit, mem, &l2_entry, valid)) {
   3792                 if (mem == L2_ENTRY_2m) {
   3793                     soc_mem_t mem1 = L2_ENTRY_1m;
   3794                     rv = soc_mem_read(unit, mem1, COPYNO_ALL,
   3795                                       (2 * l2_index) + 1, l2_entry);
   3796                     if (SOC_FAILURE(rv)) {
   3797                         rv = BCM_E_MEMORY;
   3798                         break;
   3799                     }
   3800                     if (soc_mem_field32_get(unit, mem1, &l2_entry, VALIDf)) {
   3801                         continue;
   3802                     }
   3803                 }
   3804                 /* Found invalid entry - stop the search, victim found */
   3805                 cf_unhit = l2_index; 
   3806                 break;
   3807             }
   3808             /* Check if the newer entry and existing entry belong to the same 
   3809                memory view */
   3810             if (((soc_mem_field32_get(unit, mem, &l2_entry, ktf) == kt[0]) ||
   3811                  (soc_mem_field32_get(unit, mem, &l2_entry, ktf) == kt[1]))) {
   3812                 if (mem == L2_ENTRY_1m) {
   3813                     if (_BCM_TR3_L2_1_FIELD32_MEMACC_GET(unit, l2_entry,
   3814                                                          STATIC_BIT)) {
   3815                         /* Skip static entries */
   3816                         skip_entry = TRUE;
   3817                     }
   3818                     if (!skip_entry) {
   3819                         memacc = _BCM_TR3_L2_MEMACC(unit, L2_ENTRY_1,
   3820                                           _BCM_TR3_L2_MEMACC_MAC_ADDR);
   3821                         soc_memacc_mac_addr_get(memacc, l2_entry, mac);
   3822                         if (BCM_MAC_IS_MCAST(mac)) {
   3823                             skip_entry = TRUE;
   3824                         }
   3825                     }
   3826                     if (!skip_entry) {
   3827                         if (_BCM_TR3_L2_1_FIELD32_MEMACC_GET(unit, l2_entry,
   3828                                                              HITDA) ||
   3829                             _BCM_TR3_L2_1_FIELD32_MEMACC_GET(unit, l2_entry,
   3830                                                              HITSA)) {
   3831                             cf_hit =  l2_index;
   3832                         } else {
   3833                             /* Found unhit entry -
   3834                              * stop search, victim found */
   3835                             cf_unhit = l2_index;
   3836                             break;
   3837                         }
   3838                     }
   3839                 } else {
   3840                     if (_BCM_TR3_L2_2_FIELD32_MEMACC_GET(unit, l2_entry,
   3841                                                          STATIC_BIT)) {
   3842                         /* Skip static entries */
   3843                         skip_entry = TRUE;
   3844                     }
   3845                     if (!skip_entry) {
   3846                         memacc = _BCM_TR3_L2_MEMACC(unit, L2_ENTRY_2,
   3847                                           _BCM_TR3_L2_MEMACC_MAC_ADDR);
   3848                         soc_memacc_mac_addr_get(memacc, l2_entry, mac);
   3849                         if (BCM_MAC_IS_MCAST(mac)) {
   3850                             skip_entry = TRUE;
   3851                         }
   3852                     }
   3853                     if (!skip_entry) {
   3854                         if (_BCM_TR3_L2_2_FIELD32_MEMACC_GET(unit, l2_entry,
   3855                                                              HITDA) ||
   3856                             _BCM_TR3_L2_2_FIELD32_MEMACC_GET(unit, l2_entry,
   3857                                                              HITSA)) {
   3858                             cf_hit = l2_index;
   3859                         } else {
   3860                             /* Found unhit entry -
   3861                              * stop search, victim found */
   3862                             cf_unhit = l2_index;
   3863                             break;
   3864                         }
   3865                     }
   3866                 }
   3867             }
   3868         }
   3869         if (SOC_FAILURE(rv) || (cf_unhit >= 0)) {
   3870             break;
   3871         }
   3872     }
   3873     
   3874     if ((cf_unhit >= 0) || (cf_hit >= 0)) {
   3875         /* Prefer unhit entries over hit entries */
   3876         l2_index = (cf_unhit >= 0)? cf_unhit : cf_hit;
   3877         rv = soc_mem_delete_index(unit, mem, MEM_BLOCK_ALL, 
   3878                                                  l2_index);
   3879     } else {
   3880         if (mem == L2_ENTRY_2m) {
   3881             soc_mem_t mem1 = L2_ENTRY_1m;
   3882             
   3883             /* Try replacing 2 consecutive narrow entries with one wide */
   3884             kt = key_type_1;
   3885             for (bidx = 0; bidx < mem_banks.count; bidx++) {
   3886                 for (i = 0; i < 2; i++) {
   3887                     narrow_avail = 0;
   3888                     del_low_idx  = 0;
   3889                     del_high_idx = 0;
   3890                     /* We cached the wide entry index pre-emptively */
   3891                     l2_index = index_cache[bidx]*2 + i*2;
   3892                     rv = soc_mem_read(unit, mem1, COPYNO_ALL, l2_index, l2_entry);
   3893                     if (SOC_FAILURE(rv)) {
   3894                         rv = BCM_E_MEMORY;
   3895                         break;
   3896                     }
   3897                     if (!soc_mem_field32_get(unit, mem1, &l2_entry, VALIDf)) {
   3898                         /* Found one invalid entry */
   3899                         narrow_avail++;
   3900                     } else if (((soc_mem_field32_get(unit, mem1, &l2_entry,
   3901                                                      KEY_TYPEf) == kt[0]) ||
   3902                                 (soc_mem_field32_get(unit, mem1, &l2_entry,
   3903                                                      KEY_TYPEf) == kt[1]))) {
   3904                         if (_BCM_TR3_L2_1_FIELD32_MEMACC_GET(unit, l2_entry,
   3905                                                              STATIC_BIT)) {
   3906                             /* Skip static entries */
   3907                             continue;
   3908                         } else {
   3909                             memacc = _BCM_TR3_L2_MEMACC(unit, L2_ENTRY_1,
   3910                                               _BCM_TR3_L2_MEMACC_MAC_ADDR);
   3911                             soc_memacc_mac_addr_get(memacc, l2_entry, mac);
   3912                             if (BCM_MAC_IS_MCAST(mac)) {
   3913                                 continue;
   3914                             }
   3915                         }
   3916                         narrow_avail++;
   3917                         del_low_idx = 1;
   3918                     }
   3919                     /* narrow_avail should be one */ 
   3920                     l2_index++;
   3921                     rv = soc_mem_read(unit, mem1, COPYNO_ALL, l2_index, l2_entry);
   3922                     if (SOC_FAILURE(rv)) {
   3923                         rv = BCM_E_MEMORY;
   3924                         break;
   3925                     }
   3926                     if (!soc_mem_field32_get(unit, mem1, &l2_entry, VALIDf)) {
   3927                         /* Found two invalid entry */
   3928                         narrow_avail++;
   3929                         break;
   3930                     } else if (((soc_mem_field32_get(unit, mem1, &l2_entry,
   3931                                                      KEY_TYPEf) == kt[0]) ||
   3932                                 (soc_mem_field32_get(unit, mem1, &l2_entry,
   3933                                                      KEY_TYPEf) == kt[1]))) {
   3934                         if (_BCM_TR3_L2_1_FIELD32_MEMACC_GET(unit, l2_entry,
   3935                                                              STATIC_BIT)) {
   3936                             /* Skip static entries */
   3937                             continue;
   3938                         } else {
   3939                             memacc = _BCM_TR3_L2_MEMACC(unit, L2_ENTRY_1,
   3940                                               _BCM_TR3_L2_MEMACC_MAC_ADDR);
   3941                             soc_memacc_mac_addr_get(memacc, l2_entry, mac);
   3942                             if (BCM_MAC_IS_MCAST(mac)) {
   3943                                 continue;
   3944                             }
   3945                         }
   3946                         narrow_avail++;
   3947                         del_high_idx = 1;
   3948                         break;
   3949                     }
   3950                 }
   3951                 if (SOC_FAILURE(rv)) {
   3952                     break;
   3953                 }
   3954                 if (narrow_avail == 2) {
   3955                     if (del_low_idx) {
   3956                         rv = soc_mem_delete_index(unit, mem1, MEM_BLOCK_ALL, l2_index-1);
   3957                         if (SOC_FAILURE(rv)) {
   3958                             rv = BCM_E_MEMORY;
   3959                             break;
   3960                         }
   3961                     }
   3962                     if (del_high_idx) {
   3963                         rv = soc_mem_delete_index(unit, mem1, MEM_BLOCK_ALL, l2_index);
   3964                         if (SOC_FAILURE(rv)) {
   3965                             rv = BCM_E_MEMORY;
   3966                             break;
   3967                         }   
   3968                     }
   3969                     /* Get the cached wide entry index */
   3970                     l2_index = index_cache[bidx] + i;
   3971                     break;
   3972                 }
   3973             }
   3974             /* we may endup here when first entry is invalid and 
   3975                second one is static */
   3976             if (SOC_FAILURE(rv) || (narrow_avail < 2)) {
   3977                 /* coverity[value_overwrite] */
   3978                 l2_index = 0; /* Never used, but stops compiler uninit complaint */
   3979                 rv = BCM_E_FULL;     /* no dynamics to delete */
   3980             }
   3981         } else {
   3982             /* Try to find a wide entry and replace with a narrow one */
   3983             soc_mem_t mem1 = L2_ENTRY_2m;
   3984             kt = key_type_2;
   3985             for (bidx = 0; bidx < mem_banks.count; bidx++) {
   3986                 for (i = 0; i < 2; i++) {
   3987                     l2_index = index_cache[bidx]/2 + i;
   3988                     rv = soc_mem_read(unit, mem1, COPYNO_ALL, l2_index, l2_entry);  
   3989                     if (SOC_FAILURE(rv)) {
   3990                         rv = BCM_E_MEMORY;
   3991                         break;
   3992                     }
   3993                     if ((soc_mem_field32_get(unit, mem, &l2_entry, ktf) == kt[0]) ||
   3994                          (soc_mem_field32_get(unit, mem, &l2_entry, ktf) == kt[1])) {
   3995                         if (_BCM_TR3_L2_2_FIELD32_MEMACC_GET(unit, l2_entry,
   3996                                                                      STATIC_BIT)) {
   3997                             continue;
   3998                         }
   3999                         memacc = _BCM_TR3_L2_MEMACC(unit, L2_ENTRY_2,
   4000                                                       _BCM_TR3_L2_MEMACC_MAC_ADDR);
   4001                         soc_memacc_mac_addr_get(memacc, l2_entry, mac);
   4002                         if (BCM_MAC_IS_MCAST(mac)) {
   4003                             continue;
   4004                         }
   4005                         if (_BCM_TR3_L2_2_FIELD32_MEMACC_GET(unit, l2_entry, HITDA) ||
   4006                             _BCM_TR3_L2_2_FIELD32_MEMACC_GET(unit, l2_entry, HITSA)) {
   4007                              cf_hit = l2_index;
   4008                         } else {
   4009                             /* Found unhit entry -
   4010                              * stop search, victim found */
   4011                              cf_unhit = l2_index;
   4012                              break;
   4013                         }
   4014                     }
   4015                 }
   4016                 if (cf_unhit < 0) {
   4017                     if (cf_hit >= 0) {
   4018                         l2_index = cf_hit;
   4019                     } else {
   4020                        rv = BCM_E_FULL;    
   4021                     }
   4022                 }
   4023             }
   4024             if (SOC_SUCCESS(rv)) {
   4025                 rv = soc_mem_delete_index(unit, mem1, MEM_BLOCK_ALL, l2_index);
   4026            }
   4027         }
   4028     }
   4029     if (SOC_SUCCESS(rv)) {
   4030         rv = soc_mem_insert(unit, mem, MEM_BLOCK_ALL, entry);
   4031     }
   4032     SOC_L2X_MEM_UNLOCK(unit);
   4033     rvt = soc_l2x_thaw(unit);
   4034     return SOC_FAILURE(rv) ? rv : rvt;
   4035 }
   4036 
   4037 /*
   4038  * Function:
   4039  *      _bcm_tr3_l2_hash_pending_override
   4040  * Purpose:
   4041  *      Given an L2 entries structure, search for pending entries to
   4042  *      eject in favor of the new entry.
   4043  * Parameters:
   4044  *      unit - (IN) Unit number.
   4045  *      l2_entries  (IN/OUT) Triumph3 L2 entries structure
   4046  * Returns:
   4047  *      BCM_E_xxx
   4048  * Notes:
   4049  *      In case new entry is double wide,we check for any pending narrow entries
   4050  *      which can be deleted or free, and then do an insert. del_low_idx and
   4051  *      del_high_idx are set if the entry is not free and has to be deleted
   4052  *      before insert.
   4053  */
   4054 int
   4055 _bcm_tr3_l2_hash_pending_override(int unit, _bcm_tr3_l2_entries_t *l2_entries)
   4056 {
   4057     uint32 *kt, valid;
   4058     void *entry;
   4059     int rv, rvt, base_index, l2_index=0, skip_entry;
   4060     int p_hit, narrow_avail = 0;
   4061     int del_low_idx = 0, del_high_idx = 0;
   4062     soc_mem_t mem;
   4063     soc_field_t ktf;
   4064     uint8 i, bidx, num_ent;
   4065     _soc_ism_mem_banks_t mem_banks;
   4066     soc_memacc_t *memacc;
   4067     bcm_mac_t mac;
   4068     uint32 l2_entry[SOC_MAX_MEM_WORDS], result, bucket_index;
   4069     uint32 key_type_1[] = {SOC_MEM_KEY_L2_ENTRY_1_L2_BRIDGE,
   4070                            SOC_MEM_KEY_L2_ENTRY_1_L2_VFI};
   4071     uint32 key_type_2[] = {SOC_MEM_KEY_L2_ENTRY_2_L2_BRIDGE,
   4072                            SOC_MEM_KEY_L2_ENTRY_2_L2_VFI};
   4073     int index_cache[_SOC_ISM_MAX_BANKS] = {-1};
   4074 
   4075     /* NOTE: Implementation assumes that enough criteria/info will be set
   4076              in the bcm_l2_addr_t param to not have any ambiguity between
   4077              ENTRY_1 and ENTRY_2, i.e the following conditions would not
   4078              be true together */
   4079     if (l2_entries->entry_flags & _BCM_TR3_L2_SELECT_L2_ENTRY_1) {
   4080         mem = L2_ENTRY_1m;
   4081         entry = &l2_entries->l2_entry_1;
   4082         kt = key_type_1;
   4083         valid = VALIDf;
   4084         ktf = KEY_TYPEf;
   4085     } else if (l2_entries->entry_flags & _BCM_TR3_L2_SELECT_L2_ENTRY_2) {
   4086         mem = L2_ENTRY_2m;
   4087         entry = &l2_entries->l2_entry_2;
   4088         kt = key_type_2;
   4089         valid = VALID_0f;
   4090         ktf = KEY_TYPE_0f;
   4091     } else {
   4092         return BCM_E_PARAM;
   4093     }
   4094     rv = soc_ism_get_banks_for_mem(unit, mem, mem_banks.banks,
   4095                                    mem_banks.bank_size, &mem_banks.count);
   4096     if (SOC_FAILURE(rv)) {
   4097         return BCM_E_INTERNAL;
   4098     }
   4099     if (mem_banks.count == 0) {
   4100         return BCM_E_NOT_FOUND;
   4101     }
   4102 
   4103     /* Don't let the table rearrange in the background */
   4104     BCM_IF_ERROR_RETURN(soc_l2x_freeze(unit));
   4105 
   4106     p_hit = -1;
   4107     SOC_L2X_MEM_LOCK(unit);
   4108     for (bidx = 0; bidx < mem_banks.count; bidx++) {
   4109         /* base index depends on the view, L2_ENTRY_1 or L2_ENTRY_2 */
   4110         rv = soc_generic_hash(unit, mem, entry,
   4111                               (uint32)1 << mem_banks.banks[bidx],
   4112                               0, &base_index, &result,
   4113                               &bucket_index, &num_ent);
   4114         if (SOC_FAILURE(rv)) {
   4115             rv = BCM_E_INTERNAL;
   4116             break;
   4117         }
   4118         /* Cache indexes for later use, based on the newer entry type*/
   4119         index_cache[bidx] = base_index;
   4120         for (i = 0; i < num_ent; i++ ) {
   4121             skip_entry = FALSE;
   4122             l2_index = base_index + i;
   4123             rv = soc_mem_read(unit, mem, COPYNO_ALL, l2_index, l2_entry);
   4124             if (SOC_FAILURE(rv)) {
   4125                 rv = BCM_E_MEMORY;
   4126                 break;
   4127             }
   4128             if (!soc_mem_field32_get(unit, mem, &l2_entry, valid)) {
   4129                 if (mem == L2_ENTRY_2m) {
   4130                     soc_mem_t mem1 = L2_ENTRY_1m;
   4131                     rv = soc_mem_read(unit, mem1, COPYNO_ALL,
   4132                                       (2 * l2_index) + 1, l2_entry);
   4133                     if (SOC_FAILURE(rv)) {
   4134                         rv = BCM_E_MEMORY;
   4135                         break;
   4136                     }
   4137                     if (soc_mem_field32_get(unit, mem1, &l2_entry, VALIDf)) {
   4138                         continue;
   4139                     }
   4140                 }
   4141                 /* Found invalid entry - stop the search, victim found */
   4142                 p_hit = l2_index;
   4143                 break;
   4144             }
   4145             /* Check if the newer entry and existing entry belong to the same
   4146                memory view */
   4147             if (((soc_mem_field32_get(unit, mem, &l2_entry, ktf) == kt[0]) ||
   4148                  (soc_mem_field32_get(unit, mem, &l2_entry, ktf) == kt[1]))) {
   4149                 if (mem == L2_ENTRY_1m) {
   4150                     if (_BCM_TR3_L2_1_FIELD32_MEMACC_GET(unit, l2_entry,
   4151                                                          STATIC_BIT)) {
   4152                         /* Skip static entries */
   4153                         skip_entry = TRUE;
   4154                     }
   4155                     if (!skip_entry) {
   4156                         memacc = _BCM_TR3_L2_MEMACC(unit, L2_ENTRY_1,
   4157                                           _BCM_TR3_L2_MEMACC_MAC_ADDR);
   4158                         soc_memacc_mac_addr_get(memacc, l2_entry, mac);
   4159                         if (BCM_MAC_IS_MCAST(mac)) {
   4160                             skip_entry = TRUE;
   4161                         }
   4162                     }
   4163                     if (!skip_entry) {
   4164                         if (_BCM_TR3_L2_1_FIELD32_MEMACC_GET(unit, l2_entry,
   4165                                     PENDING)) {
   4166                             p_hit = l2_index;
   4167                             break;
   4168                         }
   4169                     }
   4170                 } else {
   4171                     if (_BCM_TR3_L2_2_FIELD32_MEMACC_GET(unit, l2_entry,
   4172                                                          STATIC_BIT)) {
   4173                         /* Skip static entries */
   4174                         skip_entry = TRUE;
   4175                     }
   4176                     if (!skip_entry) {
   4177                         memacc = _BCM_TR3_L2_MEMACC(unit, L2_ENTRY_2,
   4178                                           _BCM_TR3_L2_MEMACC_MAC_ADDR);
   4179                         soc_memacc_mac_addr_get(memacc, l2_entry, mac);
   4180                         if (BCM_MAC_IS_MCAST(mac)) {
   4181                             skip_entry = TRUE;
   4182                         }
   4183                     }
   4184                     if (!skip_entry) {
   4185                         if (_BCM_TR3_L2_2_FIELD32_MEMACC_GET(unit, l2_entry,
   4186                                                              PENDING)) {
   4187                             p_hit = l2_index;
   4188                             break;
   4189                         }
   4190                     }
   4191                 }
   4192             }
   4193         }
   4194         if (SOC_FAILURE(rv) || (p_hit >= 0)) {
   4195             break;
   4196         }
   4197     }
   4198 
   4199     if (p_hit >= 0) {
   4200         l2_index = p_hit;
   4201         rv = soc_mem_delete_index(unit, mem, MEM_BLOCK_ALL,
   4202                                                  l2_index);
   4203     } else {
   4204         if (mem == L2_ENTRY_2m) {
   4205             soc_mem_t mem1 = L2_ENTRY_1m;
   4206 
   4207             /* Try replacing 2 consecutive narrow entries with one wide */
   4208             kt = key_type_1;
   4209             for (bidx = 0; bidx < mem_banks.count; bidx++) {
   4210                 for (i = 0; i < 2; i++) {
   4211                     narrow_avail = 0;
   4212                     del_low_idx  = 0;
   4213                     del_high_idx = 0;
   4214                     /* We cached the wide entry index pre-emptively */
   4215                     l2_index = index_cache[bidx]*2 + i*2;
   4216                     rv = soc_mem_read(unit, mem1, COPYNO_ALL, l2_index, l2_entry);
   4217                     if (SOC_FAILURE(rv)) {
   4218                         rv = BCM_E_MEMORY;
   4219                         break;
   4220                     }
   4221                     if (!soc_mem_field32_get(unit, mem1, &l2_entry, VALIDf)) {
   4222                         /* Found one invalid entry */
   4223                         narrow_avail++;
   4224                     } else if (((soc_mem_field32_get(unit, mem1, &l2_entry,
   4225                                                      KEY_TYPEf) == kt[0]) ||
   4226                                 (soc_mem_field32_get(unit, mem1, &l2_entry,
   4227                                                      KEY_TYPEf) == kt[1]))) {
   4228                         if (_BCM_TR3_L2_1_FIELD32_MEMACC_GET(unit, l2_entry,
   4229                                                              STATIC_BIT)) {
   4230                             /* Skip static entries */
   4231                             continue;
   4232                         } else {
   4233                             memacc = _BCM_TR3_L2_MEMACC(unit, L2_ENTRY_1,
   4234                                               _BCM_TR3_L2_MEMACC_MAC_ADDR);
   4235                             soc_memacc_mac_addr_get(memacc, l2_entry, mac);
   4236                             if (BCM_MAC_IS_MCAST(mac)) {
   4237                                 continue;
   4238                             }
   4239                         }
   4240                         narrow_avail++;
   4241                         del_low_idx = 1;
   4242                     }
   4243                     /* narrow_avail should be one */
   4244                     l2_index++;
   4245                     rv = soc_mem_read(unit, mem1, COPYNO_ALL, l2_index, l2_entry);
   4246                     if (SOC_FAILURE(rv)) {
   4247                         rv = BCM_E_MEMORY;
   4248                         break;
   4249                     }
   4250                     if (!soc_mem_field32_get(unit, mem1, &l2_entry, VALIDf)) {
   4251                         /* Found two invalid entry */
   4252                         narrow_avail++;
   4253                         break;
   4254                     } else if (((soc_mem_field32_get(unit, mem1, &l2_entry,
   4255                                                      KEY_TYPEf) == kt[0]) ||
   4256                                 (soc_mem_field32_get(unit, mem1, &l2_entry,
   4257                                                      KEY_TYPEf) == kt[1]))) {
   4258                         if (_BCM_TR3_L2_1_FIELD32_MEMACC_GET(unit, l2_entry,
   4259                                                              STATIC_BIT)) {
   4260                             /* Skip static entries */
   4261                             continue;
   4262                         } else {
   4263                             memacc = _BCM_TR3_L2_MEMACC(unit, L2_ENTRY_1,
   4264                                               _BCM_TR3_L2_MEMACC_MAC_ADDR);
   4265                             soc_memacc_mac_addr_get(memacc, l2_entry, mac);
   4266                             if (BCM_MAC_IS_MCAST(mac)) {
   4267                                 continue;
   4268                             }
   4269                         }
   4270                         narrow_avail++;
   4271                         del_high_idx = 1;
   4272                         break;
   4273                     }
   4274                 }
   4275                 if (SOC_FAILURE(rv)) {
   4276                     break;
   4277                 }
   4278                 if (narrow_avail == 2) {
   4279                     if (del_low_idx) {
   4280                         rv = soc_mem_delete_index(unit, mem1, MEM_BLOCK_ALL, l2_index-1);
   4281                         if (SOC_FAILURE(rv)) {
   4282                             rv = BCM_E_MEMORY;
   4283                             break;
   4284                         }
   4285                     }
   4286                     if (del_high_idx) {
   4287                         rv = soc_mem_delete_index(unit, mem1, MEM_BLOCK_ALL, l2_index);
   4288                         if (SOC_FAILURE(rv)) {
   4289                             rv = BCM_E_MEMORY;
   4290                             break;
   4291                         }
   4292                     }
   4293                     /* Get the cached wide entry index */
   4294                     l2_index = index_cache[bidx] + i;
   4295                     break;
   4296                 }
   4297             }
   4298             /* we may endup here when first entry is invalid and
   4299                second one is static */
   4300             if (SOC_FAILURE(rv) || (narrow_avail < 2)) {
   4301                 /* coverity[value_overwrite] */
   4302                 l2_index = 0; /* Never used, but stops compiler uninit complaint */
   4303                 rv = BCM_E_FULL;     /* no dynamics to delete */
   4304             }
   4305         } else {
   4306             /* Try to find a wide entry and replace with a narrow one */
   4307             soc_mem_t mem1 = L2_ENTRY_2m;
   4308             kt = key_type_2;
   4309             for (bidx = 0; bidx < mem_banks.count; bidx++) {
   4310                 for (i = 0; i < 2; i++) {
   4311                     l2_index = index_cache[bidx]/2 + i;
   4312                     rv = soc_mem_read(unit, mem1, COPYNO_ALL, l2_index, l2_entry);
   4313                     if (SOC_FAILURE(rv)) {
   4314                         rv = BCM_E_MEMORY;
   4315                         break;
   4316                     }
   4317                     if ((soc_mem_field32_get(unit, mem, &l2_entry, ktf) == kt[0]) ||
   4318                          (soc_mem_field32_get(unit, mem, &l2_entry, ktf) == kt[1])) {
   4319                         if (_BCM_TR3_L2_2_FIELD32_MEMACC_GET(unit, l2_entry,
   4320                                                                      STATIC_BIT)) {
   4321                             continue;
   4322                         }
   4323                         memacc = _BCM_TR3_L2_MEMACC(unit, L2_ENTRY_2,
   4324                                                       _BCM_TR3_L2_MEMACC_MAC_ADDR);
   4325                         soc_memacc_mac_addr_get(memacc, l2_entry, mac);
   4326                         if (BCM_MAC_IS_MCAST(mac)) {
   4327                             continue;
   4328                         }
   4329                         if (_BCM_TR3_L2_2_FIELD32_MEMACC_GET(unit, l2_entry, PENDING)) {
   4330                              p_hit = l2_index;
   4331                              break;
   4332                         }
   4333                     }
   4334                 }
   4335                 if (p_hit >= 0) {
   4336                     l2_index = p_hit;
   4337                 } else {
   4338                     rv = BCM_E_FULL;
   4339                 }
   4340             }
   4341             if (SOC_SUCCESS(rv)) {
   4342                 rv = soc_mem_delete_index(unit, mem1, MEM_BLOCK_ALL, l2_index);
   4343            }
   4344         }
   4345     }
   4346     if (SOC_SUCCESS(rv)) {
   4347         rv = soc_mem_insert(unit, mem, MEM_BLOCK_ALL, entry);
   4348     }
   4349     SOC_L2X_MEM_UNLOCK(unit);
   4350     rvt = soc_l2x_thaw(unit);
   4351     return SOC_FAILURE(rv) ? rv : rvt;
   4352 }
   4353 
   4354 /****************************************************************************
   4355  *
   4356  * L2 Callbacks Registration
   4357  */
   4358 static bcm_l2_addr_callback_t _bcm_tr3_l2_cbs[SOC_MAX_NUM_DEVICES];
   4359 static void *_bcm_tr3_l2_cb_data[SOC_MAX_NUM_DEVICES];
   4360 
   4361 void
   4362 _bcm_tr3_l2_register_callback(int unit, uint32 flags,
   4363                               soc_mem_t mem_type,
   4364                               l2_combo_entry_t *entry_del,
   4365                               l2_combo_entry_t *entry_add,
   4366                               void *fn_data)
   4367 {
   4368     if (_bcm_tr3_l2_cbs[unit] != NULL) {
   4369         bcm_l2_addr_t l2addr_del, l2addr_add;
   4370         uint32 set_flags = 0; /* Common flags: Move, From/to native */
   4371         _bcm_tr3_l2_entries_t l2_entries;
   4372 
   4373         /* First, set up the entries:  decode HW entries and set flags */
   4374         if (entry_del != NULL) {
   4375             l2_entries.entry_flags = 0;
   4376             switch (mem_type) {
   4377             case L2_ENTRY_1m:
   4378                 sal_memcpy(&l2_entries.l2_entry_1, entry_del, 
   4379                            sizeof(l2_entry_1_entry_t));
   4380                 l2_entries.entry_flags |= _BCM_TR3_L2_SELECT_L2_ENTRY_1;
   4381                 break;
   4382             case L2_ENTRY_2m:
   4383                 sal_memcpy(&l2_entries.l2_entry_2, entry_del, 
   4384                            sizeof(l2_entry_2_entry_t));
   4385                 l2_entries.entry_flags |= _BCM_TR3_L2_SELECT_L2_ENTRY_2;
   4386                 break;
   4387             case EXT_L2_ENTRY_1m:
   4388                 sal_memcpy(&l2_entries.ext_l2_entry_1, entry_del, 
   4389                            sizeof(ext_l2_entry_1_entry_t));
   4390                 l2_entries.entry_flags |= _BCM_TR3_L2_SELECT_EXT_L2_ENTRY_1;
   4391                 break;
   4392             case EXT_L2_ENTRY_2m:
   4393                 sal_memcpy(&l2_entries.ext_l2_entry_2, entry_del, 
   4394                            sizeof(ext_l2_entry_2_entry_t));
   4395                 l2_entries.entry_flags |= _BCM_TR3_L2_SELECT_EXT_L2_ENTRY_2;
   4396                 break;
   4397             default: assert(0);
   4398             }
   4399             (void)_bcm_tr3_l2api_from_l2hw(unit, &l2addr_del, &l2_entries);
   4400         }
   4401         if (entry_add != NULL) {
   4402             l2_entries.entry_flags = 0;
   4403             switch (mem_type) {
   4404             case L2_ENTRY_1m:
   4405                 sal_memcpy(&l2_entries.l2_entry_1, entry_add, 
   4406                            sizeof(l2_entry_1_entry_t));
   4407                 l2_entries.entry_flags |= _BCM_TR3_L2_SELECT_L2_ENTRY_1;
   4408                 break;
   4409             case L2_ENTRY_2m:
   4410                 sal_memcpy(&l2_entries.l2_entry_2, entry_add, 
   4411                            sizeof(l2_entry_2_entry_t));
   4412                 l2_entries.entry_flags |= _BCM_TR3_L2_SELECT_L2_ENTRY_2;
   4413                 break;
   4414             case EXT_L2_ENTRY_1m:
   4415                 sal_memcpy(&l2_entries.ext_l2_entry_1, entry_add, 
   4416                            sizeof(ext_l2_entry_1_entry_t));
   4417                 l2_entries.entry_flags |= _BCM_TR3_L2_SELECT_EXT_L2_ENTRY_1;
   4418                 break;
   4419             case EXT_L2_ENTRY_2m:
   4420                 sal_memcpy(&l2_entries.ext_l2_entry_2, entry_add, 
   4421                            sizeof(ext_l2_entry_2_entry_t));
   4422                 l2_entries.entry_flags |= _BCM_TR3_L2_SELECT_EXT_L2_ENTRY_2;
   4423                 break;
   4424             default: assert(0);
   4425             }
   4426             (void)_bcm_tr3_l2api_from_l2hw(unit, &l2addr_add, &l2_entries);
   4427         }
   4428 
   4429         if ((entry_del != NULL) && (entry_add != NULL)) { /* It's a move */
   4430             set_flags |= BCM_L2_MOVE;
   4431             if (SOC_USE_GPORT(unit)) {
   4432                 if (l2addr_del.port != l2addr_add.port) {
   4433                     set_flags |= BCM_L2_MOVE_PORT;
   4434                 }
   4435             } else {
   4436                 if (l2addr_del.modid != l2addr_add.modid ||
   4437                     l2addr_del.tgid != l2addr_add.tgid ||
   4438                     l2addr_del.port != l2addr_add.port) {
   4439                     set_flags |= BCM_L2_MOVE_PORT;
   4440                 }
   4441             }
   4442             if (!(l2addr_del.flags & BCM_L2_TRUNK_MEMBER)) {
   4443                 if (bcm_tr3_l2_port_native(unit, l2addr_del.modid,
   4444                                            l2addr_del.port) > 0) {
   4445                     set_flags |= BCM_L2_FROM_NATIVE;
   4446                     set_flags |= BCM_L2_NATIVE;
   4447                 }
   4448             }
   4449             if (!(l2addr_add.flags & BCM_L2_TRUNK_MEMBER)) {
   4450                 if (bcm_tr3_l2_port_native(unit, l2addr_add.modid,
   4451                                            l2addr_add.port) > 0) {
   4452                     set_flags |= BCM_L2_TO_NATIVE;
   4453                     set_flags |= BCM_L2_NATIVE;
   4454                 }
   4455             }
   4456             l2addr_del.flags |= set_flags;
   4457             l2addr_add.flags |= set_flags;
   4458         } else if (entry_del != NULL) { /* Age out or simple delete */
   4459             if (!(l2addr_del.flags & BCM_L2_TRUNK_MEMBER)) {
   4460                 if (bcm_tr3_l2_port_native(unit, l2addr_del.modid,
   4461                                             l2addr_del.port) > 0) {
   4462                     l2addr_del.flags |= BCM_L2_NATIVE;
   4463                 }
   4464             }
   4465         } else if (entry_add != NULL) { /* Insert or learn */
   4466             if (!(l2addr_add.flags & BCM_L2_TRUNK_MEMBER)) {
   4467                 if (bcm_tr3_l2_port_native(unit, l2addr_add.modid,
   4468                                            l2addr_add.port) > 0) {
   4469                     l2addr_add.flags |= BCM_L2_NATIVE;
   4470                 }
   4471             }
   4472             if (flags & SOC_L2X_ENTRY_OVERFLOW) {
   4473                 l2addr_add.flags |= BCM_L2_ENTRY_OVERFLOW;
   4474             }
   4475         }
   4476 
   4477         /* The entries are now set up.  Make the callbacks */
   4478         if (entry_del != NULL) {
   4479             _bcm_tr3_l2_cbs[unit](unit, &l2addr_del, BCM_L2_CALLBACK_DELETE,
   4480                                   _bcm_tr3_l2_cb_data[unit]);
   4481         }
   4482         if (entry_add != NULL) {
   4483             _bcm_tr3_l2_cbs[unit](unit, &l2addr_add, BCM_L2_CALLBACK_ADD,
   4484                                   _bcm_tr3_l2_cb_data[unit]);
   4485         }
   4486     }
   4487 }
   4488 
   4489 /*
   4490  * Function:
   4491  *      _bcm_tr3_l2_hw_init
   4492  * Purpose:
   4493  *      Initialize the BCM L2 HW subsystem.
   4494  * Parameters:
   4495  *      unit - (IN) Unit number.
   4496  * Returns:
   4497  *      BCM_E_xxx
   4498  * Notes:
   4499  */
   4500 int 
   4501 _bcm_tr3_l2_hw_init(int unit)
   4502 {
   4503     int         rv, lclass, was_running = FALSE;
   4504     uint32      flags;
   4505     sal_usecs_t interval;
   4506 
   4507     if (soc_l2x_running(unit, &flags, &interval)) { 
   4508         was_running = TRUE; 
   4509         BCM_IF_ERROR_RETURN(soc_tr3_l2x_stop(unit)); 
   4510     }
   4511 
   4512     if (!SOC_WARM_BOOT(unit) && !SOC_IS_RCPU_ONLY(unit)) {
   4513         if (!(SAL_BOOT_QUICKTURN || SAL_BOOT_SIMULATION ||
   4514               SAL_BOOT_BCMSIM)) {
   4515             (void)_tr3_l2x_delete_all(unit);
   4516 
   4517             /*
   4518              * Init class based learning
   4519              */
   4520             BCM_IF_ERROR_RETURN(soc_mem_clear(unit, PORT_CBL_TABLEm, 
   4521                                               MEM_BLOCK_ALL, 0));
   4522             for (lclass = 0; lclass < SOC_REG_NUMELS(unit, CBL_ATTRIBUTEr);
   4523                  lclass++) {
   4524                 BCM_IF_ERROR_RETURN(WRITE_CBL_ATTRIBUTEr(unit, lclass, 0));
   4525             }
   4526         }
   4527     }
   4528 
   4529     
   4530 
   4531     rv = _bcm_tr3_l2_mbi_init(unit);
   4532     if (BCM_FAILURE(rv) && (rv != BCM_E_UNAVAIL)) {
   4533         return rv;
   4534     }
   4535 
   4536     /* bcm_l2_register clients */
   4537     soc_l2_entry_register(unit, _bcm_tr3_l2_register_callback, NULL);
   4538 
   4539     if (was_running) {
   4540         interval = (SAL_BOOT_BCMSIM) ? BCMSIM_L2XMSG_INTERVAL : interval;
   4541         soc_l2x_start(unit, flags, interval);
   4542     }
   4543 
   4544     return BCM_E_NONE;
   4545 }
   4546 
   4547 /*
   4548  * Function:
   4549  *      _bcm_tr3_l2_cache_gport_resolve
   4550  * Purpose:
   4551  *      Convert destination in a GPORT format to modid port pair or trunk id
   4552  * Parameters:
   4553  *      unit - Unit number
   4554  *      l2caddr - (IN/OUT) Hardware-independent L2 entry
   4555  * Returns:
   4556  *      BCM_E_XXX
   4557  */
   4558 STATIC int 
   4559 _bcm_tr3_l2_cache_gport_resolve(int unit, bcm_l2_cache_addr_t *l2caddr)
   4560 {
   4561     bcm_port_t      port;
   4562     bcm_module_t    modid;
   4563     bcm_trunk_t     tgid;
   4564     int             id;
   4565 
   4566     if (BCM_GPORT_IS_SET(l2caddr->dest_port)) {
   4567         BCM_IF_ERROR_RETURN(_bcm_esw_gport_resolve(unit, l2caddr->dest_port, 
   4568                                                    &modid, &port, &tgid, &id));
   4569         /* MPLS MIM and WLAN GPORTS are not currently supported. */
   4570         if (-1 != id) {
   4571             return (BCM_E_UNAVAIL);
   4572         }
   4573         /* Trunk GPORT */
   4574         if (BCM_TRUNK_INVALID != tgid) {
   4575             l2caddr->flags |= BCM_L2_CACHE_TRUNK;
   4576             l2caddr->dest_trunk = tgid;
   4577         } else {    /* MODPORT GPORT */
   4578             l2caddr->dest_port = port;
   4579             l2caddr->dest_modid = modid;
   4580         }
   4581     }
   4582 
   4583     if (BCM_GPORT_IS_SET(l2caddr->src_port)) {
   4584         BCM_IF_ERROR_RETURN(bcm_esw_port_local_get(unit, l2caddr->src_port, 
   4585                                                    &port));
   4586         l2caddr->src_port = port;
   4587     }
   4588 
   4589     return BCM_E_NONE;
   4590 }
   4591 
   4592 /*
   4593  * Function:
   4594  *      _bcm_tr3_l2_cache_gport_construct
   4595  * Purpose:
   4596  *      Constract a GPORT destination format from modid port pair or trunk id
   4597  * Parameters:
   4598  *      unit - Unit number
   4599  *      l2caddr - (IN/OUT) Hardware-independent L2 entry
   4600  * Returns:
   4601  *      BCM_E_XXX
   4602  */
   4603 STATIC int 
   4604 _bcm_tr3_l2_cache_gport_construct(int unit, bcm_l2_cache_addr_t *l2caddr)
   4605 {
   4606     bcm_gport_t         gport;
   4607     _bcm_gport_dest_t   gport_dst;
   4608 
   4609      _bcm_gport_dest_t_init(&gport_dst);
   4610 
   4611      if (l2caddr->flags & BCM_L2_CACHE_TRUNK) {
   4612          gport_dst.gport_type = BCM_GPORT_TYPE_TRUNK;
   4613          gport_dst.tgid = l2caddr->dest_trunk;
   4614      } else {
   4615          gport_dst.gport_type = BCM_GPORT_TYPE_MODPORT;
   4616          gport_dst.modid = l2caddr->dest_modid;
   4617          gport_dst.port = l2caddr->dest_port;
   4618      }
   4619 
   4620     BCM_IF_ERROR_RETURN(
   4621         _bcm_esw_gport_construct(unit, &gport_dst, &gport));
   4622 
   4623     l2caddr->dest_port = gport;
   4624 
   4625     gport_dst.gport_type = BCM_GPORT_TYPE_MODPORT;
   4626     gport_dst.port = l2caddr->src_port;
   4627     BCM_IF_ERROR_RETURN(
   4628         bcm_esw_stk_my_modid_get(unit, &gport_dst.modid));
   4629     if (gport_dst.modid < 0) {
   4630         return BCM_E_UNAVAIL;
   4631     }
   4632 
   4633     BCM_IF_ERROR_RETURN(
   4634         _bcm_esw_gport_construct(unit, &gport_dst, &gport));
   4635 
   4636     l2caddr->src_port = gport;
   4637 
   4638     return BCM_E_NONE;
   4639 }
   4640 
   4641 /*
   4642  * Function:
   4643  *      _bcm_tr3_l2_cache_to_l2u
   4644  * Purpose:
   4645  *      Convert a hardware-independent L2 cache entry to a L2 User table entry.
   4646  * Parameters:
   4647  *      unit - Unit number
   4648  *      l2u_entry - (OUT) Firebolt L2 User entry
   4649  *      l2caddr - Hardware-independent L2 entry
   4650  * Returns:
   4651  *      BCM_E_XXX
   4652  */
   4653 STATIC int
   4654 _bcm_tr3_l2_cache_to_l2u(int unit, 
   4655                      l2u_entry_t *l2u_entry, bcm_l2_cache_addr_t *l2caddr)
   4656 {
   4657     bcm_module_t    mod_in, mod_out;
   4658     bcm_port_t      port_in, port_out;
   4659     uint16          vfi;
   4660     uint32          mask[2];
   4661     soc_field_t     port_field = 0;
   4662     int             skip_l2u, isGport, modid_field_len, port_field_len;
   4663     bcm_vlan_t      vlan;
   4664 
   4665     skip_l2u = soc_property_get(unit, spn_SKIP_L2_USER_ENTRY, 0);
   4666     
   4667     if (soc_feature(unit, soc_feature_l2_user_table) && !skip_l2u) {
   4668 
   4669         int pri_field_len;
   4670         int max_pri;
   4671         /* If VPN specified do not perform vlan id check */
   4672         if (!_BCM_VPN_IS_SET(l2caddr->vlan)) {
   4673             VLAN_CHK_ID(unit, l2caddr->vlan);
   4674         }
   4675 
   4676         if (l2caddr->flags & BCM_L2_CACHE_SETPRI) {
   4677             pri_field_len = soc_mem_field_length(unit, L2_USER_ENTRYm, PRIf);
   4678             max_pri = (1 << pri_field_len) - 1;
   4679 
   4680             /* Allow the maximum internal priority as per the device support */
   4681             if ((l2caddr->prio < BCM_PRIO_MIN) || (l2caddr->prio > max_pri)) {
   4682                     return BCM_E_PARAM;
   4683             }
   4684         }
   4685 
   4686         sal_memset(l2u_entry, 0, sizeof (*l2u_entry));
   4687 
   4688         _l2u_field32_set(unit, l2u_entry, VALIDf, 1);
   4689         _l2u_mac_addr_set(unit, l2u_entry, MAC_ADDRf, l2caddr->mac);
   4690 
   4691         if (_BCM_VPN_IS_SET(l2caddr->vlan)) {
   4692             _l2u_field32_set(unit, l2u_entry, KEY_TYPEf, 1);
   4693             _BCM_VPN_GET(vfi, _BCM_VPN_TYPE_VFI, l2caddr->vlan);
   4694             _l2u_field32_set(unit, l2u_entry, VFIf, vfi);
   4695 
   4696             if (l2caddr->flags & BCM_L2_CACHE_PROTO_PKT) {
   4697                 if (soc_mem_field_valid(unit, L2_USER_ENTRYm, 
   4698                                         L2_PROTOCOL_PKTf)) {
   4699                     _l2u_field32_set(unit, l2u_entry, L2_PROTOCOL_PKTf, 1);
   4700                 } else {
   4701                   return BCM_E_UNAVAIL;
   4702                 }
   4703             }
   4704 
   4705         } else {
   4706             _l2u_field32_set(unit, l2u_entry, KEY_TYPEf, 0);
   4707             vlan = l2caddr->vlan;
   4708             _l2u_field32_set(unit, l2u_entry, VLAN_IDf, vlan);
   4709         }
   4710 
   4711         if (l2caddr->flags & BCM_L2_CACHE_SETPRI) {
   4712             _l2u_field32_set(unit, l2u_entry, PRIf, l2caddr->prio);
   4713             _l2u_field32_set(unit, l2u_entry, RPEf, 1);
   4714         }
   4715 
   4716         if (l2caddr->flags & BCM_L2_CACHE_CPU) {
   4717             _l2u_field32_set(unit, l2u_entry, CPUf, 1);
   4718         }
   4719 
   4720         if (l2caddr->flags & BCM_L2_CACHE_BPDU) {
   4721             _l2u_field32_set(unit, l2u_entry, BPDUf, 1);
   4722         }
   4723 
   4724         if (l2caddr->flags & BCM_L2_CACHE_DISCARD) {
   4725             _l2u_field32_set(unit, l2u_entry, DST_DISCARDf, 1);
   4726         }
   4727 
   4728         if (l2caddr->flags & BCM_L2_CACHE_LEARN_DISABLE) {
   4729             _l2u_field32_set(unit, l2u_entry, DO_NOT_LEARN_MACSAf, 1);
   4730         }
   4731 
   4732         if (BCM_GPORT_IS_SET(l2caddr->dest_port) || 
   4733             BCM_GPORT_IS_SET(l2caddr->src_port)) {
   4734             BCM_IF_ERROR_RETURN(
   4735                 _bcm_tr3_l2_cache_gport_resolve(unit, l2caddr));
   4736             isGport = 1;
   4737         } else {
   4738             isGport = 0;
   4739         }
   4740         if (soc_feature(unit, soc_feature_trunk_group_overlay)) {
   4741             if (l2caddr->flags & BCM_L2_CACHE_TRUNK) {
   4742                 _l2u_field32_set(unit, l2u_entry, Tf, 1);
   4743                 _l2u_field32_set(unit, l2u_entry, TGIDf, l2caddr->dest_trunk);
   4744             } else {
   4745                 port_field = PORT_NUMf;
   4746             }
   4747         } else {
   4748             if (l2caddr->flags & BCM_L2_CACHE_TRUNK) {
   4749                 _l2u_field32_set(unit, l2u_entry, MODULE_IDf,
   4750                                  BCM_TRUNK_TO_MODIDf(unit,
   4751                                                      l2caddr->dest_trunk));
   4752                 _l2u_field32_set(unit, l2u_entry, PORT_TGIDf,
   4753                                  BCM_TRUNK_TO_TGIDf(unit,
   4754                                                     l2caddr->dest_trunk));
   4755             } else {
   4756                 port_field = PORT_TGIDf;
   4757             }
   4758         }
   4759 
   4760         if (!((l2caddr->flags & BCM_L2_CACHE_TRUNK) ||
   4761              (l2caddr->flags & BCM_L2_CACHE_MULTICAST))) {
   4762             mod_in = l2caddr->dest_modid;
   4763             port_in = l2caddr->dest_port;
   4764             if (!isGport) {
   4765                 PORT_DUALMODID_VALID(unit, port_in);
   4766             }
   4767             BCM_IF_ERROR_RETURN
   4768                 (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_SET,
   4769                                          mod_in, port_in, &mod_out, &port_out));
   4770             if (!SOC_MODID_ADDRESSABLE(unit, mod_out)) {
   4771                 return BCM_E_BADID;
   4772             }
   4773             if (!SOC_PORT_ADDRESSABLE(unit, port_out)) {
   4774                 return BCM_E_PORT;
   4775             }
   4776             _l2u_field32_set(unit, l2u_entry, MODULE_IDf, mod_out);
   4777             _l2u_field32_set(unit, l2u_entry, port_field, port_out);
   4778         }
   4779 
   4780         if ((l2caddr->flags & BCM_L2_CACHE_MULTICAST) &&
   4781             !_BCM_VPN_IS_SET(l2caddr->vlan)) {
   4782             if (_BCM_MULTICAST_IS_SET(l2caddr->group)) {
   4783                 if (_BCM_MULTICAST_IS_L2(l2caddr->group)) {
   4784                     port_field_len = soc_mem_field_length(unit, L2_USER_ENTRYm,
   4785                                                           port_field);
   4786                     modid_field_len = soc_mem_field_length(unit, L2_USER_ENTRYm,
   4787                                                            MODULE_IDf);
   4788                     /* If MACDA is MC, HW interprets value encoded in MODULE_IDf
   4789                        and PORT_FIELD as L2MC_INDEX */
   4790                     _l2u_field32_set(unit, l2u_entry, port_field,
   4791                                      (_BCM_MULTICAST_ID_GET(l2caddr->group) &
   4792                                      ((1 << port_field_len) - 1)));
   4793                     _l2u_field32_set(unit, l2u_entry, MODULE_IDf,
   4794                                      ((_BCM_MULTICAST_ID_GET(l2caddr->group) >>
   4795                                      port_field_len) &
   4796                                      ((1 << modid_field_len) - 1)));
   4797                 } else {
   4798                     return BCM_E_PARAM;
   4799                 }
   4800             }
   4801         }
   4802 
   4803         if (l2caddr->flags & BCM_L2_CACHE_L3) {
   4804             _l2u_field32_set(unit, l2u_entry, RESERVED_0f, 1);
   4805         }
   4806 
   4807         _l2u_mac_addr_set(unit, l2u_entry, MASKf, l2caddr->mac_mask);
   4808         _l2u_field_get(unit, l2u_entry, MASKf, mask);
   4809         mask[1] |= (l2caddr->vlan_mask & 0xfff) << 16;
   4810 
   4811         if (!(l2caddr->flags & BCM_L2_CACHE_L3)) {
   4812             if ((l2caddr->src_port) || (l2caddr->src_port_mask) ) {
   4813                 return BCM_E_PORT;
   4814             }
   4815         }
   4816 
   4817         _l2u_field_set(unit, l2u_entry, MASKf, mask);
   4818         _l2u_field32_set(unit, l2u_entry, CLASS_IDf, l2caddr->lookup_class);
   4819 
   4820         return BCM_E_NONE;
   4821     }
   4822     return BCM_E_UNAVAIL;
   4823 }
   4824 
   4825 /*
   4826  * Function:
   4827  *      _bcm_tr3_l2_from_l2u
   4828  * Purpose:
   4829  *      Convert L2 User table entry to a hardware-independent L2 cache entry.
   4830  * Parameters:
   4831  *      unit - Unit number
   4832  *      l2caddr - (OUT) Hardware-independent L2 entry
   4833  *      l2u_entry - Firebolt L2 User entry
   4834  * Returns:
   4835  *      BCM_E_XXX
   4836  */
   4837 STATIC int
   4838 _bcm_tr3_l2_cache_from_l2u(int unit, 
   4839                        bcm_l2_cache_addr_t *l2caddr, l2u_entry_t *l2u_entry)
   4840 {
   4841     bcm_module_t    mod_in = 0, mod_out;
   4842     bcm_port_t      port_in = 0, port_out;
   4843     uint32          mask[2];
   4844     int             skip_l2u, isGport, port_field_len, modid_field_len, rval;
   4845 #if defined(INCLUDE_L3)
   4846     bcm_vlan_t      vlan;
   4847 #endif
   4848 
   4849     skip_l2u = soc_property_get(unit, spn_SKIP_L2_USER_ENTRY, 0);
   4850 
   4851     if (soc_feature(unit, soc_feature_l2_user_table) && !skip_l2u) {
   4852 
   4853         sal_memset(l2caddr, 0, sizeof (*l2caddr));
   4854 
   4855         if (!_l2u_field32_get(unit, l2u_entry, VALIDf)) {
   4856             return BCM_E_NOT_FOUND;
   4857         }
   4858 
   4859         _l2u_mac_addr_get(unit, l2u_entry, MAC_ADDRf, l2caddr->mac);
   4860 
   4861         if (_l2u_field32_get(unit, l2u_entry, KEY_TYPEf)) {
   4862 #if defined(INCLUDE_L3)
   4863             /* key type 1 i.e. VFI */
   4864             vlan = _l2u_field32_get(unit, l2u_entry, VFIf);
   4865             if (_bcm_vfi_used_get(unit, vlan, _bcmVfiTypeMpls)) {
   4866                 _BCM_VPN_SET(l2caddr->vlan, _BCM_VPN_TYPE_VFI, vlan);
   4867             } else  if (_bcm_vfi_used_get(unit, vlan, _bcmVfiTypeMim)) {
   4868                 _BCM_VPN_SET(l2caddr->vlan, _BCM_VPN_TYPE_VFI, vlan);
   4869             } else  if (_bcm_vfi_used_get(unit, vlan, _bcmVfiTypeL2Gre)) {
   4870                 BCM_IF_ERROR_RETURN(
   4871                    _bcm_tr3_l2gre_vpn_get(unit, (int) vlan, &l2caddr->vlan));
   4872             }
   4873 
   4874 #endif
   4875         } else { /* key type 0 i.e. VLAN ID */
   4876             l2caddr->vlan = _l2u_field32_get(unit, l2u_entry, VLAN_IDf);
   4877         }
   4878 
   4879         l2caddr->prio = _l2u_field32_get(unit, l2u_entry, PRIf);
   4880 
   4881         if (_l2u_field32_get(unit, l2u_entry, RPEf)) {
   4882             l2caddr->flags |= BCM_L2_CACHE_SETPRI;
   4883         }
   4884 
   4885         if (_l2u_field32_get(unit, l2u_entry, CPUf)) {
   4886             l2caddr->flags |= BCM_L2_CACHE_CPU;
   4887         }
   4888 
   4889         if (_l2u_field32_get(unit, l2u_entry, BPDUf)) {
   4890             l2caddr->flags |= BCM_L2_CACHE_BPDU;
   4891         }
   4892 
   4893         if (soc_mem_field_valid(unit, L2_USER_ENTRYm, L2_PROTOCOL_PKTf)) {
   4894             if (_l2u_field32_get(unit, l2u_entry, L2_PROTOCOL_PKTf)) {
   4895                 l2caddr->flags |= BCM_L2_CACHE_PROTO_PKT;
   4896             }
   4897         }
   4898 
   4899         if (_l2u_field32_get(unit, l2u_entry, DST_DISCARDf)) {
   4900             l2caddr->flags |= BCM_L2_CACHE_DISCARD;
   4901         }
   4902 
   4903         if (_l2u_field32_get(unit, l2u_entry, DO_NOT_LEARN_MACSAf)) {
   4904             l2caddr->flags |= BCM_L2_CACHE_LEARN_DISABLE;
   4905         }
   4906 
   4907         if (_l2u_field32_get(unit, l2u_entry, Tf)) {
   4908             l2caddr->flags |= BCM_L2_CACHE_TRUNK;
   4909             l2caddr->dest_trunk = _l2u_field32_get(unit, l2u_entry, TGIDf);
   4910         }
   4911 
   4912         if (BCM_MAC_IS_MCAST(l2caddr->mac) &&
   4913             !_BCM_VPN_IS_SET(l2caddr->vlan)) {
   4914             l2caddr->flags |= BCM_L2_CACHE_MULTICAST;
   4915             mod_in = _l2u_field32_get(unit, l2u_entry, MODULE_IDf);
   4916             port_in = _l2u_field32_get(unit, l2u_entry, PORT_NUMf);
   4917             l2caddr->dest_modid = mod_in;
   4918             l2caddr->dest_port = port_in;
   4919             port_field_len = soc_mem_field_length(unit, L2_USER_ENTRYm,
   4920                                                   PORT_NUMf);
   4921             modid_field_len = soc_mem_field_length(unit, L2_USER_ENTRYm,
   4922                                                    MODULE_IDf);
   4923             /* If MACDA is MC, HW interprets value encoded in MODULE_IDf
   4924                and PORT_FIELD as L2MC_INDEX */
   4925             l2caddr->group = ((port_in & ((1 << port_field_len) - 1)) |
   4926                               ((mod_in & ((1 << modid_field_len) - 1))
   4927                               << port_field_len));
   4928             /* Translate l2mc index */
   4929             BCM_IF_ERROR_RETURN(
   4930                 bcm_esw_switch_control_get(unit, bcmSwitchL2McIdxRetType,
   4931                                            &rval));
   4932             if (rval) {
   4933                 _BCM_MULTICAST_GROUP_SET(l2caddr->group, _BCM_MULTICAST_TYPE_L2,
   4934                                          l2caddr->group);
   4935             }
   4936         }
   4937 
   4938         if (!((l2caddr->flags & BCM_L2_CACHE_TRUNK) ||
   4939             (l2caddr->flags & BCM_L2_CACHE_MULTICAST))) {
   4940             mod_in = _l2u_field32_get(unit, l2u_entry, MODULE_IDf);
   4941             port_in = _l2u_field32_get(unit, l2u_entry, PORT_NUMf);
   4942 
   4943             if (!SOC_MODID_ADDRESSABLE(unit, mod_in)) {
   4944                 return BCM_E_BADID;
   4945             }
   4946             BCM_IF_ERROR_RETURN(_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET,
   4947                                                        mod_in, port_in, &mod_out,
   4948                                                        &port_out));
   4949             l2caddr->dest_modid = mod_out;
   4950             l2caddr->dest_port = port_out;
   4951         }
   4952         BCM_IF_ERROR_RETURN(
   4953             bcm_esw_switch_control_get(unit, bcmSwitchUseGport, &isGport));
   4954 
   4955         if (_l2u_field32_get(unit, l2u_entry, RESERVED_0f)) {
   4956             l2caddr->flags |= BCM_L2_CACHE_L3;
   4957         }
   4958 
   4959         if (isGport) {
   4960             BCM_IF_ERROR_RETURN(
   4961                 _bcm_tr3_l2_cache_gport_construct(unit, l2caddr));
   4962         }
   4963 
   4964         _l2u_mac_addr_get(unit, l2u_entry, MASKf, l2caddr->mac_mask);
   4965         _l2u_field_get(unit, l2u_entry, MASKf, mask);
   4966         l2caddr->vlan_mask = (mask[1] >> 16) & 0xfff;
   4967         l2caddr->lookup_class = _l2u_field32_get(unit, l2u_entry, CLASS_IDf);
   4968 
   4969         return BCM_E_NONE;
   4970     }
   4971     return BCM_E_UNAVAIL;
   4972 }
   4973 
   4974 /*
   4975  * Function:
   4976  *      _bcm_tr3_l2cache_to_my_station
   4977  * Purpose:
   4978  *      Convert an L2 API data structure to a MY_STATION_TCAM entry
   4979  * Parameters:
   4980  *      unit              Unit number
   4981  *      my_station_entry  (OUT) MY_STATION_TCAM entry
   4982  *      l2caddr            L2 API data structure
   4983  */
   4984 STATIC void
   4985 _bcm_tr3_l2cache_to_my_station(int unit, 
   4986                               my_station_tcam_entry_t *my_station_entry,
   4987                               bcm_l2_cache_addr_t *l2caddr)
   4988 {
   4989 
   4990     soc_mem_field32_set(unit, MY_STATION_TCAMm, my_station_entry, VALIDf, 1);
   4991     soc_mem_field32_set(unit, MY_STATION_TCAMm, my_station_entry, VLAN_IDf,
   4992                         l2caddr->vlan);
   4993     soc_mem_field32_set(unit, MY_STATION_TCAMm, my_station_entry, VLAN_ID_MASKf,
   4994                         l2caddr->vlan_mask);
   4995     soc_mem_mac_addr_set(unit, MY_STATION_TCAMm, my_station_entry, MAC_ADDRf,
   4996                          l2caddr->mac);
   4997     soc_mem_mac_addr_set(unit, MY_STATION_TCAMm, my_station_entry, MAC_ADDR_MASKf,
   4998                          l2caddr->mac_mask);
   4999     soc_mem_field32_set(unit, MY_STATION_TCAMm, my_station_entry, ING_PORT_NUMf,
   5000                         l2caddr->src_port);
   5001     soc_mem_field32_set(unit, MY_STATION_TCAMm, my_station_entry, 
   5002                         ING_PORT_NUM_MASKf, l2caddr->src_port_mask);
   5003 
   5004     if (l2caddr->flags & BCM_L2_CACHE_L3) {
   5005         soc_mem_field32_set(unit, MY_STATION_TCAMm, my_station_entry,
   5006                             IPV4_TERMINATION_ALLOWEDf, 1);
   5007         soc_mem_field32_set(unit, MY_STATION_TCAMm, my_station_entry,
   5008                             IPV6_TERMINATION_ALLOWEDf, 1);
   5009         soc_mem_field32_set(unit, MY_STATION_TCAMm, my_station_entry,
   5010                             ARP_RARP_TERMINATION_ALLOWEDf, 1);
   5011     }
   5012 
   5013     if (l2caddr->flags & BCM_L2_CACHE_DISCARD) {
   5014         soc_mem_field32_set(unit, MY_STATION_TCAMm, my_station_entry,
   5015                             DISCARDf, 1);
   5016     }
   5017     if (l2caddr->flags & BCM_L2_CACHE_CPU) {
   5018         soc_mem_field32_set(unit, MY_STATION_TCAMm, my_station_entry,
   5019                             COPY_TO_CPUf, 1);
   5020     }
   5021 }
   5022 
   5023 /*
   5024  * Function:
   5025  *      _bcm_tr3_l2cache_from_my_station
   5026  * Purpose:
   5027  *      Convert a MY_STATION_TCAM entry to an L2cache API data structure
   5028  * Parameters:
   5029  *      unit              (IN) Unit number
   5030  *      l2caddr            (OUT) L2cache API data structure
   5031  *      my_station_entry  MY_STATION_TCAM entry
   5032  */
   5033 STATIC void
   5034 _bcm_tr3_l2cache_from_my_station(int unit, bcm_l2_cache_addr_t *l2caddr,
   5035                                 my_station_tcam_entry_t *my_station_entry)
   5036 {
   5037     sal_memset(l2caddr, 0, sizeof(*l2caddr));
   5038 
   5039     /* Valid bit is ignored here; entry is assumed valid */
   5040 
   5041     soc_mem_mac_addr_get(unit, MY_STATION_TCAMm, (uint32 *)my_station_entry,
   5042                          MAC_ADDRf, l2caddr->mac);
   5043     soc_mem_mac_addr_get(unit, MY_STATION_TCAMm, (uint32 *)my_station_entry,
   5044                          MAC_ADDR_MASKf, l2caddr->mac_mask);
   5045     l2caddr->vlan = soc_mem_field32_get(unit, MY_STATION_TCAMm, my_station_entry,
   5046                                        VLAN_IDf);
   5047     l2caddr->vlan_mask = soc_mem_field32_get(unit, MY_STATION_TCAMm, 
   5048                                             my_station_entry, VLAN_ID_MASKf);
   5049 
   5050     l2caddr->src_port = soc_mem_field32_get(unit, MY_STATION_TCAMm,
   5051                                            my_station_entry, ING_PORT_NUMf);
   5052 
   5053     l2caddr->src_port_mask = soc_mem_field32_get(unit, MY_STATION_TCAMm,
   5054                               my_station_entry, ING_PORT_NUM_MASKf);
   5055 
   5056     l2caddr->flags |= BCM_L2_CACHE_L3;
   5057     if (soc_mem_field32_get(unit, MY_STATION_TCAMm, my_station_entry,
   5058                             DISCARDf)) {
   5059         l2caddr->flags |= BCM_L2_CACHE_DISCARD;
   5060     }
   5061     if (soc_mem_field32_get(unit, MY_STATION_TCAMm, my_station_entry,
   5062                             COPY_TO_CPUf)) {
   5063         l2caddr->flags |= BCM_L2_CACHE_CPU;
   5064     }
   5065 }
   5066 
   5067 /*
   5068  * Function:
   5069  *     _bcm_tr3_my_station_lookup
   5070  * Purpose:
   5071  *     Perform following exact matched in MY_STATION_TCAM table:
   5072  *     - target entry lookup:
   5073  *       match the entry specified by vlan/mac and optional port
   5074  *     - (optional) alternate entry lookup: (when alt_index != NULL)
   5075  *       match the possible entry having the same vlan/mac as the target entry
   5076  * Parameters:
   5077  *     unit              Unit number
   5078  *     mac               MAC address key
   5079  *     vlan              VLAN id key
   5080  *     port              Source port number key (-1 means to match any)
   5081  *     index_to_be_skip  The index to be omit during lookup
   5082  *     entry_index       (OUT) target entry index (if BCM_E_NONE)
   5083  *                             available entry index or -1 (if BCM_E_NOT_FOUND)
   5084  *     alt_index         (OUT) alternate entry index or -1 (if BCM_E_NOT_FOUND)
   5085  *                       if alt_index is NULL, that means lookup only
   5086  * Returns:
   5087  *      BCM_E_NONE - target entry found
   5088  *      BCM_E_NOT_FOUND - target entry not found
   5089  * Notes:
   5090  *     if (target entry is found) {
   5091  *         entry_index: index for the matched target entry
   5092  *         alt_index: N/A
   5093  *     } else if (alternate entry is found) {
   5094  *         entry_index: index for the free entry to be used (-1 if table full)
   5095  *         alt_index: index for the matched alternate entry
   5096  *         *** caller needs to compare both indices, move the entry if needed
   5097  *     } else {
   5098  *         entry_index: index for the free entry to be used (-1 if table full)
   5099  *         alt_index: -1
   5100  *     }
   5101  */
   5102 STATIC int
   5103 _bcm_tr3_my_station_lookup(int unit, bcm_mac_t mac, bcm_vlan_t vlan,
   5104                           bcm_port_t port, int index_to_skip,
   5105                           int *entry_index, int *alt_index)
   5106 {
   5107     _bcm_tr3_l2_bookkeeping_t *info = L2_INFO(unit);
   5108     my_station_tcam_entry_t *entry, entry0, entry1, entry2, mask0, mask1;
   5109     int index0, index1, free_index, i, entry_words;
   5110     int start, end, step;
   5111     bcm_mac_t mac_mask;
   5112     uint32 port_mask;
   5113 
   5114     LOG_INFO(BSL_LS_BCM_L2,
   5115              (BSL_META_U(unit,
   5116                          "_bcm_tr3_my_station_lookup: unit=%d "
   5117                          "mac=%02x:%02x:%02x:%02x:%02x:%02x vlan=%d port=%d "
   5118                          "index_to_skip=%d\n"),
   5119               unit, vlan, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],
   5120               port, index_to_skip));
   5121 
   5122     sal_memset(&mac_mask, 0xff, sizeof(mac_mask));
   5123     port_mask =
   5124         (1 << soc_mem_field_length(unit, MY_STATION_TCAMm, ING_PORT_NUMf)) - 1;
   5125 
   5126     entry_words = soc_mem_entry_words(unit, MY_STATION_TCAMm);
   5127 
   5128     /*
   5129      * entry0, mask0 are for target entry
   5130      * entry1, mask1 are for alternate entry
   5131      * if (port == -1)
   5132      *     entry0 is: vlan/mac/00/fff/ffffffffffff/ff
   5133      *     entry1 is: vlan/mac/xx/fff/ffffffffffff/ff
   5134      *     start from last entry (free index needs to have larger index than
   5135      *     any alternate entry)
   5136      * else
   5137      *     entry0 is: vlan/mac/port/fff/ffffffffffff/ff
   5138      *     entry1 is: vlan/mac/00/fff/ffffffffffff/ff
   5139      *     start from first entry (free index needs to have smaller index than
   5140      *     the alternate entry)
   5141      */
   5142     sal_memset(&entry0, 0, sizeof(entry0));
   5143     soc_mem_field32_set(unit, MY_STATION_TCAMm, &entry0, VALIDf, 1);
   5144     soc_mem_field32_set(unit, MY_STATION_TCAMm, &entry0, VLAN_IDf, vlan);
   5145     soc_mem_mac_addr_set(unit, MY_STATION_TCAMm, &entry0, MAC_ADDRf, mac);
   5146     soc_mem_field32_set(unit, MY_STATION_TCAMm, &entry0, VLAN_ID_MASKf, 0xfff);
   5147     soc_mem_mac_addr_set(unit, MY_STATION_TCAMm, &entry0, MAC_ADDR_MASKf,
   5148                          mac_mask);
   5149     mask0 = entry0;
   5150     soc_mem_field32_set(unit, MY_STATION_TCAMm, &mask0, VLAN_IDf, 0xfff);
   5151     soc_mem_mac_addr_set(unit, MY_STATION_TCAMm, &mask0, MAC_ADDRf, mac_mask);
   5152     soc_mem_field32_set(unit, MY_STATION_TCAMm, &mask0, ING_PORT_NUMf,
   5153                         port_mask);
   5154     soc_mem_field32_set(unit, MY_STATION_TCAMm, &mask0, ING_PORT_NUM_MASKf,
   5155                         port_mask);
   5156     if (alt_index != NULL) {
   5157         entry1 = entry0;
   5158         mask1 = mask0;
   5159     }
   5160 
   5161     if (port == -1) {
   5162         start = soc_mem_index_max(unit, MY_STATION_TCAMm);
   5163         end = -1;
   5164         step = -1;
   5165     } else {
   5166         soc_mem_field32_set(unit, MY_STATION_TCAMm, &entry0, ING_PORT_NUMf,
   5167                             port);
   5168         soc_mem_field32_set(unit, MY_STATION_TCAMm, &entry0,
   5169                             ING_PORT_NUM_MASKf, port_mask);
   5170         start = 0;
   5171         end = soc_mem_index_count(unit, MY_STATION_TCAMm);
   5172         step = 1;
   5173     }
   5174 
   5175     if (alt_index != NULL) {
   5176         if (port == -1) {
   5177             soc_mem_field32_set(unit, MY_STATION_TCAMm, &mask1, ING_PORT_NUMf,
   5178                                 0);
   5179         }
   5180 
   5181         /* entry2 is for checking VALID bit */
   5182         sal_memset(&entry2, 0, sizeof(entry2));
   5183         soc_mem_field32_set(unit, MY_STATION_TCAMm, &entry2, VALIDf, 1);
   5184     }
   5185 
   5186     index1 = -1;
   5187     free_index = -1;
   5188     for (index0 = start; index0 != end; index0 += step) {
   5189         /* Skip the entry that we want to move (we know it matches) */
   5190         if (index0 == index_to_skip) {
   5191             continue;
   5192         }
   5193 
   5194         entry = &info->my_station_shadow[index0];
   5195 
   5196         /* Try matching target entry */
   5197         for (i = 0; i < entry_words; i++) {
   5198             if ((entry->entry_data[i] ^ entry0.entry_data[i]) &
   5199                 mask0.entry_data[i]) {
   5200                 break;
   5201             }
   5202         }
   5203         if (i == entry_words) {
   5204             /* Target entry is found, no more action needed */
   5205             *entry_index = index0;
   5206             LOG_INFO(BSL_LS_BCM_L2,
   5207                      (BSL_META_U(unit,
   5208                                  "_bcm_tr3_my_station_lookup: found entry_index=%d\n"),
   5209                       *entry_index));
   5210             return BCM_E_NONE;
   5211         }
   5212 
   5213         if (alt_index == NULL) { /* lookup only */
   5214             continue;
   5215         }
   5216 
   5217         /* Keep track index of the first free entry */
   5218         if (free_index == -1) {
   5219             for (i = 0; i < entry_words; i++) {
   5220                 if (entry->entry_data[i] & entry2.entry_data[i]) {
   5221                     break;
   5222                 }
   5223             }
   5224             if (i == entry_words) {
   5225                 if (index1 != -1) {
   5226                     /* Both free entry and alternate entry are found */
   5227                     *entry_index = index0;
   5228                     *alt_index = index1;
   5229                     LOG_INFO(BSL_LS_BCM_L2,
   5230                              (BSL_META_U(unit,
   5231                                          "_bcm_tr3_my_station_lookup: not found "
   5232                                          "entry_index=%d alt_index=%d\n"),
   5233                               *entry_index, *alt_index));
   5234                     return BCM_E_NOT_FOUND;
   5235                 } else {
   5236                     free_index = index0;
   5237                     continue;
   5238                 }
   5239             }
   5240         }
   5241 
   5242         /* Try matching alternate entry. If alternate entry is found, it
   5243          * implies target entry is not in the table */
   5244         for (i = 0; i < entry_words; i++) {
   5245             if ((entry->entry_data[i] ^ entry1.entry_data[i]) &
   5246                 mask1.entry_data[i]) {
   5247                 break;
   5248             }
   5249         }
   5250         if (i == entry_words) {
   5251             if (free_index != -1) {
   5252                 /* both free entry and alternate entry are found */
   5253                 *entry_index = free_index;
   5254                 *alt_index = index0;
   5255                 LOG_INFO(BSL_LS_BCM_L2,
   5256                          (BSL_META_U(unit,
   5257                                      "_bcm_tr3_my_station_lookup: not found "
   5258                                      "entry_index=%d alt_index=%d\n"),
   5259                           *entry_index, *alt_index));
   5260                 return BCM_E_NOT_FOUND;
   5261             } else {
   5262                 index1 = index0;
   5263                 continue;
   5264             }
   5265         }
   5266     }
   5267 
   5268     *entry_index = free_index;
   5269     if (alt_index != NULL) {
   5270         *alt_index = index1;
   5271     }
   5272     LOG_INFO(BSL_LS_BCM_L2,
   5273              (BSL_META_U(unit,
   5274                          "_bcm_tr3_my_station_lookup: not found "
   5275                          "entry_index=%d alt_index=%d\n"),
   5276               *entry_index, alt_index != NULL ? *alt_index : -100));
   5277 
   5278     return BCM_E_NOT_FOUND;
   5279 }
   5280 
   5281 /*
   5282  * Function:
   5283  *     bcm_tr3_l2cache_myStation_set
   5284  * Purpose:
   5285  *     Add MY_STATION_TCAM entry from L2 cache API
   5286  * Parameters:
   5287  *     unit              Unit number
   5288  *     index             Index
   5289  *     l2caddr           L2 cache API data structure
   5290  */
   5291 int
   5292 _bcm_tr3_l2cache_myStation_set(int unit, int index, bcm_l2_cache_addr_t *l2caddr)
   5293 {
   5294     _bcm_tr3_l2_bookkeeping_t *info = L2_INFO(unit);
   5295     int rv, entry_index, alt_index;
   5296     my_station_tcam_entry_t *entry;
   5297     l2u_entry_t l2u_entry;
   5298     bcm_vlan_t vlan;
   5299     bcm_mac_t mac;
   5300     bcm_port_t port;
   5301 
   5302     VLAN_CHK_ID(unit, l2caddr->vlan);
   5303 
   5304     soc_mem_lock(unit, MY_STATION_TCAMm);
   5305 
   5306     entry_index = -1;
   5307     entry = &info->my_station_shadow[index];
   5308     if (!soc_mem_field32_get(unit, MY_STATION_TCAMm, entry, VALIDf)) {
   5309         /* Entry is not in used */
   5310         entry_index = index;
   5311     } else {
   5312         /* Check if the existing entry is added by l2cache API */
   5313         rv = soc_l2u_get(unit, &l2u_entry, index);
   5314         if (BCM_SUCCESS(rv) &&
   5315             (soc_mem_field32_get(unit, L2_USER_ENTRYm, &l2u_entry,
   5316                               RESERVED_0f))) {
   5317             entry_index = index;
   5318         }
   5319     }
   5320     if (entry_index != -1) {
   5321         /* The entry is not used by API other than l2cache */
   5322         sal_memset(entry, 0, sizeof(*entry));
   5323         _bcm_tr3_l2cache_to_my_station(unit, entry, l2caddr);
   5324         rv = soc_mem_write(unit, MY_STATION_TCAMm, MEM_BLOCK_ALL, index,
   5325                            entry);
   5326         soc_mem_unlock(unit, MY_STATION_TCAMm);
   5327         return rv;
   5328     }
   5329 
   5330     /* Need to move the current entry */
   5331     vlan = soc_mem_field32_get(unit, MY_STATION_TCAMm, entry, VLAN_IDf);
   5332     soc_mem_mac_addr_get(unit, MY_STATION_TCAMm, entry, MAC_ADDRf, mac);
   5333     if (soc_mem_field32_get(unit, MY_STATION_TCAMm, entry,
   5334                             ING_PORT_NUM_MASKf) == 0) {
   5335         port = -1;
   5336     } else {
   5337         port = soc_mem_field32_get(unit, MY_STATION_TCAMm, entry,
   5338                                    ING_PORT_NUMf);
   5339     }
   5340     rv = _bcm_tr3_my_station_lookup(unit, mac, vlan, port, index, &entry_index,
   5341                                    &alt_index);
   5342     if (rv == BCM_E_NOT_FOUND && entry_index == -1) {
   5343         /* No free entry available for insertion */
   5344         rv = BCM_E_FULL;
   5345     }
   5346     if (rv != BCM_E_NOT_FOUND) {
   5347         soc_mem_unlock(unit, MY_STATION_TCAMm);
   5348         return rv;
   5349     }
   5350 
   5351     if (alt_index != -1 &&
   5352         ((port == -1 && alt_index > entry_index) ||
   5353          (port != -1 && alt_index < entry_index))) {
   5354         /* Free entry is available for moving the target entry and alternate
   5355          * entry exists. However need to swap these 2 entries to maintain
   5356          * proper lookup precedence */
   5357         info->my_station_shadow[entry_index] =
   5358             info->my_station_shadow[alt_index];
   5359         rv = soc_mem_write(unit, MY_STATION_TCAMm, MEM_BLOCK_ALL, entry_index,
   5360                            &info->my_station_shadow[entry_index]);
   5361         if (BCM_FAILURE(rv)) {
   5362             soc_mem_unlock(unit, MY_STATION_TCAMm);
   5363             return rv;
   5364         }
   5365         entry_index = alt_index;
   5366     }
   5367 
   5368     /* Move the entry at specified index to the available free location */
   5369     info->my_station_shadow[entry_index] = *entry;
   5370     rv = soc_mem_write(unit, MY_STATION_TCAMm, MEM_BLOCK_ALL, entry_index,
   5371                        entry);
   5372     if (BCM_FAILURE(rv)) {
   5373         soc_mem_unlock(unit, MY_STATION_TCAMm);
   5374         return rv;
   5375     }
   5376 
   5377     /* Add the new entry */
   5378     sal_memset(entry, 0, sizeof(*entry));
   5379     _bcm_tr3_l2cache_to_my_station(unit, entry, l2caddr);
   5380     rv = soc_mem_write(unit, MY_STATION_TCAMm, MEM_BLOCK_ALL, index,
   5381                        entry);
   5382 
   5383     soc_mem_unlock(unit, MY_STATION_TCAMm);
   5384     return rv;
   5385 }
   5386 
   5387 /*
   5388  * Function:
   5389  *      _bcm_tr3_l2cache_myStation_delete
   5390  * Purpose:
   5391  *    Delete l2cache entry from myStation TCAM
   5392  * Parameters:
   5393  *      unit -   [IN] Unit number
   5394  *      index -  [IN] index to a table
   5395  */
   5396 STATIC int 
   5397 _bcm_tr3_l2cache_myStation_delete(int unit, int index)
   5398 {
   5399     _bcm_tr3_l2_bookkeeping_t *info = L2_INFO(unit);
   5400     int rv, i, entry_words;
   5401     my_station_tcam_entry_t *entry;
   5402     l2u_entry_t l2u_entry;
   5403     uint32 *l3_mask, *tunnel_mask;
   5404 
   5405     l3_mask = info->my_station_l3_mask.entry_data;
   5406     tunnel_mask = info->my_station_tunnel_mask.entry_data;
   5407     entry_words = soc_mem_entry_words(unit, MY_STATION_TCAMm);
   5408 
   5409     soc_mem_lock(unit, MY_STATION_TCAMm);
   5410 
   5411     entry = &info->my_station_shadow[index];
   5412 
   5413     /* Check if the entry has L3 related flag enabled */
   5414     for (i = 0; i < entry_words; i++) {
   5415         if (entry->entry_data[i] & l3_mask[i]) {
   5416             break;
   5417         }
   5418     }
   5419     if (i == entry_words) {
   5420         soc_mem_unlock(unit, MY_STATION_TCAMm);
   5421         return BCM_E_NOT_FOUND;
   5422     }
   5423 
   5424     /* Check if the entry is valid */
   5425     if (!soc_mem_field32_get(unit, MY_STATION_TCAMm, entry, VALIDf)) {
   5426         soc_mem_unlock(unit, MY_STATION_TCAMm);
   5427         return BCM_E_NOT_FOUND;
   5428     }
   5429 
   5430     /* Check if the entry is added by l2cache API */
   5431     rv = soc_l2u_get(unit, &l2u_entry, index);
   5432     if (BCM_FAILURE(rv)) {
   5433         soc_mem_unlock(unit, MY_STATION_TCAMm);
   5434         return rv;
   5435     }
   5436     if (!soc_mem_field32_get(unit, L2_USER_ENTRYm, &l2u_entry,
   5437                            RESERVED_0f)) {
   5438         return BCM_E_NOT_FOUND;
   5439     }
   5440     /* Check to see if we need to delete or modify the entry */
   5441     for (i = 0; i < entry_words; i++) {
   5442         if (entry->entry_data[i] & tunnel_mask[i]) {
   5443             break;
   5444         }
   5445     }
   5446     if (i == entry_words) {
   5447         /* Delete the entry if no tunnel related flag is enabled */
   5448         sal_memset(entry, 0, sizeof(*entry));
   5449     } else {
   5450         /* Modify the entry if any tunnel related flag is enabled */
   5451         for (i = 0; i < entry_words; i++) {
   5452             entry->entry_data[i] &= ~l3_mask[i];
   5453         }
   5454         soc_mem_field32_set(unit, MY_STATION_TCAMm, entry, DISCARDf, 0);
   5455         soc_mem_field32_set(unit, MY_STATION_TCAMm, entry, COPY_TO_CPUf, 0);
   5456     }
   5457     rv = soc_mem_write(unit, MY_STATION_TCAMm, MEM_BLOCK_ALL, index, entry);
   5458 
   5459     soc_mem_unlock(unit, MY_STATION_TCAMm);
   5460     return rv;
   5461 }
   5462 
   5463 /*
   5464  * Function:
   5465  *      _bcm_tr3_l2cache_myStation_get
   5466  * Purpose:
   5467  *      Get l2cache entry for L2 processing.
   5468  * Parameters:
   5469  *      unit -          [IN] Unit number
   5470  *      index -         [IN] index to a table
   5471  *      l2addr -        [OUT] pointer to l2_cache structure to fill
   5472  */
   5473 STATIC int 
   5474 _bcm_tr3_l2cache_myStation_get(int unit, int index, bcm_l2_cache_addr_t *l2caddr)
   5475 {
   5476     _bcm_tr3_l2_bookkeeping_t *info = L2_INFO(unit);
   5477     int i, entry_words;
   5478     my_station_tcam_entry_t *entry;
   5479     l2u_entry_t l2u_entry;
   5480     uint32 *l3_mask;
   5481 
   5482     l3_mask = info->my_station_l3_mask.entry_data;
   5483     entry_words = soc_mem_entry_words(unit, MY_STATION_TCAMm);
   5484 
   5485     entry = &info->my_station_shadow[index];
   5486 
   5487     /* Check if the entry has L3 related flag enabled */
   5488     for (i = 0; i < entry_words; i++) {
   5489         if (entry->entry_data[i] & l3_mask[i]) {
   5490             break;
   5491         }
   5492     }
   5493     if (i == entry_words) {
   5494         return BCM_E_NOT_FOUND;
   5495     }
   5496 
   5497     /* Check if the entry is valid */
   5498     if (!soc_mem_field32_get(unit, MY_STATION_TCAMm, entry, VALIDf)) {
   5499         return BCM_E_NOT_FOUND;
   5500     }
   5501 
   5502     /* Check if the entry is added by l2cache API */
   5503     SOC_IF_ERROR_RETURN(soc_l2u_get(unit, &l2u_entry, index));
   5504     if (! soc_mem_field32_get(unit, L2_USER_ENTRYm, &l2u_entry,    
   5505                            RESERVED_0f)) {
   5506         return BCM_E_NOT_FOUND;
   5507     }
   5508 
   5509     _bcm_tr3_l2cache_from_my_station(unit, l2caddr, entry);
   5510 
   5511     return BCM_E_NONE;
   5512 
   5513 }
   5514 
   5515 
   5516 /*
   5517  * Function:
   5518  *      _bcm_tr3_l2_learn_limit_system_get
   5519  * Purpose:
   5520  *      Get MAC learn limit for a system
   5521  * Parameters:
   5522  *      unit  - BCM unit number
   5523  *      flags - Action bitmask
   5524  *      limit - System limit of MAC addresses to learn
   5525  *              Negative if limit disabled
   5526  * Returns:
   5527  *      BCM_E_XXX
   5528  */
   5529 STATIC int
   5530 _bcm_tr3_l2_learn_limit_system_get(int unit, uint32 *flags, int *limit)
   5531 {
   5532     uint32  rval;
   5533 
   5534     BCM_IF_ERROR_RETURN(READ_SYS_MAC_LIMIT_CONTROLr(unit, &rval));
   5535     *flags &= ~(BCM_L2_LEARN_LIMIT_ACTION_DROP |
   5536                 BCM_L2_LEARN_LIMIT_ACTION_CPU);
   5537     if (soc_reg_field_get(unit, SYS_MAC_LIMIT_CONTROLr, rval,
   5538                           SYS_OVER_LIMIT_TOCPUf)) {
   5539         *flags |= BCM_L2_LEARN_LIMIT_ACTION_CPU;
   5540     }
   5541     if (soc_reg_field_get(unit, SYS_MAC_LIMIT_CONTROLr, rval,
   5542                           SYS_OVER_LIMIT_DROPf)) {
   5543         *flags |= BCM_L2_LEARN_LIMIT_ACTION_DROP;
   5544     }
   5545     /*
   5546      * When MAC limiting is enabled, ENABLE_INTERNAL_L2_ENTRYf
   5547      * is always set. So only checking for this field
   5548      * to retrieve MAC limit value
   5549      */
   5550     if (soc_reg_field_get(unit, SYS_MAC_LIMIT_CONTROLr, rval,
   5551                            ENABLE_INTERNAL_L2_ENTRYf)) {
   5552         *limit = soc_reg_field_get(unit, SYS_MAC_LIMIT_CONTROLr, rval,
   5553                                    SYS_LIMITf);
   5554     } else {
   5555         *limit = -1;
   5556     }
   5557 
   5558     return BCM_E_NONE;
   5559 }
   5560 
   5561 /*
   5562  * Function:
   5563  *      _bcm_tr3_l2_learn_limit_get
   5564  * Purpose:
   5565  *      Get MAC learn limit for a port/trunk/vlan
   5566  * Parameters:
   5567  *      unit  - BCM unit number
   5568  *      mem   - PORT_OR_TRUNK_MAC_LIMITm or VLAN_OR_VFI_MAC_LIMITm
   5569  *      index - for PORT_OR_TRUNK_MAC_LIMITm
   5570  *                  0 - 127: trunk identifier
   5571  *                  128 - 181: port identifier + 128
   5572  *              for VLAN_OR_VFI_MAC_LIMITm
   5573  *                  0 - 4095: VLAN identifier
   5574  *                  4096 - 5119: virtual forwarding instance + 4096
   5575  *      flags - Action bitmask
   5576  *      limit - Max number of MAC addresses can be learned for the specified
   5577  *              identifier
   5578  *              Negative if limit disabled (i.e. unlimit)
   5579  * Returns:
   5580  *      BCM_E_XXX
   5581  */
   5582 STATIC int
   5583 _bcm_tr3_l2_learn_limit_get(int unit, soc_mem_t mem, int index, uint32* flags,
   5584                            int* limit)
   5585 {
   5586     uint32 entry[SOC_MAX_MEM_WORDS];
   5587 
   5588     SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ANY, index, &entry));
   5589     *flags &= ~(BCM_L2_LEARN_LIMIT_ACTION_DROP |
   5590                 BCM_L2_LEARN_LIMIT_ACTION_CPU);
   5591     if (soc_mem_field32_get(unit, mem, &entry, OVER_LIMIT_DROPf)) {
   5592         *flags |= BCM_L2_LEARN_LIMIT_ACTION_DROP;
   5593     }
   5594     if (soc_mem_field32_get(unit, mem, &entry, OVER_LIMIT_TOCPUf)) {
   5595         *flags |= BCM_L2_LEARN_LIMIT_ACTION_CPU;
   5596     }
   5597     *limit = soc_mem_field32_get(unit, mem, &entry, LIMITf);
   5598 
   5599     return BCM_E_NONE;
   5600 }
   5601 
   5602 
   5603 /*
   5604  * Function:
   5605  *      _bcm_tr3_l2_learn_limit_set
   5606  * Purpose:
   5607  *      Set MAC learn limit for a port/trunk/vlan
   5608  * Parameters:
   5609  *      unit  - BCM unit number
   5610  *      mem   - PORT_OR_TRUNK_MAC_LIMITm or VLAN_OR_VFI_MAC_LIMITm
   5611  *      index - for PORT_OR_TRUNK_MAC_LIMITm
   5612  *                  0 - 127: trunk identifier
   5613  *                  128 - 181: port identifier + 128
   5614  *              for VLAN_OR_VFI_MAC_LIMITm
   5615  *                  0 - 4095: VLAN identifier
   5616  *                  4096 - 5119: virtual forwarding instance + 4096
   5617  *      flags - Action bitmask
   5618  *      limit - Max number of MAC addresses can be learned for the specified
   5619  *              identifier
   5620  *              Negative if limit disabled (i.e. unlimit)
   5621  * Returns:
   5622  *      BCM_E_XXX
   5623  */
   5624 STATIC int
   5625 _bcm_tr3_l2_learn_limit_set(int unit, soc_mem_t mem, int index, uint32 flags,
   5626                            int limit)
   5627 {
   5628     uint32 entry[SOC_MAX_MEM_WORDS], rval;
   5629     int rv;
   5630     port_or_trunk_mac_limit_entry_t init_entry;
   5631     int32 max_limit;
   5632 
   5633     if (limit < 0) {
   5634         soc_mem_lock(unit, mem);
   5635         sal_memcpy(&init_entry, soc_mem_entry_null(unit,mem),
   5636                                          sizeof(init_entry));
   5637 
   5638         /* Reset Limit value is different than soc_mem_entry_null
   5639          * for devices with ESM */
   5640         max_limit = BCM_MAC_LIMIT_MAX(unit);
   5641 
   5642         soc_mem_field32_set(unit, mem, &init_entry, LIMITf, max_limit);
   5643         rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, index, &init_entry);
   5644 
   5645         soc_mem_unlock(unit, mem);
   5646         return rv;
   5647     }
   5648 
   5649     soc_mem_lock(unit, mem);
   5650     rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, index, &entry);
   5651     if (BCM_SUCCESS(rv)) {
   5652         soc_mem_field32_set(unit, mem, &entry, OVER_LIMIT_TOCPUf,
   5653                             flags & BCM_L2_LEARN_LIMIT_ACTION_CPU ? 1 : 0);
   5654         soc_mem_field32_set(unit, mem, &entry, OVER_LIMIT_DROPf,
   5655                             flags & BCM_L2_LEARN_LIMIT_ACTION_DROP ? 1 : 0);
   5656         soc_mem_field32_set(unit, mem, &entry, LIMITf, limit);
   5657         rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, index, &entry);
   5658     }
   5659     soc_mem_unlock(unit, mem);
   5660 
   5661     if (BCM_FAILURE(rv)) {
   5662         return rv;
   5663     }
   5664 
   5665     /* Registers RSEL1_MISC_CONTROL and SYS_MAC_LIMIT_CONTROL are 
   5666      * identical in config. Enable if any of Port, Trunk, Vlan, 
   5667      * VFI, or system learn limits are enabled, disable only when 
   5668      * system limit is disabled */
   5669 
   5670     BCM_IF_ERROR_RETURN(READ_RSEL1_MISC_CONTROLr(unit, &rval));
   5671     soc_reg_field_set(unit, RSEL1_MISC_CONTROLr, &rval,
   5672                       MAC_LIMIT_ENABLEf, 1); 
   5673     BCM_IF_ERROR_RETURN(WRITE_RSEL1_MISC_CONTROLr(unit, rval));
   5674 
   5675     BCM_IF_ERROR_RETURN(READ_SYS_MAC_LIMIT_CONTROLr(unit, &rval));
   5676 
   5677     /*
   5678      * Enable MAC limiting for internal L2 and also for external L2
   5679      * if it is available
   5680      */
   5681     soc_reg_field_set(unit, SYS_MAC_LIMIT_CONTROLr, &rval, 
   5682                       ENABLE_INTERNAL_L2_ENTRYf, 1);
   5683     if (soc_feature(unit, soc_feature_esm_support)) {
   5684         if ((SOC_MEM_IS_VALID(unit, EXT_L2_ENTRY_1m) &&
   5685              (0 < soc_mem_index_count(unit, EXT_L2_ENTRY_1m))) ||
   5686             ((SOC_MEM_IS_VALID(unit, EXT_L2_ENTRY_2m) &&
   5687              (0 < soc_mem_index_count(unit, EXT_L2_ENTRY_2m))))) {
   5688             soc_reg_field_set(unit, SYS_MAC_LIMIT_CONTROLr, &rval,
   5689                     ENABLE_EXTERNAL_L2_ENTRYf, 1);
   5690         }
   5691     }
   5692     return (WRITE_SYS_MAC_LIMIT_CONTROLr(unit, rval));
   5693 }
   5694 
   5695 /*
   5696  * Function:
   5697  *      _bcm_tr3_l2_to_my_station
   5698  * Purpose:
   5699  *      Convert an L2 API data structure to a Triumph3 MY_STATION_TCAM entry
   5700  * Parameters:
   5701  *      unit              Unit number
   5702  *      entry            (OUT) MY_STATION_TCAM entry
   5703  *      l2addr            L2 API data structure
   5704  */
   5705 STATIC void
   5706 _bcm_tr3_l2_to_my_station(int unit, my_station_tcam_entry_t *entry,
   5707                          bcm_l2_addr_t *l2addr, int incl_key_mask)
   5708 {
   5709     bcm_mac_t mac_mask;
   5710     uint32 fval;
   5711 
   5712     if (incl_key_mask) {
   5713         soc_mem_field32_set(unit, MY_STATION_TCAMm, entry, VALIDf, 1);
   5714         soc_mem_field32_set(unit, MY_STATION_TCAMm, entry, VLAN_IDf,
   5715                             l2addr->vid);
   5716         soc_mem_field32_set(unit, MY_STATION_TCAMm, entry, VLAN_ID_MASKf, 0xfff);
   5717         soc_mem_mac_addr_set(unit, MY_STATION_TCAMm, entry, MAC_ADDRf,
   5718                              l2addr->mac);
   5719         sal_memset(&mac_mask, 0xff, sizeof(mac_mask));
   5720         soc_mem_mac_addr_set(unit, MY_STATION_TCAMm, entry, MAC_ADDR_MASKf,
   5721                               mac_mask);
   5722     }
   5723 
   5724     fval = l2addr->flags & BCM_L2_L3LOOKUP ? 1: 0;
   5725     soc_mem_field32_set(unit, MY_STATION_TCAMm, entry,
   5726               IPV4_TERMINATION_ALLOWEDf, fval);
   5727     soc_mem_field32_set(unit, MY_STATION_TCAMm, entry,
   5728               IPV6_TERMINATION_ALLOWEDf, fval);
   5729     soc_mem_field32_set(unit, MY_STATION_TCAMm, entry,
   5730               ARP_RARP_TERMINATION_ALLOWEDf, fval);
   5731 
   5732     fval = l2addr->flags & BCM_L2_DISCARD_DST ? 1 : 0;
   5733     soc_mem_field32_set(unit, MY_STATION_TCAMm, entry, DISCARDf, fval);
   5734     fval = l2addr->flags & BCM_L2_COPY_TO_CPU ? 1 : 0;
   5735     soc_mem_field32_set(unit, MY_STATION_TCAMm, entry, COPY_TO_CPUf, fval);
   5736 }
   5737 
   5738 /*
   5739  * Function:
   5740  *      _bcm_tr3_l2_from_my_station
   5741  * Purpose:
   5742  *      Convert a Triumph3 MY_STATION_TCAM entry to an L2 API data structure
   5743  * Parameters:
   5744  *      unit              Unit number
   5745  *      l2addr            (OUT) L2 API data structure
   5746  *      my_station_entry  MY_STATION_TCAM entry
   5747  */
   5748 STATIC void
   5749 _bcm_tr3_l2_from_my_station(int unit, bcm_l2_addr_t *l2addr,
   5750                            my_station_tcam_entry_t *my_station_entry)
   5751 {
   5752     sal_memset(l2addr, 0, sizeof(*l2addr));
   5753 
   5754     /* Valid bit is ignored here; entry is assumed valid */
   5755 
   5756     soc_mem_mac_addr_get(unit, MY_STATION_TCAMm, (uint32 *)my_station_entry,
   5757                          MAC_ADDRf, l2addr->mac);
   5758     l2addr->vid = soc_mem_field32_get(unit, MY_STATION_TCAMm, my_station_entry,
   5759                                       VLAN_IDf);
   5760 
   5761     if (soc_mem_field32_get(unit, MY_STATION_TCAMm, my_station_entry,
   5762                             IPV4_TERMINATION_ALLOWEDf)) {
   5763         l2addr->flags |= BCM_L2_L3LOOKUP;
   5764     }
   5765 
   5766     if (soc_mem_field32_get(unit, MY_STATION_TCAMm, my_station_entry,
   5767                             DISCARDf)) {
   5768         l2addr->flags |= BCM_L2_DISCARD_DST;
   5769     }
   5770     if (soc_mem_field32_get(unit, MY_STATION_TCAMm, my_station_entry,
   5771                             COPY_TO_CPUf)) {
   5772         l2addr->flags |= BCM_L2_COPY_TO_CPU;
   5773     }
   5774     l2addr->flags |= BCM_L2_LEARN_LIMIT_EXEMPT;
   5775 }
   5776 
   5777 /*
   5778  * Function:
   5779  *      bcm_tr3_l2_myStation_get
   5780  * Purpose:
   5781  *      Get (MAC, VLAN) entry for L2 processing.
   5782  *      Frames destined to (MAC, VLAN) is subjected to L2/L3 processing.
   5783  * Parameters:
   5784  *      unit - Unit number
   5785  *      mac  - MAC address
   5786  *      vlan - VLAN ID
   5787  */
   5788 int
   5789 _bcm_tr3_l2_myStation_get (int unit, bcm_mac_t mac, bcm_vlan_t vid,
   5790                          bcm_l2_addr_t *l2addr)
   5791 {
   5792     _bcm_tr3_l2_bookkeeping_t *info = L2_INFO(unit);
   5793     int index, i, entry_words;
   5794     my_station_tcam_entry_t *entry;
   5795     l2u_entry_t l2u_entry;
   5796     uint32 *l3_mask;
   5797 
   5798     /* Handle VFIs as well as invalid vlans */
   5799     if (vid > BCM_VLAN_MAX) {
   5800         return BCM_E_NOT_FOUND; 
   5801     }
   5802 
   5803     l3_mask = info->my_station_l3_mask.entry_data;
   5804     entry_words = soc_mem_entry_words(unit, MY_STATION_TCAMm);
   5805 
   5806     BCM_IF_ERROR_RETURN
   5807         (_bcm_tr3_my_station_lookup(unit, mac, vid, -1, -1, &index, NULL));
   5808 
   5809     entry = &info->my_station_shadow[index];
   5810 
   5811     /* Check if the entry has L3 related flag enabled */
   5812     for (i = 0; i < entry_words; i++) {
   5813         if (entry->entry_data[i] & l3_mask[i]) {
   5814             break;
   5815         }
   5816     }
   5817     if (i == entry_words) {
   5818         return BCM_E_NOT_FOUND;
   5819     }
   5820 
   5821     /* Check if the entry is not added by l2cache API */
   5822     SOC_IF_ERROR_RETURN(soc_l2u_get(unit, &l2u_entry, index));
   5823     if (soc_mem_field32_get(unit, L2_USER_ENTRYm, &l2u_entry,
   5824                          RESERVED_0f)) {
   5825         return BCM_E_NOT_FOUND;
   5826     }
   5827 
   5828     _bcm_tr3_l2_from_my_station(unit, l2addr, entry);
   5829 
   5830     return BCM_E_NONE;
   5831 }
   5832 
   5833 /*
   5834  * Function:
   5835  *      _bcm_tr3_l2_myStation_add
   5836  * Purpose:
   5837  *      Add l2 entry for L3 processing.
   5838  * Parameters:
   5839  *      unit -         [IN] Unit number
   5840  *      l2addr -       [IN] pointer to l2_addr structure 
   5841  */
   5842 STATIC int
   5843 _bcm_tr3_l2_myStation_add(int unit, bcm_l2_addr_t *l2addr)
   5844 {
   5845     _bcm_tr3_l2_bookkeeping_t *info = L2_INFO(unit);
   5846     int rv, index, alt_index;
   5847     my_station_tcam_entry_t *entry;
   5848     l2u_entry_t l2u_entry;
   5849 
   5850     VLAN_CHK_ID(unit, l2addr->vid);
   5851 
   5852     soc_mem_lock(unit, MY_STATION_TCAMm);
   5853 
   5854     rv = _bcm_tr3_my_station_lookup(unit, l2addr->mac, l2addr->vid, -1, -1,
   5855                                    &index, &alt_index);
   5856     if (BCM_SUCCESS(rv)) {
   5857         /* Check if the entry is not added by l2cache API */
   5858         rv = soc_l2u_get(unit, &l2u_entry, index);
   5859         if (BCM_FAILURE(rv)) {
   5860             soc_mem_unlock(unit, MY_STATION_TCAMm);
   5861             return rv;
   5862         }
   5863         if (soc_mem_field32_get(unit, L2_USER_ENTRYm, &l2u_entry,
   5864                              RESERVED_0f)) {
   5865             soc_mem_unlock(unit, MY_STATION_TCAMm);
   5866             return BCM_E_EXISTS;
   5867         }
   5868         /* Entry exist, update the entry */
   5869         entry = &info->my_station_shadow[index];
   5870         _bcm_tr3_l2_to_my_station(unit, entry, l2addr, FALSE);
   5871         rv = soc_mem_write(unit, MY_STATION_TCAMm, MEM_BLOCK_ALL, index,
   5872                            entry);
   5873     } else if (rv == BCM_E_NOT_FOUND && index == -1) {
   5874         /* No free entry available for insertion */
   5875         rv = BCM_E_FULL;
   5876     }
   5877     if (rv != BCM_E_NOT_FOUND) {
   5878         soc_mem_unlock(unit, MY_STATION_TCAMm);
   5879         return rv;
   5880     }
   5881 
   5882     if (alt_index > index) {
   5883         /* Free entry is available for new entry insertion and alternate entry
   5884          * exists. However need to swap these 2 entries to maintain proper
   5885          * lookup precedence */
   5886         info->my_station_shadow[index] = info->my_station_shadow[alt_index];
   5887         rv = soc_mem_write(unit, MY_STATION_TCAMm, MEM_BLOCK_ALL, index,
   5888                            &info->my_station_shadow[index]);
   5889         if (BCM_FAILURE(rv)) {
   5890             soc_mem_unlock(unit, MY_STATION_TCAMm);
   5891             return rv;
   5892         }
   5893         index = alt_index;
   5894     }
   5895 
   5896     /* Add the new entry */
   5897     entry = &info->my_station_shadow[index];
   5898     sal_memset(entry, 0, sizeof(*entry));
   5899     _bcm_tr3_l2_to_my_station(unit, entry, l2addr, TRUE);
   5900     rv = soc_mem_write(unit, MY_STATION_TCAMm, MEM_BLOCK_ALL, index, entry);
   5901 
   5902     soc_mem_unlock(unit, MY_STATION_TCAMm);
   5903     return rv;
   5904 }
   5905 
   5906 /*
   5907  * Function:
   5908  *      _bcm_tr3_l2_myStation_delete
   5909  * Purpose:
   5910  *      Delete an l2 entry for L3 processing.
   5911  * Parameters:
   5912  *      unit - (IN) Unit number
   5913  *      mac  - (IN) MAC address to delete
   5914  *      vid  - (IN) VLAN id
   5915  *      index_used -   (OUT) index of entry that was deleted
   5916  */
   5917 STATIC int
   5918 _bcm_tr3_l2_myStation_delete(int unit, bcm_mac_t mac, bcm_vlan_t vid,
   5919                                   int *index_used)
   5920 {
   5921     _bcm_tr3_l2_bookkeeping_t *info = L2_INFO(unit);
   5922     int rv, index, i, entry_words;
   5923     my_station_tcam_entry_t *entry;
   5924     l2u_entry_t l2u_entry;
   5925     uint32 *l3_mask, *tunnel_mask;
   5926 
   5927     VLAN_CHK_ID(unit, vid);
   5928 
   5929     l3_mask = info->my_station_l3_mask.entry_data;
   5930     tunnel_mask = info->my_station_tunnel_mask.entry_data;
   5931     entry_words = soc_mem_entry_words(unit, MY_STATION_TCAMm);
   5932 
   5933     soc_mem_lock(unit, MY_STATION_TCAMm);
   5934 
   5935     rv = _bcm_tr3_my_station_lookup(unit, mac, vid, -1, -1, &index, NULL);
   5936     if (BCM_SUCCESS(rv)) {
   5937         entry = &info->my_station_shadow[index];
   5938 
   5939         /* Check if the entry has L3 related flag enabled */
   5940         for (i = 0; i < entry_words; i++) {
   5941             if (entry->entry_data[i] & l3_mask[i]) {
   5942                 break;
   5943             }
   5944         }
   5945         if (i == entry_words) {
   5946             soc_mem_unlock(unit, MY_STATION_TCAMm);
   5947             return BCM_E_NOT_FOUND;
   5948         }
   5949 
   5950         /* Check if the entry is not added by l2cache API */
   5951         rv = soc_l2u_get(unit, &l2u_entry, index);
   5952         if (BCM_FAILURE(rv)) {
   5953             soc_mem_unlock(unit, MY_STATION_TCAMm);
   5954             return rv;
   5955         }
   5956 
   5957         if (soc_mem_field32_get(unit, L2_USER_ENTRYm, &l2u_entry,
   5958                              RESERVED_0f)) {
   5959             soc_mem_unlock(unit, MY_STATION_TCAMm);
   5960             return BCM_E_NOT_FOUND;
   5961         }
   5962         /* Check to see if we need to delete or modify the entry */
   5963         for (i = 0; i < entry_words; i++) {
   5964             if (entry->entry_data[i] & tunnel_mask[i]) {
   5965                 break;
   5966             }
   5967         }
   5968         if (i == entry_words) {
   5969             /* Delete the entry if no tunnel related flag is enabled */
   5970             sal_memset(entry, 0, sizeof(*entry));
   5971         } else {
   5972             /* Modify the entry if any tunnel related flag is enabled */
   5973             for (i = 0; i < entry_words; i++) {
   5974                 entry->entry_data[i] &= ~l3_mask[i];
   5975             }
   5976             soc_mem_field32_set(unit, MY_STATION_TCAMm, entry, DISCARDf, 0);
   5977             soc_mem_field32_set(unit, MY_STATION_TCAMm, entry, COPY_TO_CPUf,
   5978                                 0);
   5979         }
   5980         rv = soc_mem_write(unit, MY_STATION_TCAMm, MEM_BLOCK_ALL, index,
   5981                            entry);
   5982     }
   5983 
   5984     soc_mem_unlock(unit, MY_STATION_TCAMm);
   5985     return rv;
   5986 }
   5987 
   5988 /*
   5989  * Function:
   5990  *      _bcm_tr3_l2_bookkeeping_info_init
   5991  * Purpose:
   5992  *      Initialize the Tr3 L2 book keeping info 
   5993  * Parameters:
   5994  *      unit - (IN) Unit number
   5995  */
   5996 STATIC int
   5997 _bcm_tr3_l2_bookkeeping_info_init(int unit)
   5998 {
   5999     int num_station, alloc_size;
   6000     _bcm_tr3_l2_bookkeeping_t *info = L2_INFO(unit);
   6001 
   6002     num_station = soc_mem_index_count(unit, MY_STATION_TCAMm);
   6003     alloc_size = sizeof(my_station_tcam_entry_t) * num_station;
   6004 
   6005     if (NULL == info->my_station_shadow) {
   6006         info->my_station_shadow =
   6007             sal_alloc(alloc_size, "my station shadow");
   6008         if (info->my_station_shadow == NULL) {
   6009             return BCM_E_MEMORY;
   6010         }
   6011         sal_memset(info->my_station_shadow, 0, alloc_size);
   6012     }
   6013 
   6014     /* L3 flags */
   6015     soc_mem_field32_set(unit, MY_STATION_TCAMm,
   6016                         &info->my_station_l3_mask,
   6017                         IPV4_TERMINATION_ALLOWEDf, 1);
   6018     soc_mem_field32_set(unit, MY_STATION_TCAMm,
   6019                         &info->my_station_l3_mask,
   6020                         IPV6_TERMINATION_ALLOWEDf, 1);
   6021     soc_mem_field32_set(unit, MY_STATION_TCAMm,
   6022                         &info->my_station_l3_mask,
   6023                         ARP_RARP_TERMINATION_ALLOWEDf, 1);
   6024     /* Tunnel flags */
   6025     soc_mem_field32_set(unit, MY_STATION_TCAMm,
   6026                         &info->my_station_tunnel_mask,
   6027                         MIM_TERMINATION_ALLOWEDf, 1);
   6028     soc_mem_field32_set(unit, MY_STATION_TCAMm,
   6029                         &info->my_station_tunnel_mask,
   6030                         MPLS_TERMINATION_ALLOWEDf, 1);
   6031     soc_mem_field32_set(unit, MY_STATION_TCAMm,
   6032                     &info->my_station_tunnel_mask,
   6033                     TRILL_TERMINATION_ALLOWEDf, 1);
   6034 
   6035     return BCM_E_NONE;
   6036 }
   6037 
   6038 STATIC int
   6039 _bcm_tr3_l2_cbl_init(int unit) {
   6040 
   6041     soc_mem_t mem;
   6042     int entry_words;
   6043     int index_max;
   6044     union {
   6045         port_cbl_table_entry_t port_cbl[128];
   6046         uint32 w[1];
   6047     } entry;
   6048     void *entries[1];
   6049     soc_profile_mem_t *profile;
   6050     int module;
   6051     uint32 profile_index;
   6052     int field_len;
   6053 
   6054     /* Create profile for PORT_CBL_TABLE table */
   6055     if (!SOC_WARM_BOOT(unit)) {
   6056         BCM_IF_ERROR_RETURN(soc_mem_clear(unit, PORT_CBL_TABLEm,
   6057                                              COPYNO_ALL, FALSE));
   6058     }
   6059     if (_bcm_l2_tr3_port_cbl_profile[unit] == NULL) {
   6060         _bcm_l2_tr3_port_cbl_profile[unit] =
   6061             sal_alloc(sizeof(soc_profile_mem_t),
   6062                       "PORT_CBL_TABLE profile");
   6063         if (_bcm_l2_tr3_port_cbl_profile[unit] == NULL) {
   6064             return BCM_E_MEMORY;
   6065         }
   6066         soc_profile_mem_t_init(_bcm_l2_tr3_port_cbl_profile[unit]);
   6067     }
   6068     profile = _bcm_l2_tr3_port_cbl_profile[unit];
   6069     mem = PORT_CBL_TABLEm;
   6070     entry_words = sizeof(port_cbl_table_entry_t) / sizeof(uint32);
   6071     field_len = soc_mem_field_length(unit, PORT_CBL_TABLE_MODBASEm,
   6072                                      BASEf);
   6073     /* coverity[large_shift : FALSE] */
   6074     index_max = (1 << (field_len - 1)) - 1;
   6075     entries[0] = &entry;
   6076     sal_memset(&entry.port_cbl[0], 0, sizeof(entry.port_cbl[0]));
   6077     field_len = soc_mem_field_length(unit, PORT_CBL_TABLEm,
   6078                                      PORT_LEARNING_CLASSf);
   6079     soc_mem_field32_set(unit, PORT_CBL_TABLEm, &entry.port_cbl[0],
   6080                         PORT_LEARNING_CLASSf, (1 << field_len) - 1);
   6081 
   6082     BCM_IF_ERROR_RETURN
   6083         (soc_profile_mem_index_create(unit, &mem, &entry_words, NULL,
   6084                                       &index_max, entries, 1,
   6085                                       profile));
   6086 
   6087     if (!SOC_WARM_BOOT(unit)) {
   6088         BCM_IF_ERROR_RETURN(soc_mem_clear(unit, PORT_CBL_TABLE_MODBASEm,
   6089                                     COPYNO_ALL, FALSE));
   6090         sal_memset(entry.port_cbl, 0, sizeof(entry.port_cbl));
   6091         BCM_IF_ERROR_RETURN
   6092             (soc_profile_mem_add(unit, profile, entries,
   6093                                  SOC_PORT_ADDR_MAX(unit) + 1,
   6094                                  &profile_index));
   6095         for (module = 1; module <= SOC_MODID_MAX(unit); module++) {
   6096             SOC_IF_ERROR_RETURN
   6097                 (soc_profile_mem_reference
   6098                  (unit, profile, profile_index,
   6099                   SOC_PORT_ADDR_MAX(unit) + 1));
   6100         }
   6101     }
   6102 #ifdef BCM_WARM_BOOT_SUPPORT
   6103     else {
   6104         port_cbl_table_modbase_entry_t base_entry;
   6105 
   6106         for (module = 0; module <= SOC_MODID_MAX(unit); module++) {
   6107             SOC_IF_ERROR_RETURN
   6108                 (soc_mem_read(unit, PORT_CBL_TABLE_MODBASEm,
   6109                               MEM_BLOCK_ANY, module, &base_entry));
   6110             profile_index =
   6111                 soc_mem_field32_get(unit, PORT_CBL_TABLE_MODBASEm,
   6112                                     &base_entry, BASEf);
   6113             SOC_IF_ERROR_RETURN
   6114                 (soc_profile_mem_reference
   6115                  (unit, profile, profile_index,
   6116                   SOC_PORT_ADDR_MAX(unit) + 1));
   6117         }
   6118     }
   6119 #endif /* BCM_WARM_BOOT_SUPPORT */
   6120 
   6121     return BCM_E_NONE;
   6122 }
   6123 
   6124 #ifdef BCM_WARM_BOOT_SUPPORT
   6125 /*
   6126  * Function:
   6127  *      _bcm_tr3_l2_reinit
   6128  * Purpose:
   6129  *      Recover L2_INFO s/w state for TR3
   6130  * Parameters:
   6131  *      unit - (IN) Unit number.
   6132  * Returns:
   6133  *      BCM_E_xxx
   6134  * Notes:
   6135  */
   6136 STATIC int
   6137 _bcm_tr3_l2_reinit(int unit)
   6138 {
   6139     int i, num_station;
   6140     _bcm_tr3_l2_bookkeeping_t *info = L2_INFO(unit);
   6141     my_station_tcam_entry_t   entry;
   6142     bcm_mac_t                 mac_addr;
   6143     bcm_vlan_t                vid;
   6144     bcm_l2_addr_t             l2addr;
   6145     int                       rv;
   6146 
   6147     /* Compute hash for each entry */
   6148     num_station = soc_mem_index_count(unit, MY_STATION_TCAMm);
   6149     for (i = 0; i < num_station; i++) {
   6150 
   6151         sal_memcpy(&entry, soc_mem_entry_null(unit, MY_STATION_TCAMm),
   6152                    sizeof(my_station_tcam_entry_t));
   6153         BCM_IF_ERROR_RETURN
   6154             (READ_MY_STATION_TCAMm(unit, MEM_BLOCK_ANY, i, &entry));
   6155         if (!soc_mem_field32_get(unit,
   6156                                   MY_STATION_TCAMm, &entry, VALIDf)) {
   6157             continue;
   6158         }
   6159 
   6160         soc_mem_mac_addr_get(unit, MY_STATION_TCAMm,
   6161                              &entry, MAC_ADDRf, mac_addr);
   6162         vid = soc_mem_field32_get(unit, MY_STATION_TCAMm,
   6163                                   &entry, VLAN_IDf);
   6164 
   6165         rv = _bcm_tr3_l2_addr_get(unit, mac_addr, vid, TRUE, &l2addr);
   6166         if (BCM_FAILURE(rv)) {
   6167             continue;
   6168         }
   6169 
   6170         sal_memcpy(&info->my_station_shadow[i], &entry,
   6171                            sizeof(my_station_tcam_entry_t));
   6172     }
   6173 
   6174     return BCM_E_NONE;
   6175 }
   6176 #endif /* BCM_WARM_BOOT_SUPPORT */
   6177 
   6178 /*
   6179  * Function:
   6180  *      bcm_tr3_l2_init
   6181  * Purpose:
   6182  *      Initialize the BCM L2 subsystem.
   6183  * Parameters:
   6184  *      unit - (IN) Unit number.
   6185  * Returns:
   6186  *      BCM_E_xxx
   6187  * Notes:
   6188  */
   6189 int 
   6190 bcm_tr3_l2_init(int unit)
   6191 {
   6192     int rv; 
   6193     int frozen;
   6194     uint32 regval = 0;
   6195 
   6196     BCM_IF_ERROR_RETURN(soc_tr3_l2_is_frozen(unit, &frozen));
   6197     if (TRUE == frozen) {
   6198         return BCM_E_BUSY;
   6199     }
   6200 
   6201     BCM_IF_ERROR_RETURN(bcm_tr3_l2_detach(unit));
   6202 
   6203     /* First, determine which memories are active in this device */
   6204     _bcm_tr3_l2_mems_valid[unit] = 0;
   6205     if (0 < soc_mem_index_count(unit, L2_ENTRY_1m)) {
   6206         /* The ISM tables are active, so include them */
   6207         _bcm_tr3_l2_mems_valid[unit] |= _BCM_TR3_L2_SELECT_INTERNAL;
   6208     }
   6209     if (soc_feature(unit, soc_feature_esm_support)) {
   6210         if (SOC_MEM_IS_VALID(unit, EXT_L2_ENTRY_1m) &&
   6211             (0 < soc_mem_index_count(unit, EXT_L2_ENTRY_1m))) {
   6212             /* The ESM standard table is active, so include it */
   6213             _bcm_tr3_l2_mems_valid[unit] |=
   6214                 _BCM_TR3_L2_SELECT_EXT_L2_ENTRY_1;
   6215         }
   6216         if ((SOC_MEM_IS_VALID(unit, EXT_L2_ENTRY_2m)) &&
   6217             (0 < soc_mem_index_count(unit, EXT_L2_ENTRY_2m))) {
   6218             /* The ESM wide table is active, so include it */
   6219             _bcm_tr3_l2_mems_valid[unit] |=
   6220                 _BCM_TR3_L2_SELECT_EXT_L2_ENTRY_2;
   6221         }
   6222     }
   6223 
   6224     /* If, only ESM is available and no ISM, then learn on ESM tables */
   6225     if (!(_bcm_tr3_l2_mems_valid[unit] & _BCM_TR3_L2_SELECT_INTERNAL)) {
   6226         if ((_bcm_tr3_l2_mems_valid[unit] & 
   6227             _BCM_TR3_L2_SELECT_EXT_L2_ENTRY_1) ||
   6228             (_bcm_tr3_l2_mems_valid[unit] & _BCM_TR3_L2_SELECT_EXT_L2_ENTRY_2))
   6229         {   
   6230             BCM_IF_ERROR_RETURN(READ_LEARN_CONTROLr(unit, &regval));
   6231             soc_reg_field_set(unit, LEARN_CONTROLr, &regval,
   6232                               EXTERNAL_L2_ENTRYf, 1);
   6233             BCM_IF_ERROR_RETURN(WRITE_LEARN_CONTROLr(unit, regval));
   6234         }
   6235     }
   6236                 
   6237     /* Initialize memory accelation structures */
   6238     BCM_IF_ERROR_RETURN(_bcm_tr3_l2_memacc_init(unit));
   6239 
   6240     /* Clear the HW state and associated SW data */
   6241     BCM_IF_ERROR_RETURN(_bcm_tr3_l2_hw_init(unit));
   6242 
   6243     if (!SOC_WARM_BOOT(unit)) {
   6244         /*
   6245          * Init L2 cache
   6246          */
   6247         rv = bcm_tr3_l2_cache_init(unit);
   6248         if (BCM_FAILURE(rv) && (rv != BCM_E_UNAVAIL)) {
   6249             return rv;
   6250         }
   6251     }
   6252 
   6253     /*
   6254      * Init L2 learn limit
   6255      */
   6256     rv = _bcm_tr3_l2_learn_limit_init(unit);
   6257     if (BCM_FAILURE(rv) && (rv != BCM_E_UNAVAIL)) {
   6258         return rv;
   6259     }
   6260 
   6261     BCM_IF_ERROR_RETURN(_bcm_tr3_l2_cbl_init(unit));
   6262 
   6263     /* Create callback data structure */
   6264     _bcm_tr3_l2_data[unit] = sal_alloc(sizeof(*_bcm_tr3_l2_data[unit]),
   6265                                        "BCM TR3 L2 callback data");
   6266     if (NULL == _bcm_tr3_l2_data[unit]) {
   6267         return BCM_E_MEMORY;
   6268     }
   6269     sal_memset(_bcm_tr3_l2_data[unit], 0, sizeof(*_bcm_tr3_l2_data[unit]));
   6270 
   6271     if (SOC_CONTROL(unit)->l2x_age_interval != 0) {
   6272         SOC_IF_ERROR_RETURN(soc_tr3_l2_bulk_age_stop(unit));
   6273     }
   6274 
   6275     /* L2 book keeping info init */
   6276     BCM_IF_ERROR_RETURN(_bcm_tr3_l2_bookkeeping_info_init(unit));
   6277 
   6278     if(soc_property_get(unit, spn_RUN_L2_SW_AGING, 0)) {
   6279         SOC_IF_ERROR_RETURN(soc_tr3_l2_bulk_age_start(unit, 0));
   6280     }
   6281     if (soc_feature(unit, soc_feature_l2_overflow)) {
   6282         if(soc_property_get(unit, spn_L2_OVERFLOW_EVENT, 0)) {
   6283             SOC_CONTROL_LOCK(unit);
   6284             SOC_CONTROL(unit)->l2_overflow_enable = TRUE;
   6285             SOC_CONTROL_UNLOCK(unit);
   6286         }
   6287     }
   6288     _bcm_tr3_l2_init[unit] = 1; /* some positive value */
   6289 
   6290 
   6291     BCM_IF_ERROR_RETURN(_bcm_tr_l2_station_control_init(unit));
   6292 
   6293 #ifdef BCM_WARM_BOOT_SUPPORT
   6294     if (SOC_WARM_BOOT(unit)) {
   6295         BCM_IF_ERROR_RETURN(_bcm_tr_l2_station_reload(unit));
   6296         BCM_IF_ERROR_RETURN(_bcm_tr3_l2_reinit(unit));
   6297 
   6298     }
   6299 #endif
   6300 
   6301     return BCM_E_NONE;
   6302 }
   6303 
   6304 /*
   6305  * Function:
   6306  *      bcm_tr3_l2_clear
   6307  * Purpose:
   6308  *      Clear the BCM L2 subsystem.
   6309  * Parameters:
   6310  *      unit - (IN) Unit number.
   6311  * Returns:
   6312  *      BCM_E_xxx
   6313  * Notes:
   6314  */
   6315 int 
   6316 bcm_tr3_l2_clear(int unit)
   6317 {
   6318     BCM_TR3_L2_INIT(unit);
   6319 
   6320     /* Clear the HW state and associated SW data */
   6321     BCM_IF_ERROR_RETURN(_bcm_tr3_l2_hw_init(unit));
   6322 
   6323     /* Stop l2x thread if callback registration started it. */
   6324     if (_bcm_tr3_l2_data[unit]->flags & _BCM_TR3_L2X_THREAD_STOP) {
   6325         BCM_IF_ERROR_RETURN(soc_tr3_l2x_stop(unit));
   6326     }
   6327 
   6328     /* Clear registered callbacks from _bcm_tr3_l2_data structure */
   6329     _bcm_tr3_l2_data[unit]->cb_count = 0;
   6330     _bcm_tr3_l2_data[unit]->flags = 0;
   6331     sal_memset(&_bcm_tr3_l2_data[unit]->cb, 0,
   6332                sizeof(_bcm_tr3_l2_data[unit]->cb));
   6333 
   6334     _bcm_tr3_l2_init[unit] = 1;
   6335     return BCM_E_NONE;
   6336 }
   6337 
   6338 /*
   6339  * Function:
   6340  *      bcm_tr3_l2_detach
   6341  * Purpose:
   6342  *      Finalize the BCM L2 subsystem.
   6343  * Parameters:
   6344  *      unit - (IN) Unit number.
   6345  * Returns:
   6346  *      BCM_E_xxx
   6347  * Notes:
   6348  */
   6349 int 
   6350 bcm_tr3_l2_detach(int unit)
   6351 {
   6352     int frozen;
   6353     int mem_idx;
   6354 
   6355 #ifdef BCM_WARM_BOOT_SUPPORT
   6356     if (SOC_WARM_BOOT(unit)) {
   6357         _bcm_tr3_l2_init[unit] = 0;
   6358         return BCM_E_NONE;
   6359     }
   6360 #endif /* BCM_WARM_BOOT_SUPPORT */
   6361 
   6362     /* Verify the table is not frozen */
   6363     BCM_IF_ERROR_RETURN(soc_tr3_l2_is_frozen(unit, &frozen));
   6364     if (TRUE == frozen) {
   6365         return BCM_E_BUSY;
   6366     }
   6367 
   6368     if (_tr3_mbi_entries[unit] != NULL) {
   6369         sal_free(_tr3_mbi_entries[unit]);
   6370         _tr3_mbi_entries[unit] = NULL;
   6371     }
   6372  
   6373     /* Deallocate resources used by station control support. */
   6374     BCM_IF_ERROR_RETURN(_bcm_tr_l2_station_control_deinit(unit));
   6375 
   6376     /* Deallocate _bcm_tr3_l2_data structure if callbacks were registered */
   6377     if (NULL != _bcm_tr3_l2_data[unit]) {
   6378         if (NULL != _bcm_tr3_l2_data[unit]->l2_mutex) {
   6379             sal_mutex_destroy(_bcm_tr3_l2_data[unit]->l2_mutex);
   6380         }
   6381         sal_free(_bcm_tr3_l2_data[unit]);
   6382         _bcm_tr3_l2_data[unit] = NULL;
   6383     }
   6384 
   6385     /* Deallocate memory acceration structures */
   6386     for (mem_idx = _BCM_TR3_L2_MEM_L2_ENTRY_1;
   6387          mem_idx < _BCM_TR3_L2_MEM_NUM;
   6388          mem_idx++) {
   6389         if (NULL != _bcm_tr3_l2_memacc_list[unit][mem_idx]) {
   6390             sal_free(_bcm_tr3_l2_memacc_list[unit][mem_idx]);
   6391             _bcm_tr3_l2_memacc_list[unit][mem_idx] = NULL;
   6392         }
   6393     }
   6394 
   6395     _bcm_tr3_l2_init[unit] = 0;
   6396     return BCM_E_NONE;
   6397 }
   6398 
   6399 /*
   6400  * Function:
   6401  *      bcm_tr3_l2_addr_add
   6402  * Purpose:
   6403  *      Add an L2 address entry to the specified device.
   6404  * Parameters:
   6405  *      unit - (IN) Unit number.
   6406  *      l2addr - (IN) Pointer to bcm_l2_addr_t containing all valid fields.
   6407  * Returns:
   6408  *      BCM_E_xxx
   6409  * Notes:
   6410  */
   6411 int 
   6412 bcm_tr3_l2_addr_add(int unit, bcm_l2_addr_t *l2addr)
   6413 {
   6414     _bcm_tr3_l2_entries_t l2_entries, l2_entries_lookup;
   6415     l2_combo_entry_t ovf_entry;
   6416     uint32 key_ent[SOC_MAX_MEM_WORDS], key_ovf[SOC_MAX_MEM_WORDS];
   6417     soc_mem_t mem_type;
   6418     int rv, mb_index = 0;
   6419     uint8 l2_flags;
   6420 
   6421     BCM_TR3_L2_INIT(unit);
   6422 
   6423     /* Input parameters check. */
   6424     if (NULL == l2addr) {
   6425         return (BCM_E_PARAM);
   6426     }
   6427 
   6428     if (l2addr->flags & BCM_L2_LOCAL_CPU) {
   6429         l2addr->port = CMIC_PORT(unit);
   6430         BCM_IF_ERROR_RETURN(bcm_esw_stk_modid_get(unit, &l2addr->modid));
   6431     }
   6432 
   6433     if (l2addr->flags & BCM_L2_TRUNK_MEMBER) {
   6434         BCM_IF_ERROR_RETURN(_bcm_trunk_id_validate(unit, l2addr->tgid));
   6435     }
   6436 
   6437     if (SOC_L2X_GROUP_ENABLE_GET(unit)) {
   6438         if (soc_feature(unit, soc_feature_extended_address_class)) {
   6439             if ((l2addr->group > SOC_EXT_ADDR_CLASS_MAX(unit)) ||
   6440                 (l2addr->group < 0)) {
   6441                 return (BCM_E_PARAM);
   6442             }
   6443         } else if ((l2addr->group > SOC_ADDR_CLASS_MAX(unit)) || 
   6444             (l2addr->group < 0)) {
   6445             return (BCM_E_PARAM);
   6446         }
   6447         if (!BCM_PBMP_IS_NULL(l2addr->block_bitmap)) {
   6448             return (BCM_E_PARAM);
   6449         }
   6450     } else {
   6451         if (l2addr->group)  {
   6452             return (BCM_E_PARAM);
   6453         }
   6454     }
   6455     
   6456     if (l2addr->flags & BCM_L2_L3LOOKUP) {
   6457          BCM_IF_ERROR_RETURN(_bcm_tr3_l2_myStation_add(unit, l2addr));
   6458     }
   6459 
   6460     /* Does the entry exist already? */
   6461     sal_memset(&l2_entries_lookup, 0, sizeof (l2_entries_lookup));
   6462     sal_memset(&l2_entries, 0, sizeof (l2_entries));
   6463     l2_entries.entry_flags = _BCM_TR3_L2_SELECT_ALL(unit);
   6464     BCM_IF_ERROR_RETURN(_bcm_tr3_l2api_to_l2hw(unit, &l2_entries,
   6465                                                l2addr, FALSE));
   6466 
   6467     /* Store the flags which indicates which memory that the entry should go */
   6468     l2_flags = l2_entries.entry_flags;
   6469 
   6470     /* For lookup purpose set flags to ALL, so that search is done in
   6471      * all the 4 possible tables
   6472      */
   6473     l2_entries.entry_flags =_BCM_TR3_L2_SELECT_ALL(unit);
   6474 
   6475     _BCM_ALL_L2X_MEM_LOCK(unit);
   6476     rv = _bcm_tr3_l2_entries_lookup(unit, &l2_entries, &l2_entries_lookup);
   6477 
   6478     /* Restore the flags back to original value */
   6479     l2_entries.entry_flags = l2_flags;
   6480 
   6481     if (BCM_E_NOT_FOUND == rv) {
   6482         l2_entries_lookup.entry_flags = 0; /* No found entries */
   6483     } else if (BCM_FAILURE(rv)) {
   6484         _BCM_ALL_L2X_MEM_UNLOCK(unit);
   6485         return rv;
   6486     }
   6487 
   6488     if (0 != (l2_entries_lookup.entry_flags & l2_entries.entry_flags)) {
   6489         /* The existing location is capable of holding the requested info,
   6490          * so overwrite it.  Mark the current table location as the
   6491          * only one of interest.
   6492          */
   6493         l2_entries.entry_flags = l2_entries_lookup.entry_flags;
   6494     }
   6495 
   6496     if (!SOC_L2X_GROUP_ENABLE_GET(unit)) {
   6497         /* Mac blocking, attempt to associate with bitmap entry */
   6498         rv = _bcm_tr3_mac_block_insert(unit, l2addr->block_bitmap,
   6499                                        &mb_index);
   6500         if (BCM_E_NONE != rv) {
   6501             _BCM_ALL_L2X_MEM_UNLOCK(unit);
   6502             return rv;
   6503         }
   6504         _bcm_tr3_l2hw_entries_field32_set(unit, &l2_entries,
   6505                       _BCM_TR3_L2_MEMACC_MAC_BLOCK_INDEX, mb_index);
   6506     }
   6507 
   6508     rv = BCM_E_FULL;
   6509     /* In order of efficiency? */
   6510     if (l2_entries.entry_flags & _BCM_TR3_L2_SELECT_L2_ENTRY_1) {
   6511         rv = soc_mem_insert_return_old(unit, L2_ENTRY_1m, MEM_BLOCK_ANY, 
   6512                                        (void *)&(l2_entries.l2_entry_1),
   6513                                        (void *)&(l2_entries.l2_entry_1));
   6514     }
   6515     if ((l2_entries.entry_flags & _BCM_TR3_L2_SELECT_EXT_L2_ENTRY_1) &&
   6516         (BCM_E_FULL == rv)) {
   6517         rv = soc_mem_insert_return_old(unit, EXT_L2_ENTRY_1m, MEM_BLOCK_ANY, 
   6518                                        (void *)&(l2_entries.ext_l2_entry_1),
   6519                                        (void *)&(l2_entries.ext_l2_entry_1));
   6520     }
   6521     if ((l2_entries.entry_flags & _BCM_TR3_L2_SELECT_L2_ENTRY_2) &&
   6522         (BCM_E_FULL == rv)) {
   6523         rv = soc_mem_insert_return_old(unit, L2_ENTRY_2m, MEM_BLOCK_ANY, 
   6524                                        (void *)&(l2_entries.l2_entry_2),
   6525                                        (void *)&(l2_entries.l2_entry_2));
   6526     }
   6527     if ((l2_entries.entry_flags & _BCM_TR3_L2_SELECT_EXT_L2_ENTRY_2) &&
   6528         (BCM_E_FULL == rv)) {
   6529         rv = soc_mem_insert_return_old(unit, EXT_L2_ENTRY_2m, MEM_BLOCK_ANY, 
   6530                                        (void *)&(l2_entries.ext_l2_entry_2),
   6531                                        (void *)&(l2_entries.ext_l2_entry_2));
   6532     }
   6533 
   6534     if ((BCM_E_FULL == rv) && (l2addr->flags & BCM_L2_REPLACE_DYNAMIC)) {
   6535         /* coverity[stack_use_callee] */
   6536         /* coverity[stack_use_overflow] */
   6537         _BCM_ALL_L2X_MEM_UNLOCK(unit);
   6538         rv = _bcm_tr3_l2_hash_dynamic_replace(unit, &l2_entries);
   6539         _BCM_ALL_L2X_MEM_LOCK(unit);
   6540     } else if ((BCM_E_FULL == rv) && (l2addr->flags & BCM_L2_ADD_OVERRIDE_PENDING)) {
   6541         /* coverity[stack_use_callee] */
   6542         /* coverity[stack_use_overflow] */
   6543         _BCM_ALL_L2X_MEM_UNLOCK(unit);
   6544         rv = _bcm_tr3_l2_hash_pending_override(unit, &l2_entries);
   6545         _BCM_ALL_L2X_MEM_LOCK(unit);
   6546     } else if (rv == BCM_E_EXISTS) {
   6547         if (!SOC_L2X_GROUP_ENABLE_GET(unit)) {
   6548             mb_index = _bcm_tr3_l2hw_entries_field32_get(unit, &l2_entries,
   6549                                 _BCM_TR3_L2_MEMACC_MAC_BLOCK_INDEX);
   6550             _bcm_tr3_mac_block_delete(unit, mb_index);
   6551         }
   6552         rv = BCM_E_NONE;
   6553     }
   6554 
   6555     if ((rv < 0) && !SOC_L2X_GROUP_ENABLE_GET(unit)) {
   6556          _bcm_tr3_mac_block_delete(unit, mb_index);
   6557     }
   6558 
   6559     if (BCM_SUCCESS(rv)) {
   6560         if (soc_feature(unit, soc_feature_l2_overflow) &&
   6561             (l2addr->flags & BCM_L2_ENTRY_OVERFLOW)) {
   6562             /* Check if this entry is in the overflow memory and resume process */
   6563             if (soc_tr3_l2_overflow_entry_get(unit, &ovf_entry, &mem_type)) {
   6564                 _BCM_ALL_L2X_MEM_UNLOCK(unit);
   6565                 return BCM_E_INTERNAL;
   6566             }
   6567             sal_memset(key_ent, 0, sizeof(key_ent));
   6568             sal_memset(key_ovf, 0, sizeof(key_ovf));
   6569             /* Extract and compare key only (for matching mem types) */
   6570             if ((mem_type == L2_ENTRY_1m) &&
   6571                 (l2_entries.entry_flags & _BCM_TR3_L2_SELECT_L2_ENTRY_1)) {
   6572                 soc_mem_field_get(unit, mem_type, l2_entries.l2_entry_1.entry_data,
   6573                                   L2__KEYf, key_ent);
   6574                 soc_mem_field_get(unit, mem_type, ovf_entry.words, L2__KEYf,
   6575                                   key_ovf);
   6576                 if (sal_memcmp(key_ent, key_ovf, sizeof(key_ent))) {
   6577                     _BCM_ALL_L2X_MEM_UNLOCK(unit);
   6578                     return BCM_E_PARAM;
   6579                 } else {
   6580                     if (soc_tr3_l2_overflow_start(unit)) {
   6581                         _BCM_ALL_L2X_MEM_UNLOCK(unit);
   6582                         return BCM_E_INTERNAL;
   6583                     }
   6584                 }
   6585             } else if ((mem_type == L2_ENTRY_2m) &&
   6586                (l2_entries.entry_flags & _BCM_TR3_L2_SELECT_L2_ENTRY_2)) {
   6587                 soc_mem_field_get(unit, mem_type, l2_entries.l2_entry_2.entry_data,
   6588                                   L2__KEYf, key_ent);
   6589                 soc_mem_field_get(unit, mem_type, ovf_entry.words, L2__KEY_0f,
   6590                                   key_ovf);
   6591                 if (sal_memcmp(key_ent, key_ovf, sizeof(key_ent))) {
   6592                     _BCM_ALL_L2X_MEM_UNLOCK(unit);
   6593                     return BCM_E_PARAM;
   6594                 } else {
   6595                     if (soc_tr3_l2_overflow_start(unit)) {
   6596                         _BCM_ALL_L2X_MEM_UNLOCK(unit);
   6597                         return BCM_E_INTERNAL;
   6598                     }
   6599                 }
   6600             } else {
   6601                 _BCM_ALL_L2X_MEM_UNLOCK(unit);
   6602                 return BCM_E_PARAM;
   6603             }
   6604         }
   6605 
   6606         if ((0 != l2_entries_lookup.entry_flags) &&
   6607             (0 == (l2_entries_lookup.entry_flags & l2_entries.entry_flags))) {
   6608             rv = _bcm_tr3_l2_entries_delete(unit, &l2_entries_lookup);
   6609             
   6610             if (!SOC_L2X_GROUP_ENABLE_GET(unit)) {
   6611                 mb_index =
   6612                     _bcm_tr3_l2hw_entries_field32_get(unit, &l2_entries_lookup,
   6613                              _BCM_TR3_L2_MEMACC_MAC_BLOCK_INDEX);
   6614                 _bcm_tr3_mac_block_delete(unit, mb_index);
   6615             }
   6616         }
   6617     }
   6618     _BCM_ALL_L2X_MEM_UNLOCK(unit);
   6619 
   6620     return rv;
   6621 }
   6622 
   6623 /*
   6624  * Function:
   6625  *      bcm_tr3_l2_addr_delete
   6626  * Purpose:
   6627  *      Delete an L2 address entry from the specified device.
   6628  * Parameters:
   6629  *      unit - (IN) Unit number.
   6630  *      mac - (IN) MAC address to delete
   6631  *      vid - (IN) VLAN id
   6632  * Returns:
   6633  *      BCM_E_xxx
   6634  * Notes:
   6635  */
   6636 int 
   6637 bcm_tr3_l2_addr_delete(int unit, bcm_mac_t mac, bcm_vlan_t vid)
   6638 {
   6639     bcm_l2_addr_t  l2addr;
   6640     _bcm_tr3_l2_entries_t l2_entries, l2_entries_lookup;
   6641     int            l2_index, mb_index;
   6642     int            rv = BCM_E_NONE;
   6643 
   6644     BCM_TR3_L2_INIT(unit);
   6645 
   6646     if (BCM_VLAN_VALID(vid)) {
   6647         /* Flush any myStation entry */
   6648         rv = _bcm_tr3_l2_myStation_delete(unit, mac, vid, &l2_index);
   6649         if ((rv != BCM_E_NOT_FOUND) && (rv != BCM_E_FULL)) {
   6650             if (rv != BCM_E_NONE) {
   6651                 return rv;
   6652             }
   6653         }
   6654     }
   6655 
   6656     bcm_l2_addr_t_init(&l2addr, mac, vid);
   6657 
   6658     /* Does the entry exist already? */
   6659     sal_memset(&l2_entries_lookup, 0, sizeof (l2_entries_lookup));
   6660     sal_memset(&l2_entries, 0, sizeof (l2_entries));
   6661     l2_entries.entry_flags = _BCM_TR3_L2_SELECT_ALL(unit);
   6662     BCM_IF_ERROR_RETURN(_bcm_tr3_l2api_to_l2hw(unit, &l2_entries,
   6663                                                &l2addr, TRUE));
   6664 
   6665     _BCM_ALL_L2X_MEM_LOCK(unit);
   6666     rv = _bcm_tr3_l2_entries_lookup(unit, (void *)&l2_entries,
   6667                                     (void *)&l2_entries_lookup);
   6668 
   6669     if (BCM_E_NONE != rv) {
   6670         _BCM_ALL_L2X_MEM_UNLOCK(unit);
   6671         return rv;
   6672     }
   6673 
   6674     if (!SOC_L2X_GROUP_ENABLE_GET(unit)) {
   6675         mb_index = _bcm_tr3_l2hw_entries_field32_get(unit,
   6676                                                      &l2_entries_lookup,
   6677                             _BCM_TR3_L2_MEMACC_MAC_BLOCK_INDEX);
   6678         _bcm_tr3_mac_block_delete(unit, mb_index);
   6679     }
   6680 
   6681     rv = _bcm_tr3_l2_entries_delete(unit, &l2_entries_lookup);
   6682     _BCM_ALL_L2X_MEM_UNLOCK(unit);
   6683 
   6684     return rv;
   6685 }
   6686 
   6687 /*
   6688  * Function:
   6689  *      _bcm_tr3_delete_replace_flags_convert
   6690  * Description:
   6691  *      A helper function to all delete_by APIs to use bcm_l2_replace. 
   6692  *      Converts L2 flags to L2 replace flags compatable to use with bcm_l2_replace
   6693  * Parameters:
   6694  *      unit        [IN]- device unit
   6695  *      flags       [IN] - BCM_L2_DELETE_XXX
   6696  *      repl_flags  [OUT]- Vflags BCM_L2_REPLACE_XXX
   6697  * Returns:
   6698  *      BCM_E_XXX
   6699  */
   6700 
   6701 STATIC int 
   6702 _bcm_tr3_delete_replace_flags_convert(int unit, uint32 flags, uint32 *repl_flags)
   6703 {
   6704     uint32 tmp_flags = 0;
   6705 
   6706     if (flags & BCM_L2_REPLACE_AGE){
   6707         tmp_flags = BCM_L2_REPLACE_AGE;
   6708     }else{
   6709         tmp_flags = BCM_L2_REPLACE_DELETE;
   6710     }
   6711 
   6712     if (flags & BCM_L2_DELETE_PENDING) {
   6713         tmp_flags |= BCM_L2_REPLACE_PENDING;
   6714     }
   6715     if (flags & BCM_L2_DELETE_STATIC) {
   6716         tmp_flags |= BCM_L2_REPLACE_MATCH_STATIC; 
   6717     }
   6718     if (flags & BCM_L2_DELETE_NO_CALLBACKS) {
   6719         tmp_flags |= BCM_L2_REPLACE_NO_CALLBACKS;
   6720     }
   6721     if (flags & BCM_L2_LEARN_LIMIT) {
   6722         tmp_flags |= BCM_L2_REPLACE_LEARN_LIMIT;
   6723     }
   6724 
   6725     if ((flags & BCM_L2_REPLACE_MATCH_UC) && (flags & BCM_L2_REPLACE_MATCH_MC))
   6726     {
   6727         /* Both flags are contradictory and can't be set together */
   6728         return BCM_E_PARAM;
   6729     }
   6730 
   6731     if (flags & BCM_L2_REPLACE_MATCH_UC) {
   6732         tmp_flags |= BCM_L2_REPLACE_MATCH_UC;
   6733     }
   6734 
   6735     if (flags & BCM_L2_REPLACE_MATCH_MC) {
   6736         tmp_flags |= BCM_L2_REPLACE_MATCH_MC;
   6737     }
   6738 
   6739     *repl_flags = tmp_flags;
   6740     return BCM_E_NONE;
   6741 }
   6742 
   6743 /*
   6744  * Function:
   6745  *      bcm_tr3_l2_addr_delete_by_port
   6746  * Purpose:
   6747  *      Delete L2 entries associated with a destination module/port.
   6748  * Parameters:
   6749  *      unit - (IN) Unit number.
   6750  *      mod - (IN) <UNDEF>
   6751  *      port - (IN) <UNDEF>
   6752  *      flags - (IN) <UNDEF>
   6753  * Returns:
   6754  *      BCM_E_xxx
   6755  * Notes:
   6756  */
   6757 int 
   6758 bcm_tr3_l2_addr_delete_by_port(int unit, 
   6759     bcm_module_t mod, 
   6760     bcm_port_t port, 
   6761     uint32 flags)
   6762 {
   6763     bcm_l2_addr_t   match_addr;
   6764     uint32          repl_flags;
   6765 
   6766     BCM_TR3_L2_INIT(unit);
   6767     
   6768     sal_memset(&match_addr, 0, sizeof(bcm_l2_addr_t));
   6769     if (!BCM_GPORT_IS_SET(port) && mod == -1) {
   6770         if (!SOC_PORT_VALID(unit, port)) {
   6771             return BCM_E_PORT;
   6772         }
   6773         BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &match_addr.modid));
   6774     } else {
   6775         match_addr.modid = mod;
   6776     }
   6777     match_addr.port = port;
   6778     BCM_IF_ERROR_RETURN
   6779         (_bcm_tr3_delete_replace_flags_convert(unit, flags, &repl_flags));
   6780     repl_flags |= BCM_L2_REPLACE_MATCH_DEST;
   6781     return _bcm_tr3_l2_replace(unit, repl_flags, &match_addr, 0, 0, 0);
   6782 }
   6783 
   6784 /*
   6785  * Function:
   6786  *      bcm_tr3_l2_addr_delete_by_mac
   6787  * Purpose:
   6788  *      Delete L2 entries associated with a MAC address.
   6789  * Parameters:
   6790  *      unit - (IN) Unit number.
   6791  *      mac - (IN) <UNDEF>
   6792  *      flags - (IN) <UNDEF>
   6793  * Returns:
   6794  *      BCM_E_xxx
   6795  * Notes:
   6796  */
   6797 int 
   6798 bcm_tr3_l2_addr_delete_by_mac(int unit, 
   6799     bcm_mac_t mac, 
   6800     uint32 flags)
   6801 {
   6802     bcm_l2_addr_t   match_addr;
   6803     uint32          repl_flags;
   6804 
   6805     BCM_TR3_L2_INIT(unit);
   6806 
   6807     sal_memset(&match_addr, 0, sizeof(bcm_l2_addr_t));
   6808     sal_memcpy(match_addr.mac, mac, sizeof(bcm_mac_t));
   6809     BCM_IF_ERROR_RETURN
   6810         (_bcm_tr3_delete_replace_flags_convert(unit, flags, &repl_flags));
   6811     repl_flags |= BCM_L2_REPLACE_MATCH_MAC;
   6812     BCM_IF_ERROR_RETURN
   6813         (_bcm_tr3_l2_replace(unit, repl_flags|BCM_L2_REPLACE_VPN_TYPE, &match_addr, 0, 0, 0));
   6814     return _bcm_tr3_l2_replace(unit, repl_flags, &match_addr, 0, 0, 0);
   6815 }
   6816 
   6817 /*
   6818  * Function:
   6819  *      bcm_tr3_l2_addr_delete_by_vlan
   6820  * Purpose:
   6821  *      Delete L2 entries associated with a VLAN.
   6822  * Parameters:
   6823  *      unit - (IN) Unit number.
   6824  *      vid - (IN) <UNDEF>
   6825  *      flags - (IN) <UNDEF>
   6826  * Returns:
   6827  *      BCM_E_xxx
   6828  * Notes:
   6829  */
   6830 int 
   6831 bcm_tr3_l2_addr_delete_by_vlan(int unit, 
   6832     bcm_vlan_t vid, 
   6833     uint32 flags)
   6834 {
   6835     bcm_l2_addr_t   match_addr;
   6836     uint32          repl_flags;
   6837 
   6838     BCM_TR3_L2_INIT(unit);
   6839 
   6840     sal_memset(&match_addr, 0, sizeof(bcm_l2_addr_t));
   6841     match_addr.vid = vid;
   6842     BCM_IF_ERROR_RETURN
   6843         (_bcm_tr3_delete_replace_flags_convert(unit, flags, &repl_flags));
   6844     repl_flags |= BCM_L2_REPLACE_MATCH_VLAN;
   6845     return _bcm_tr3_l2_replace(unit, repl_flags, &match_addr, 0, 0, 0);
   6846 }
   6847 
   6848 /*
   6849  * Function:
   6850  *      bcm_tr3_l2_addr_delete_by_trunk
   6851  * Purpose:
   6852  *      Delete L2 entries associated with a trunk.
   6853  * Parameters:
   6854  *      unit - (IN) Unit number.
   6855  *      tid - (IN) <UNDEF>
   6856  *      flags - (IN) <UNDEF>
   6857  * Returns:
   6858  *      BCM_E_xxx
   6859  * Notes:
   6860  */
   6861 int 
   6862 bcm_tr3_l2_addr_delete_by_trunk(int unit, 
   6863     bcm_trunk_t tid, 
   6864     uint32 flags)
   6865 {
   6866     bcm_l2_addr_t   match_addr;
   6867     uint32          repl_flags;
   6868 
   6869     BCM_TR3_L2_INIT(unit);
   6870 
   6871     sal_memset(&match_addr, 0, sizeof(bcm_l2_addr_t));
   6872     match_addr.tgid = tid;
   6873     match_addr.flags |= BCM_L2_TRUNK_MEMBER;
   6874     BCM_IF_ERROR_RETURN
   6875         (_bcm_tr3_delete_replace_flags_convert(unit, flags, &repl_flags));
   6876     repl_flags |= BCM_L2_REPLACE_MATCH_DEST;
   6877     return _bcm_tr3_l2_replace(unit, repl_flags, &match_addr, 0, 0, 0); 
   6878 }
   6879 
   6880 /*
   6881  * Function:
   6882  *      bcm_tr3_l2_addr_delete_by_mac_port
   6883  * Purpose:
   6884  *      Delete L2 entries associated with a MAC address and a
   6885  *      destination module/port.
   6886  * Parameters:
   6887  *      unit - (IN) Unit number.
   6888  *      mac - (IN) <UNDEF>
   6889  *      mod - (IN) <UNDEF>
   6890  *      port - (IN) <UNDEF>
   6891  *      flags - (IN) <UNDEF>
   6892  * Returns:
   6893  *      BCM_E_xxx
   6894  * Notes:
   6895  */
   6896 int 
   6897 bcm_tr3_l2_addr_delete_by_mac_port(int unit, 
   6898     bcm_mac_t mac, 
   6899     bcm_module_t mod, 
   6900     bcm_port_t port, 
   6901     uint32 flags)
   6902 {
   6903     bcm_l2_addr_t   match_addr;
   6904     uint32          repl_flags;
   6905 
   6906     BCM_TR3_L2_INIT(unit);
   6907 
   6908     sal_memset(&match_addr, 0, sizeof(bcm_l2_addr_t));
   6909     sal_memcpy(match_addr.mac, mac, sizeof(bcm_mac_t));
   6910     if (!BCM_GPORT_IS_SET(port) && mod == -1) {
   6911         if (!SOC_PORT_VALID(unit, port)) {
   6912             return BCM_E_PORT;
   6913         }
   6914         BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &match_addr.modid));
   6915     } else {
   6916         match_addr.modid = mod;
   6917     }
   6918     match_addr.port = port;
   6919     BCM_IF_ERROR_RETURN
   6920         (_bcm_tr3_delete_replace_flags_convert(unit, flags, &repl_flags));
   6921     repl_flags |= BCM_L2_REPLACE_MATCH_MAC | BCM_L2_REPLACE_MATCH_DEST;
   6922     return _bcm_tr3_l2_replace(unit, repl_flags, &match_addr, 0, 0, 0);
   6923 }
   6924 
   6925 /*
   6926  * Function:
   6927  *      bcm_tr3_l2_addr_delete_by_vlan_port
   6928  * Purpose:
   6929  *      Delete L2 entries associated with a VLAN and a destination
   6930  *      module/port.
   6931  * Parameters:
   6932  *      unit - (IN) Unit number.
   6933  *      vid - (IN) <UNDEF>
   6934  *      mod - (IN) <UNDEF>
   6935  *      port - (IN) <UNDEF>
   6936  *      flags - (IN) <UNDEF>
   6937  * Returns:
   6938  *      BCM_E_xxx
   6939  * Notes:
   6940  */
   6941 int 
   6942 bcm_tr3_l2_addr_delete_by_vlan_port(int unit, 
   6943     bcm_vlan_t vid, 
   6944     bcm_module_t mod, 
   6945     bcm_port_t port, 
   6946     uint32 flags)
   6947 {
   6948     bcm_l2_addr_t   match_addr;
   6949     uint32          repl_flags;
   6950 
   6951     BCM_TR3_L2_INIT(unit);
   6952 
   6953     sal_memset(&match_addr, 0, sizeof(bcm_l2_addr_t));
   6954     match_addr.vid = vid;
   6955     if (!BCM_GPORT_IS_SET(port) && mod == -1) {
   6956         if (!SOC_PORT_VALID(unit, port)) {
   6957             return BCM_E_PORT;
   6958         }
   6959         BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &match_addr.modid));
   6960     } else {
   6961         match_addr.modid = mod;
   6962     }
   6963     match_addr.port = port;
   6964     BCM_IF_ERROR_RETURN
   6965         (_bcm_tr3_delete_replace_flags_convert(unit, flags, &repl_flags));
   6966     repl_flags |= BCM_L2_REPLACE_MATCH_VLAN |BCM_L2_REPLACE_MATCH_DEST;
   6967     return _bcm_tr3_l2_replace(unit, repl_flags, &match_addr, 0, 0, 0);
   6968 }
   6969 
   6970 /*
   6971  * Function:
   6972  *      bcm_tr3_l2_addr_delete_by_vlan_trunk
   6973  * Purpose:
   6974  *      Delete L2 entries associated with a VLAN and a destination
   6975  *      module/port.
   6976  * Parameters:
   6977  *      unit - (IN) Unit number.
   6978  *      vid - (IN) <UNDEF>
   6979  *      tid - (IN) <UNDEF>
   6980  *      flags - (IN) <UNDEF>
   6981  * Returns:
   6982  *      BCM_E_xxx
   6983  * Notes:
   6984  */
   6985 int 
   6986 bcm_tr3_l2_addr_delete_by_vlan_trunk(int unit, 
   6987     bcm_vlan_t vid, 
   6988     bcm_trunk_t tid, 
   6989     uint32 flags)
   6990 {
   6991     bcm_l2_addr_t   match_addr;
   6992     uint32          repl_flags;
   6993 
   6994     BCM_TR3_L2_INIT(unit);
   6995 
   6996     sal_memset(&match_addr, 0, sizeof(bcm_l2_addr_t));
   6997     match_addr.vid = vid;
   6998     match_addr.tgid = tid;
   6999     match_addr.flags |= BCM_L2_TRUNK_MEMBER;
   7000     BCM_IF_ERROR_RETURN
   7001         (_bcm_tr3_delete_replace_flags_convert(unit, flags, &repl_flags));
   7002     repl_flags |= BCM_L2_REPLACE_MATCH_VLAN | BCM_L2_REPLACE_MATCH_DEST;
   7003     return _bcm_tr3_l2_replace(unit, repl_flags, &match_addr, 0, 0, 0);
   7004 }
   7005 
   7006 /*
   7007  * Function:
   7008  *      _bcm_tr3_l2_addr_get
   7009  * Purpose:
   7010  *      Check if an L2 entry is present in the L2 table.
   7011  * Parameters:
   7012  *      unit          - (IN) Unit number.
   7013  *      mac_addr      - (IN) input MAC address to search
   7014  *      vid           - (IN) input VLAN ID to search
   7015  *      check_l2_only - (IN) only check if the target exist in L2 table.
   7016  *      l2addr        - (OUT) Pointer to bcm_l2_addr_t structureI
   7017  *                            to receive result
   7018  * Returns:
   7019  *      BCM_E_xxx
   7020  * Notes:
   7021  */
   7022 int 
   7023 _bcm_tr3_l2_addr_get(int unit, bcm_mac_t mac_addr, bcm_vlan_t vid, 
   7024                      int check_l2_only, bcm_l2_addr_t *l2addr)
   7025 {
   7026     _bcm_tr3_l2_entries_t l2_entries, l2_entries_lookup;
   7027     int          rv, rval;
   7028 
   7029     /* First check if in My Station table in case it's an L3-enabled
   7030      * entry.
   7031      */
   7032     if (!check_l2_only) {
   7033         rv = _bcm_tr3_l2_myStation_get(unit, mac_addr, vid, l2addr);
   7034         if (BCM_E_NOT_FOUND != rv) {
   7035             return rv;
   7036         }
   7037     }
   7038 
   7039     bcm_l2_addr_t_init(l2addr, mac_addr, vid);
   7040 
   7041     /* Find if the entry exists */
   7042     sal_memset(&l2_entries_lookup, 0, sizeof (l2_entries_lookup));
   7043     sal_memset(&l2_entries, 0, sizeof (l2_entries));
   7044     l2_entries.entry_flags = _BCM_TR3_L2_SELECT_ALL(unit);
   7045     BCM_IF_ERROR_RETURN(_bcm_tr3_l2api_to_l2hw(unit, &l2_entries,
   7046                                                l2addr, TRUE));
   7047 
   7048     _BCM_ALL_L2X_MEM_LOCK(unit);
   7049     rv = _bcm_tr3_l2_entries_lookup(unit, (void *)&l2_entries,
   7050                                     (void *)&l2_entries_lookup);
   7051 
   7052     if (BCM_E_NONE != rv) {
   7053         _BCM_ALL_L2X_MEM_UNLOCK(unit);
   7054         return rv;
   7055     }
   7056 
   7057     if (check_l2_only) {
   7058         _BCM_ALL_L2X_MEM_UNLOCK(unit);
   7059         return rv;
   7060     }
   7061     
   7062     /* Translate back to API abstraction */
   7063     rv = _bcm_tr3_l2api_from_l2hw(unit, l2addr, &l2_entries_lookup);
   7064     _BCM_ALL_L2X_MEM_UNLOCK(unit);
   7065 
   7066     /* Translate l2mc index */
   7067     BCM_IF_ERROR_RETURN(
   7068         bcm_esw_switch_control_get(unit, bcmSwitchL2McIdxRetType, &rval));
   7069     if ((rval) && BCM_MAC_IS_MCAST(l2addr->mac) &&
   7070                   !(_BCM_MULTICAST_IS_SET(l2addr->l2mc_group))) {
   7071        _BCM_MULTICAST_GROUP_SET(l2addr->l2mc_group, _BCM_MULTICAST_TYPE_L2,
   7072                                                             l2addr->l2mc_group);
   7073     }
   7074 
   7075     return rv;
   7076 }
   7077 
   7078 int 
   7079 bcm_tr3_l2_addr_get(int unit, bcm_mac_t mac_addr, bcm_vlan_t vid, 
   7080                     bcm_l2_addr_t *l2addr)
   7081 {
   7082     return _bcm_tr3_l2_addr_get(unit, mac_addr, vid, FALSE, l2addr);
   7083 }
   7084 
   7085 /*
   7086  * Function:
   7087  *      _bcm_tr3_l2_addr_callback
   7088  * Description:
   7089  *      Callback used with chip addr registration functions.
   7090  *      This callback calls all the top level client callbacks.
   7091  * Parameters:
   7092  *      unit - StrataSwitch PCI device unit number (driver internal).
   7093  *      l2addr
   7094  *      insert
   7095  *      userdata
   7096  * Returns:
   7097  */
   7098 STATIC void
   7099 _bcm_tr3_l2_addr_callback(int unit, bcm_l2_addr_t *l2addr, int insert,
   7100                           void *userdata)
   7101 {
   7102     _bcm_tr3_l2_data_t *ad = _bcm_tr3_l2_data[unit];
   7103     int                i;
   7104 
   7105     if (ad->l2_mutex == NULL) {
   7106         return;
   7107     }
   7108 
   7109     BCM_TR3_L2_CB_LOCK(unit);
   7110     for(i = 0; i < _BCM_TR3_L2_CB_MAX; i++) {
   7111         if(ad->cb[i].fn) {
   7112             ad->cb[i].fn(unit, l2addr, insert, ad->cb[i].fn_data);
   7113         }
   7114     }
   7115     BCM_TR3_L2_CB_UNLOCK(unit);
   7116 }
   7117 
   7118 /*
   7119  * Function:
   7120  *      bcm_tr3_l2_addr_register
   7121  * Purpose:
   7122  *      Register/Unregister a callback routine for BCM L2 subsystem.
   7123  * Parameters:
   7124  *      unit - (IN) Unit number.
   7125  *      callback - (IN) <UNDEF>
   7126  *      userdata - (IN) <UNDEF>
   7127  * Returns:
   7128  *      BCM_E_xxx
   7129  * Notes:
   7130  */
   7131 int 
   7132 bcm_tr3_l2_addr_register(int unit, 
   7133                          bcm_l2_addr_callback_t callback, 
   7134                          void *userdata)
   7135 {
   7136     _bcm_tr3_l2_data_t *ad = _bcm_tr3_l2_data[unit];
   7137     int                i;
   7138 #if defined(BCM_XGS_SWITCH_SUPPORT)
   7139     int rv;
   7140     int usec;
   7141 #endif /* BCM_XGS_SWITCH_SUPPORT */
   7142 
   7143     if (!SOC_IS_XGS_SWITCH(unit)) {
   7144         return BCM_E_UNAVAIL;
   7145     }
   7146 
   7147     BCM_TR3_L2_INIT(unit);
   7148 
   7149     _bcm_tr3_l2_cbs[unit] = _bcm_tr3_l2_addr_callback;
   7150     _bcm_tr3_l2_cb_data[unit] = NULL;
   7151 
   7152     BCM_TR3_L2_CB_MUTEX(unit);
   7153     BCM_TR3_L2_CB_LOCK(unit);
   7154 #if defined(BCM_XGS_SWITCH_SUPPORT)
   7155     /* Start L2x thread if it isn't running already. */
   7156     if (!soc_tr3_l2x_running(unit, NULL, NULL)) {
   7157         usec = (SAL_BOOT_BCMSIM)? BCMSIM_L2XMSG_INTERVAL : 3000000;
   7158         usec = soc_property_get(unit, spn_L2XMSG_THREAD_USEC, usec);
   7159         rv = soc_tr3_l2x_start(unit, 0, usec);
   7160         if ((BCM_FAILURE(rv)) && (rv != BCM_E_UNAVAIL)) {
   7161             _bcm_tr3_l2_cbs[unit] = NULL;
   7162             _bcm_tr3_l2_cb_data[unit] = NULL;
   7163             BCM_TR3_L2_CB_UNLOCK(unit);
   7164             return(rv);
   7165         }
   7166         ad->flags |= _BCM_TR3_L2X_THREAD_STOP;
   7167     }
   7168     if (soc_feature(unit, soc_feature_l2_overflow)) {
   7169         rv = soc_tr3_l2_overflow_start(unit);
   7170         if ((BCM_FAILURE(rv)) && (rv != BCM_E_UNAVAIL)) {
   7171             _bcm_tr3_l2_cbs[unit] = NULL;
   7172             _bcm_tr3_l2_cb_data[unit] = NULL;
   7173             BCM_TR3_L2_CB_UNLOCK(unit);
   7174             return(rv);
   7175         }
   7176     }
   7177 #endif /* BCM_XGS_SWITCH_SUPPORT */
   7178 
   7179     /* See if the function is already registered (with same data) */
   7180     for (i = 0; i < _BCM_TR3_L2_CB_MAX; i++) {
   7181         if (ad->cb[i].fn == callback && ad->cb[i].fn_data == userdata) {
   7182             BCM_TR3_L2_CB_UNLOCK(unit);
   7183             return BCM_E_NONE;
   7184         }
   7185     }
   7186 
   7187     /* Not found; add to list. */
   7188     for (i = 0; i < _BCM_TR3_L2_CB_MAX; i++) {
   7189         if (ad->cb[i].fn == NULL) {
   7190             ad->cb[i].fn = callback;
   7191             ad->cb[i].fn_data = userdata;
   7192             ad->cb_count++;
   7193             break;
   7194         }
   7195     }
   7196 
   7197     BCM_TR3_L2_CB_UNLOCK(unit);
   7198     return i >= _BCM_TR3_L2_CB_MAX ? BCM_E_RESOURCE : BCM_E_NONE;
   7199 }
   7200 
   7201 /*
   7202  * Function:
   7203  *      bcm_tr3_l2_addr_unregister
   7204  * Purpose:
   7205  *      Register/Unregister a callback routine for BCM L2 subsystem.
   7206  * Parameters:
   7207  *      unit - (IN) Unit number.
   7208  *      callback - (IN) <UNDEF>
   7209  *      userdata - (IN) <UNDEF>
   7210  * Returns:
   7211  *      BCM_E_xxx
   7212  * Notes:
   7213  */
   7214 int 
   7215 bcm_tr3_l2_addr_unregister(int unit, 
   7216                            bcm_l2_addr_callback_t callback, 
   7217                            void *userdata)
   7218 {
   7219     _bcm_tr3_l2_data_t *ad = _bcm_tr3_l2_data[unit];
   7220     int                rv = BCM_E_NOT_FOUND;
   7221     int                i;
   7222 
   7223     if (!SOC_IS_XGS_SWITCH(unit)) {
   7224         return BCM_E_UNAVAIL;
   7225     }
   7226 
   7227     BCM_TR3_L2_INIT(unit);
   7228     BCM_TR3_L2_CB_MUTEX(unit);
   7229     BCM_TR3_L2_CB_LOCK(unit);
   7230 
   7231     for (i = 0; i < _BCM_TR3_L2_CB_MAX; i++) {
   7232         if((ad->cb[i].fn == callback) && (ad->cb[i].fn_data == userdata)) {
   7233             rv = BCM_E_NONE;
   7234             ad->cb[i].fn = NULL;
   7235             ad->cb[i].fn_data = NULL;
   7236             ad->cb_count--;
   7237             if (ad->cb_count == 0) {
   7238                 _bcm_tr3_l2_cbs[unit] = NULL;
   7239                 _bcm_tr3_l2_cb_data[unit] = NULL;
   7240 
   7241 #if defined(BCM_XGS_SWITCH_SUPPORT)
   7242                 /* Stop l2x thread if callback registration started it. */
   7243                 if (ad->flags & _BCM_TR3_L2X_THREAD_STOP) {
   7244                     rv = soc_tr3_l2x_stop(unit);
   7245                     ad->flags &= ~_BCM_TR3_L2X_THREAD_STOP;
   7246                 }
   7247 #endif /* BCM_XGS_SWITCH_SUPPORT */
   7248             }
   7249         }
   7250     }
   7251 
   7252     BCM_TR3_L2_CB_UNLOCK(unit);
   7253     return (rv);
   7254 }
   7255 
   7256 /*
   7257  * Function:
   7258  *      bcm_tr3_l2_age_timer_set
   7259  * Purpose:
   7260  *      Set/Get the age timer.
   7261  * Parameters:
   7262  *      unit - (IN) Unit number.
   7263  *      age_seconds - (IN) <UNDEF>
   7264  * Returns:
   7265  *      BCM_E_xxx
   7266  * Notes:
   7267  */
   7268 int 
   7269 bcm_tr3_l2_age_timer_set(int unit, int age_seconds)
   7270 {
   7271     int rv, enabled;
   7272     
   7273     if (age_seconds < 0) {
   7274         return BCM_E_PARAM;
   7275     }
   7276     enabled = age_seconds ? 1 : 0;
   7277     rv = SOC_FUNCTIONS(unit)->soc_age_timer_set(unit, age_seconds, enabled);
   7278     return rv; 
   7279 }
   7280 
   7281 /*
   7282  * Function:
   7283  *      bcm_tr3_l2_age_timer_get
   7284  * Purpose:
   7285  *      Set/Get the age timer.
   7286  * Parameters:
   7287  *      unit - (IN) Unit number.
   7288  *      age_seconds - (OUT) <UNDEF>
   7289  * Returns:
   7290  *      BCM_E_xxx
   7291  * Notes:
   7292  */
   7293 int 
   7294 bcm_tr3_l2_age_timer_get(int unit, int *age_seconds)
   7295 {
   7296     int rv, seconds, enabled;
   7297     
   7298     rv = SOC_FUNCTIONS(unit)->soc_age_timer_get(unit, &seconds, &enabled);
   7299     if (enabled) {
   7300         *age_seconds = seconds;
   7301     } else {
   7302         *age_seconds = 0;
   7303     }
   7304     return rv;
   7305 }
   7306 
   7307 /*
   7308  * Function:
   7309  *      bcm_tr3_l2_conflict_get
   7310  * Purpose:
   7311  *      Given an L2 address entry, return existing addresses which
   7312  *      could conflict.
   7313  * Parameters:
   7314  *      unit - (IN) Unit number.
   7315  *      addr - (IN) Pointer to bcm_l2_addr_t structure to seeking conflict
   7316  *      cf_array - (OUT) Array of bcm_l2_addr_t structures to return
   7317  *                       conflicting entries
   7318  *      cf_max - (IN) Maximum entries of supplied cf_array
   7319  *      cf_count - (OUT) Number of conflicting entries returned in cf_array
   7320  * Returns:
   7321  *      BCM_E_xxx
   7322  * Notes:
   7323  */
   7324 int 
   7325 bcm_tr3_l2_conflict_get(int unit, bcm_l2_addr_t *addr,
   7326                         bcm_l2_addr_t *cf_array, int cf_max, int *cf_count)
   7327 {
   7328     uint32 *kt;
   7329     void *entry;
   7330     int rv, index;
   7331     soc_mem_t mem;
   7332     uint32 valid;
   7333     uint8 i, bidx, flag, num_ent;
   7334     _soc_ism_mem_banks_t mem_banks;
   7335     _bcm_tr3_l2_entries_t l2_entries, l2_entries_match;
   7336     uint32 l2_entry[SOC_MAX_MEM_WORDS], result, bucket_index;
   7337     uint32 key_type_1[] = {SOC_MEM_KEY_L2_ENTRY_1_L2_BRIDGE, SOC_MEM_KEY_L2_ENTRY_1_L2_VFI};
   7338     uint32 key_type_2[] = {SOC_MEM_KEY_L2_ENTRY_2_L2_BRIDGE, SOC_MEM_KEY_L2_ENTRY_2_L2_VFI};
   7339     
   7340     BCM_TR3_L2_INIT(unit);
   7341 
   7342     /* Input parameters check. */
   7343     if ((NULL == addr) || (NULL == cf_count) || 
   7344         (NULL == cf_array) || (cf_max <= 0)) {
   7345         return (BCM_E_PARAM);
   7346     }
   7347     sal_memset(&l2_entries, 0, sizeof (l2_entries));
   7348     l2_entries.entry_flags = _BCM_TR3_L2_SELECT_ALL(unit);
   7349     BCM_IF_ERROR_RETURN(_bcm_tr3_l2api_to_l2hw(unit, &l2_entries,
   7350                                                addr, FALSE));
   7351     /* NOTE: Implementation assumes that enough criteria/info will be set 
   7352              in the bcm_l2_addr_t param to not have any ambiguity between
   7353              ENTRY_1 and ENTRY_2, i.e the following conditions would not
   7354              be true together */ 
   7355     if (l2_entries.entry_flags & _BCM_TR3_L2_SELECT_L2_ENTRY_1) {
   7356         mem = L2_ENTRY_1m;
   7357         entry = &l2_entries.l2_entry_1;
   7358         kt = key_type_1;
   7359         valid = VALIDf;
   7360         flag = _BCM_TR3_L2_SELECT_L2_ENTRY_1;
   7361     } else if (l2_entries.entry_flags & _BCM_TR3_L2_SELECT_L2_ENTRY_2) {
   7362         mem = L2_ENTRY_2m;
   7363         entry = &l2_entries.l2_entry_2;
   7364         kt = key_type_2;
   7365         valid = VALID_0f;
   7366         flag = _BCM_TR3_L2_SELECT_L2_ENTRY_2;
   7367     } else {
   7368         return BCM_E_PARAM;
   7369     }
   7370     rv = soc_ism_get_banks_for_mem(unit, mem, mem_banks.banks, 
   7371                                    mem_banks.bank_size, &mem_banks.count);
   7372     if (SOC_FAILURE(rv)) {
   7373         return BCM_E_INTERNAL;
   7374     }
   7375     if (mem_banks.count == 0) {
   7376         return BCM_E_NOT_FOUND;
   7377     }
   7378     *cf_count = 0;
   7379     for (bidx = 0; bidx < mem_banks.count; bidx++) {
   7380         rv = soc_generic_hash(unit, mem, entry, (uint32)1 << mem_banks.banks[bidx],
   7381                               0, &index, &result, &bucket_index, &num_ent);
   7382         if (SOC_FAILURE(rv)) {
   7383             return BCM_E_INTERNAL;
   7384         }
   7385         for (i = 0; (i < num_ent) && (*cf_count < cf_max);) {
   7386             rv = soc_mem_read(unit, mem, COPYNO_ALL, index + i, l2_entry);
   7387             if (SOC_FAILURE(rv)) {
   7388                 return BCM_E_MEMORY;
   7389             }
   7390             if (soc_mem_field32_get(unit, mem, &l2_entry, valid) && 
   7391                 ((soc_mem_field32_get(unit, mem, &l2_entry, KEY_TYPEf) == kt[0]) ||
   7392                  (soc_mem_field32_get(unit, mem, &l2_entry, KEY_TYPEf) == kt[1]))) {
   7393                 l2_entries_match.entry_flags = flag;
   7394                 if (mem == L2_ENTRY_1m) {
   7395                     sal_memcpy(&l2_entries_match.l2_entry_1, l2_entry,
   7396                                sizeof(l2_entry_1_entry_t));
   7397                 } else {
   7398                     sal_memcpy(&l2_entries_match.l2_entry_2, l2_entry,
   7399                                sizeof(l2_entry_2_entry_t));
   7400                 }
   7401                 BCM_IF_ERROR_RETURN
   7402                     (_bcm_tr3_l2api_from_l2hw(unit, &cf_array[*cf_count], &l2_entries_match));
   7403                 *cf_count += 1;
   7404             }
   7405             i += soc_ism_get_bucket_offset(unit, mem, -1, entry, l2_entry);
   7406         }
   7407     }
   7408     return BCM_E_NONE;
   7409 }
   7410 
   7411 /*
   7412  * Function:
   7413  *      bcm_tr3_l2_port_native
   7414  * Purpose:
   7415  *      Determine if the given port is "native" from the point of view
   7416  *      of L2.
   7417  * Parameters:
   7418  *      unit - (IN) Unit number.
   7419  *      modid - (IN) <UNDEF>
   7420  *      port - (IN) <UNDEF>
   7421  * Returns:
   7422  *      BCM_E_xxx
   7423  * Notes:
   7424  */
   7425 int 
   7426 bcm_tr3_l2_port_native(int unit, int modid, int port)
   7427 {
   7428     int unit_modid;
   7429     int unit_port;  /* In case unit supports multiple module IDs */
   7430     bcm_trunk_t     tgid;
   7431     int             id, isLocal;
   7432 
   7433     BCM_TR3_L2_INIT(unit);
   7434 
   7435     if (BCM_GPORT_IS_SET(port)) {
   7436         BCM_IF_ERROR_RETURN(_bcm_esw_gport_resolve(unit, port, &modid,
   7437             &port, &tgid, &id));
   7438 
   7439         if (-1 != id || BCM_TRUNK_INVALID != tgid) {
   7440             return FALSE;
   7441         }
   7442     }
   7443 
   7444     BCM_IF_ERROR_RETURN(_bcm_esw_modid_is_local(unit, modid, &isLocal));
   7445     if (isLocal != TRUE) {
   7446         return FALSE;
   7447     }
   7448 
   7449     BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &unit_modid));
   7450     if (unit_modid != modid) {
   7451         unit_port = port + 32; 
   7452     } else {
   7453         unit_port = port;
   7454     }
   7455 
   7456     if (IS_ST_PORT(unit, unit_port)) {
   7457         return FALSE;
   7458     } 
   7459 
   7460     return TRUE;
   7461 }
   7462 
   7463 /*
   7464  * Function:
   7465  *      bcm_tr3_l2_cache_init
   7466  * Purpose:
   7467  *      Initialize the L2 cache.
   7468  * Parameters:
   7469  *      unit - (IN) Unit number.
   7470  * Returns:
   7471  *      BCM_E_xxx
   7472  * Notes:
   7473  */
   7474 int 
   7475 bcm_tr3_l2_cache_init(int unit)
   7476 {
   7477     int     skip_l2u;
   7478 
   7479     if (!SOC_UNIT_VALID(unit)) {
   7480         return BCM_E_UNIT;
   7481     }
   7482 
   7483     skip_l2u = soc_property_get(unit, spn_SKIP_L2_USER_ENTRY, 0);
   7484 
   7485     if (soc_feature(unit, soc_feature_l2_user_table) && !skip_l2u) {
   7486         bcm_l2_cache_addr_t addr;
   7487         l2u_entry_t entry;
   7488         int index;
   7489 
   7490         if (!SAL_BOOT_QUICKTURN) {
   7491             SOC_IF_ERROR_RETURN
   7492                 (soc_mem_clear(unit, L2_USER_ENTRYm, COPYNO_ALL, TRUE));
   7493         }
   7494         
   7495         bcm_l2_cache_addr_t_init(&addr);
   7496         addr.flags = BCM_L2_CACHE_CPU | BCM_L2_CACHE_BPDU;
   7497         /* Set default BPDU addresses (01:80:c2:00:00:00) */
   7498         ENET_SET_MACADDR(addr.mac, _soc_mac_spanning_tree);
   7499         ENET_SET_MACADDR(addr.mac_mask, _soc_mac_all_ones);
   7500         
   7501         addr.dest_port = CMIC_PORT(unit);
   7502         
   7503         BCM_IF_ERROR_RETURN(_bcm_tr3_l2_cache_to_l2u(unit, &entry, &addr));
   7504         for (index = 0; index < L2U_BPDU_COUNT; index++) {
   7505             SOC_IF_ERROR_RETURN(soc_l2u_insert(unit, &entry, index, &index));
   7506         }
   7507 
   7508         if (!SAL_BOOT_QUICKTURN) {
   7509             /* Set 01:80:c2:00:00:10 */
   7510             addr.mac[5] = 0x10;
   7511             
   7512             BCM_IF_ERROR_RETURN(_bcm_tr3_l2_cache_to_l2u(unit, &entry, &addr));
   7513             SOC_IF_ERROR_RETURN(soc_l2u_insert(unit, &entry, -1, &index));
   7514             /* Set 01:80:c2:00:00:0x */
   7515             addr.mac[5] = 0x00;
   7516             addr.mac_mask[5] = 0xf0;
   7517             
   7518             BCM_IF_ERROR_RETURN(_bcm_tr3_l2_cache_to_l2u(unit, &entry, &addr));
   7519             SOC_IF_ERROR_RETURN(soc_l2u_insert(unit, &entry, -1, &index));
   7520             /* Set 01:80:c2:00:00:2x */
   7521             addr.mac[5] = 0x20;
   7522             
   7523             BCM_IF_ERROR_RETURN(_bcm_tr3_l2_cache_to_l2u(unit, &entry, &addr));
   7524             SOC_IF_ERROR_RETURN(soc_l2u_insert(unit, &entry, -1, &index));
   7525         }
   7526 
   7527         return BCM_E_NONE;
   7528     }
   7529     return BCM_E_UNAVAIL;
   7530 }
   7531 
   7532 /*
   7533  * Function:
   7534  *      bcm_tr3_l2_cache_set
   7535  * Purpose:
   7536  *      Set an L2 cache entry.
   7537  * Parameters:
   7538  *      unit - (IN) Unit number.
   7539  *      index - (IN) <UNDEF>
   7540  *      addr - (IN) <UNDEF>
   7541  *      index_used - (OUT) <UNDEF>
   7542  * Returns:
   7543  *      BCM_E_xxx
   7544  * Notes:
   7545  */
   7546 int 
   7547 bcm_tr3_l2_cache_set(int unit, 
   7548     int index, 
   7549     bcm_l2_cache_addr_t *addr, 
   7550     int *index_used)
   7551 {
   7552     int skip_l2u;
   7553 
   7554     if (!SOC_UNIT_VALID(unit)) {
   7555         return BCM_E_UNIT;
   7556     }
   7557     BCM_TR3_L2_INIT(unit);
   7558 
   7559     skip_l2u = soc_property_get(unit, spn_SKIP_L2_USER_ENTRY, 0);
   7560 
   7561     if (soc_feature(unit, soc_feature_l2_user_table) && !skip_l2u) {
   7562 
   7563         l2u_entry_t         l2u_entry;
   7564         bcm_l2_cache_addr_t l2_addr;
   7565 
   7566         sal_memcpy(&l2_addr, addr, sizeof(bcm_l2_cache_addr_t));
   7567 
   7568         if (soc_feature(unit, soc_feature_extended_address_class)) {
   7569             if ((l2_addr.lookup_class > SOC_EXT_ADDR_CLASS_MAX(unit)) ||
   7570                 (l2_addr.lookup_class < 0)) {
   7571                 return (BCM_E_PARAM);
   7572             }
   7573         } else if ((l2_addr.lookup_class > SOC_ADDR_CLASS_MAX(unit)) || 
   7574             (l2_addr.lookup_class < 0)) {
   7575             return (BCM_E_PARAM);
   7576         }
   7577 
   7578         /* ESW architecture can't support multiple destinations */
   7579         if (BCM_PBMP_NOT_NULL(l2_addr.dest_ports)) {
   7580             return BCM_E_PARAM;
   7581         }
   7582 
   7583         
   7584          BCM_IF_ERROR_RETURN(
   7585             _bcm_tr3_l2_cache_to_l2u(unit, &l2u_entry, &l2_addr));
   7586         
   7587         SOC_IF_ERROR_RETURN(
   7588             soc_l2u_insert(unit, &l2u_entry, index, index_used));
   7589 
   7590         if (l2_addr.flags & BCM_L2_CACHE_L3) {
   7591             return (_bcm_tr3_l2cache_myStation_set(unit, *index_used, &l2_addr));
   7592         }
   7593 
   7594         return BCM_E_NONE;
   7595     }
   7596     return BCM_E_UNAVAIL;
   7597 }
   7598 
   7599 /*
   7600  * Function:
   7601  *      bcm_tr3_l2_cache_get
   7602  * Purpose:
   7603  *      Get an L2 cache entry.
   7604  * Parameters:
   7605  *      unit - (IN) Unit number.
   7606  *      index - (IN) <UNDEF>
   7607  *      addr - (OUT) <UNDEF>
   7608  * Returns:
   7609  *      BCM_E_xxx
   7610  * Notes:
   7611  */
   7612 int 
   7613 bcm_tr3_l2_cache_get(int unit, 
   7614     int index, 
   7615     bcm_l2_cache_addr_t *addr)
   7616 {
   7617     int skip_l2u;
   7618 
   7619     if (!SOC_UNIT_VALID(unit)) {
   7620         return BCM_E_UNIT;
   7621     }
   7622 
   7623     BCM_TR3_L2_INIT(unit);
   7624 
   7625     skip_l2u = soc_property_get(unit, spn_SKIP_L2_USER_ENTRY, 0);
   7626 
   7627     if (soc_feature(unit, soc_feature_l2_user_table) && !skip_l2u) {
   7628         l2u_entry_t l2u_entry;
   7629 
   7630         SOC_IF_ERROR_RETURN(
   7631             soc_l2u_get(unit, &l2u_entry, index));
   7632 
   7633         BCM_IF_ERROR_RETURN(
   7634             _bcm_tr3_l2_cache_from_l2u(unit, addr, &l2u_entry));
   7635 
   7636         if (addr->flags & BCM_L2_CACHE_L3) {
   7637             BCM_IF_ERROR_RETURN
   7638             (_bcm_tr3_l2cache_myStation_get(unit, index, addr));
   7639         }
   7640 
   7641         return BCM_E_NONE;
   7642     }
   7643     return BCM_E_UNAVAIL;
   7644 }
   7645 
   7646 /*
   7647  * Function:
   7648  *      bcm_tr3_l2_cache_delete
   7649  * Purpose:
   7650  *      Clear an L2 cache entry.
   7651  * Parameters:
   7652  *      unit - (IN) Unit number.
   7653  *      index - (IN) <UNDEF>
   7654  * Returns:
   7655  *      BCM_E_xxx
   7656  * Notes:
   7657  */
   7658 int 
   7659 bcm_tr3_l2_cache_delete(int unit, int index)
   7660 {
   7661     int skip_l2u, rv;
   7662     l2u_entry_t entry;
   7663 
   7664     if (!SOC_UNIT_VALID(unit)) {
   7665         return BCM_E_UNIT;
   7666     }
   7667 
   7668     BCM_TR3_L2_INIT(unit);
   7669 
   7670     skip_l2u = soc_property_get(unit, spn_SKIP_L2_USER_ENTRY, 0);
   7671 
   7672     if (soc_feature(unit, soc_feature_l2_user_table) && !skip_l2u) {
   7673         if (index < 0 || index > soc_mem_index_max(unit, L2_USER_ENTRYm)) {
   7674             return BCM_E_PARAM;
   7675         }
   7676         soc_mem_lock(unit, L2_USER_ENTRYm);
   7677         rv = READ_L2_USER_ENTRYm(unit, MEM_BLOCK_ALL, index, &entry);
   7678 
   7679         if (BCM_SUCCESS(rv) && _l2u_field32_get(unit, &entry, RESERVED_0f)) {
   7680             rv = _bcm_tr3_l2cache_myStation_delete(unit, index);
   7681         }
   7682 
   7683         if (BCM_SUCCESS(rv)) {
   7684             sal_memset(&entry, 0, sizeof(entry));
   7685             rv = WRITE_L2_USER_ENTRYm(unit, MEM_BLOCK_ALL, index, &entry);
   7686         }
   7687 
   7688         soc_mem_unlock(unit, L2_USER_ENTRYm);
   7689         return rv;
   7690     }
   7691     return BCM_E_UNAVAIL;
   7692 }
   7693 
   7694 /*
   7695  * Function:
   7696  *      bcm_tr3_l2_cache_delete_all
   7697  * Purpose:
   7698  *      Clear all L2 cache entries.
   7699  * Parameters:
   7700  *      unit - (IN) Unit number.
   7701  * Returns:
   7702  *      BCM_E_xxx
   7703  * Notes:
   7704  */
   7705 int 
   7706 bcm_tr3_l2_cache_delete_all(int unit)
   7707 {
   7708     int skip_l2u, rv, index, index_max;
   7709     l2u_entry_t entry;
   7710 
   7711     if (!SOC_UNIT_VALID(unit)) {
   7712         return BCM_E_UNIT;
   7713     }
   7714 
   7715     BCM_TR3_L2_INIT(unit);
   7716 
   7717     skip_l2u = soc_property_get(unit, spn_SKIP_L2_USER_ENTRY, 0);
   7718 
   7719 
   7720     if (soc_feature(unit, soc_feature_l2_user_table) && !skip_l2u) {
   7721 
   7722         index_max = soc_mem_index_max(unit, L2_USER_ENTRYm);
   7723 
   7724         rv = BCM_E_NONE;
   7725         soc_mem_lock(unit, L2_USER_ENTRYm);
   7726         for (index = 0; index <= index_max; index++) {
   7727             rv = READ_L2_USER_ENTRYm(unit, MEM_BLOCK_ALL, index, &entry);
   7728             if (BCM_SUCCESS(rv) && _l2u_field32_get(unit, &entry, RESERVED_0f)) {
   7729                 rv = _bcm_tr3_l2cache_myStation_delete(unit, index);
   7730                 /* Ignore entry not found case */
   7731                 if (rv == BCM_E_NOT_FOUND) {
   7732                     rv = BCM_E_NONE;
   7733                 }
   7734             } 
   7735 
   7736             if (BCM_SUCCESS(rv)) {
   7737                 sal_memset(&entry, 0, sizeof(entry));
   7738                 rv = WRITE_L2_USER_ENTRYm(unit, MEM_BLOCK_ALL, index, &entry);
   7739             }
   7740 
   7741             if (BCM_FAILURE(rv)) {
   7742                 break;
   7743             }
   7744         }
   7745         soc_mem_unlock(unit, L2_USER_ENTRYm);
   7746         return rv;
   7747     }
   7748     return BCM_E_UNAVAIL;
   7749 }
   7750 
   7751 /*
   7752  * Function:
   7753  *      bcm_tr3_metro_myStation_add
   7754  * Purpose:
   7755  *      Add a (MAC, VLAN) for tunnel/MPLS/TRILL processing.
   7756  *      Frames destined to (MAC, VLAN) is subjected to MPLS processing.
   7757  *      Shared by MPLS, MIM and TRILL
   7758  * Parameters:
   7759  *      unit - Unit number
   7760  *      mac  - MAC address
   7761  *      vlan - VLAN ID
   7762  *      port - Ingress port
   7763  */
   7764 int
   7765 bcm_tr3_metro_myStation_add(int unit, bcm_mac_t mac,
   7766                             bcm_vlan_t vlan, bcm_port_t port)
   7767 {
   7768     _bcm_tr3_l2_bookkeeping_t *info = L2_INFO(unit);
   7769     int rv, index, alt_index, i, entry_words;
   7770     my_station_tcam_entry_t *entry;
   7771     uint32 *tunnel_mask;
   7772     bcm_mac_t mac_mask;
   7773     uint32 port_mask;
   7774 
   7775     tunnel_mask = info->my_station_tunnel_mask.entry_data;
   7776     entry_words = soc_mem_entry_words(unit, MY_STATION_TCAMm);
   7777 
   7778     soc_mem_lock(unit, MY_STATION_TCAMm);
   7779 
   7780     rv = _bcm_tr3_my_station_lookup(unit, mac, vlan, port, -1, &index,
   7781                                    &alt_index);
   7782     if (BCM_SUCCESS(rv)) {
   7783         /* Entry exist, update the entry */
   7784         entry = &info->my_station_shadow[index];
   7785         for (i = 0; i < entry_words; i++) {
   7786             entry->entry_data[i] |= tunnel_mask[i];
   7787         }
   7788         rv = soc_mem_write(unit, MY_STATION_TCAMm, MEM_BLOCK_ALL, index,
   7789                            entry);
   7790     } else if (rv == BCM_E_NOT_FOUND && index == -1) {
   7791         /* No free entry available for insertion */
   7792         rv = BCM_E_FULL;
   7793     }
   7794     if (rv != BCM_E_NOT_FOUND) {
   7795         soc_mem_unlock(unit, MY_STATION_TCAMm);
   7796         return rv;
   7797     }
   7798 
   7799     if (alt_index != -1 &&
   7800         ((port == -1 && alt_index > index) ||
   7801          (port != -1 && alt_index < index))) {
   7802         /* Free entry is available for new entry insertion and alternate entry
   7803          * exists. However need to swap these 2 entries to maintain proper
   7804          * lookup precedence */
   7805         rv = soc_mem_read(unit, MY_STATION_TCAMm, MEM_BLOCK_ALL, alt_index,
   7806                           &info->my_station_shadow[index]);
   7807         if (BCM_SUCCESS(rv)) {
   7808             rv = soc_mem_write(unit, MY_STATION_TCAMm, MEM_BLOCK_ALL, index,
   7809                                &info->my_station_shadow[index]);
   7810         }
   7811         if (BCM_FAILURE(rv)) {
   7812             soc_mem_unlock(unit, MY_STATION_TCAMm);
   7813             return rv;
   7814         }
   7815         index = alt_index;
   7816     }
   7817 
   7818     /* Add the new entry */
   7819     entry = &info->my_station_shadow[index];
   7820     sal_memset(entry, 0, sizeof(*entry));
   7821     soc_mem_field32_set(unit, MY_STATION_TCAMm, entry, VALIDf, 1);
   7822     soc_mem_field32_set(unit, MY_STATION_TCAMm, entry, VLAN_IDf, vlan);
   7823     soc_mem_field32_set(unit, MY_STATION_TCAMm, entry, VLAN_ID_MASKf, 0xfff);
   7824     soc_mem_mac_addr_set(unit, MY_STATION_TCAMm, entry, MAC_ADDRf, mac);
   7825     sal_memset(&mac_mask, 0xff, sizeof(mac_mask));
   7826     soc_mem_mac_addr_set(unit, MY_STATION_TCAMm, entry, MAC_ADDR_MASKf,
   7827                          mac_mask);
   7828     if (port != -1) {
   7829         soc_mem_field32_set(unit, MY_STATION_TCAMm, entry, ING_PORT_NUMf,
   7830                             port);
   7831         port_mask = (1 << soc_mem_field_length(unit, MY_STATION_TCAMm,
   7832                                                ING_PORT_NUMf)) - 1;
   7833         soc_mem_field32_set(unit, MY_STATION_TCAMm, entry, ING_PORT_NUM_MASKf,
   7834                             port_mask);
   7835     }
   7836     for (i = 0; i < entry_words; i++) {
   7837         entry->entry_data[i] |= tunnel_mask[i];
   7838     }
   7839     rv = soc_mem_write(unit, MY_STATION_TCAMm, MEM_BLOCK_ALL, index, entry);
   7840 
   7841     soc_mem_unlock(unit, MY_STATION_TCAMm);
   7842     return rv;
   7843 }
   7844 
   7845 /*
   7846  * Function:
   7847  *      bcm_tr3_l2_tunnel_add
   7848  * Purpose:
   7849  *      Add a destination L2 address to trigger tunnel processing.
   7850  * Parameters:
   7851  *      unit - (IN) Unit number.
   7852  *      mac - (IN) MAC address
   7853  *      vlan - (IN) VLAN ID
   7854  * Returns:
   7855  *      BCM_E_xxx
   7856  * Notes:
   7857  */
   7858 int 
   7859 bcm_tr3_l2_tunnel_add(int unit, bcm_mac_t mac, bcm_vlan_t vlan)
   7860 {
   7861     BCM_TR3_L2_INIT(unit);
   7862     return bcm_tr3_metro_myStation_add(unit, mac, vlan, -1);
   7863 }
   7864 
   7865 /*
   7866  * Function:
   7867  *      bcm_tr3_metro_myStation_delete
   7868  * Purpose:
   7869  *    Delete a (MAC, VLAN) for tunnel/MPLS processing.
   7870  *    Shared by MPLS and MIM
   7871  * Parameters:
   7872  *      unit - Unit number
   7873  *      mac  - MAC address
   7874  *      vlan - VLAN ID
   7875  */
   7876 int
   7877 bcm_tr3_metro_myStation_delete(int unit, bcm_mac_t mac,
   7878                                          bcm_vlan_t vlan, bcm_port_t port)
   7879 {
   7880     _bcm_tr3_l2_bookkeeping_t *info = L2_INFO(unit);
   7881     int rv, index, i, entry_words;
   7882     my_station_tcam_entry_t *entry;
   7883     uint32 *l3_mask, *tunnel_mask;
   7884 
   7885     l3_mask = info->my_station_l3_mask.entry_data;
   7886     tunnel_mask = info->my_station_tunnel_mask.entry_data;
   7887     entry_words = soc_mem_entry_words(unit, MY_STATION_TCAMm);
   7888 
   7889     soc_mem_lock(unit, MY_STATION_TCAMm);
   7890 
   7891     rv = _bcm_tr3_my_station_lookup(unit, mac, vlan, port, -1, &index, NULL);
   7892     if (BCM_SUCCESS(rv)) {
   7893         entry = &info->my_station_shadow[index];
   7894 
   7895         /* Check if the entry has tunnel related flag enabled */
   7896         for (i = 0; i < entry_words; i++) {
   7897             if (entry->entry_data[i] & tunnel_mask[i]) {
   7898                 break;
   7899             }
   7900         }
   7901         if (i == entry_words) {
   7902             soc_mem_unlock(unit, MY_STATION_TCAMm);
   7903             return BCM_E_NOT_FOUND;
   7904         }
   7905 
   7906         /* Check to see if we need to delete or modify the entry */
   7907         for (i = 0; i < entry_words; i++) {
   7908             if (entry->entry_data[i] & l3_mask[i]) {
   7909                 break;
   7910             }
   7911         }
   7912         if (i == entry_words) {
   7913             /* Delete the entry if no L3 related flag is enabled */
   7914             sal_memset(entry, 0, sizeof(*entry));
   7915         } else {
   7916             /* Modify the entry if any L3 related flag is enabled */
   7917             for (i = 0; i < entry_words; i++) {
   7918                 entry->entry_data[i] &= ~tunnel_mask[i];
   7919             }
   7920         }
   7921         rv = soc_mem_write(unit, MY_STATION_TCAMm, MEM_BLOCK_ALL, index,
   7922                            entry);
   7923     }
   7924 
   7925     soc_mem_unlock(unit, MY_STATION_TCAMm);
   7926     return rv;
   7927 }
   7928 
   7929 /*
   7930  * Function:
   7931  *      bcm_tr3_l2_tunnel_delete
   7932  * Purpose:
   7933  *      Clear a destination L2 address used to trigger tunnel
   7934  *      processing.
   7935  * Parameters:
   7936  *      unit - (IN) Unit number.
   7937  *      mac -  (IN) MAC address
   7938  *      vlan - (IN) VLAN ID
   7939  * Returns:
   7940  *      BCM_E_xxx
   7941  * Notes:
   7942  */
   7943 int 
   7944 bcm_tr3_l2_tunnel_delete(int unit, bcm_mac_t mac, bcm_vlan_t vlan)
   7945 {
   7946     return  bcm_tr3_metro_myStation_delete(unit, mac, vlan, -1);
   7947 }
   7948 
   7949 /*
   7950  * Function:
   7951  *      bcm_tr3_metro_myStation_delete_all
   7952  * Purpose:
   7953  *      Delete all (MAC, VLAN) for tunnel/MPLS processing.
   7954  *      Shared by MPLS and MIM
   7955  * Parameters:
   7956  *      unit - Unit number
   7957  */
   7958 int
   7959 bcm_tr3_metro_myStation_delete_all(int unit)
   7960 {
   7961     _bcm_tr3_l2_bookkeeping_t *info = L2_INFO(unit);
   7962     int rv, index, i, num_entries, entry_words;
   7963     my_station_tcam_entry_t *entry, valid_mask;
   7964     uint32 *l3_mask, *tunnel_mask;
   7965 
   7966     sal_memset(&valid_mask, 0, sizeof(valid_mask));
   7967     soc_mem_field32_set(unit, MY_STATION_TCAMm, &valid_mask, VALIDf, 1);
   7968 
   7969     l3_mask = info->my_station_l3_mask.entry_data;
   7970     tunnel_mask = info->my_station_tunnel_mask.entry_data;
   7971     num_entries = soc_mem_index_count(unit, MY_STATION_TCAMm);
   7972     entry_words = soc_mem_entry_words(unit, MY_STATION_TCAMm);
   7973 
   7974     soc_mem_lock(unit, MY_STATION_TCAMm);
   7975 
   7976     rv = BCM_E_NONE;
   7977     for (index = 0; index < num_entries; index++) {
   7978         entry = &info->my_station_shadow[index];
   7979 
   7980         /* Check if the entry has tunnel related flag enabled */
   7981         for (i = 0; i < entry_words; i++) {
   7982             if (entry->entry_data[i] & tunnel_mask[i]) {
   7983                 break;
   7984             }
   7985         }
   7986         if (i == entry_words) {
   7987             continue;
   7988         }
   7989 
   7990         /* Check if the entry is valid */
   7991         for (i = 0; i < entry_words; i++) {
   7992             if (entry->entry_data[i] & valid_mask.entry_data[i]) {
   7993                 break;
   7994             }
   7995         }
   7996         if (i == entry_words) {
   7997             continue;
   7998         }
   7999 
   8000         /* Check to see if we need to delete or modify the entry */
   8001         for (i = 0; i < entry_words; i++) {
   8002             if (entry->entry_data[i] & l3_mask[i]) {
   8003                 break;
   8004             }
   8005         }
   8006         if (i == entry_words) {
   8007             /* Delete the entry if no L3 related flag is enabled */
   8008             sal_memset(entry, 0, sizeof(*entry));
   8009         } else {
   8010             /* Modify the entry if any L3 related flag is enabled */
   8011             for (i = 0; i < entry_words; i++) {
   8012                 entry->entry_data[i] &= ~tunnel_mask[i];
   8013             }
   8014         }
   8015         rv = soc_mem_write(unit, MY_STATION_TCAMm, MEM_BLOCK_ALL, index,
   8016                            entry);
   8017     }
   8018 
   8019     soc_mem_unlock(unit, MY_STATION_TCAMm);
   8020     return rv;
   8021 }
   8022 
   8023 /*
   8024  * Function:
   8025  *      bcm_tr3_l2_tunnel_delete_all
   8026  * Purpose:
   8027  *      Clear all destination L2 addresses used to trigger tunnel
   8028  *      processing.
   8029  * Parameters:
   8030  *      unit - (IN) Unit number.
   8031  * Returns:
   8032  *      BCM_E_xxx
   8033  * Notes:
   8034  */
   8035 int 
   8036 bcm_tr3_l2_tunnel_delete_all(int unit)
   8037 {
   8038     BCM_TR3_L2_INIT(unit);
   8039     return bcm_tr3_metro_myStation_delete_all(unit);
   8040 }
   8041 
   8042 /*
   8043  * Function:
   8044  *      bcm_tr3_l2_learn_limit_set
   8045  * Purpose:
   8046  *      Set L2 addresses learn limit.
   8047  * Parameters:
   8048  *      unit - (IN) Unit number.
   8049  *      limit - (IN) <UNDEF>
   8050  * Returns:
   8051  *      BCM_E_xxx
   8052  * Notes:
   8053  */
   8054 int 
   8055 bcm_tr3_l2_learn_limit_set(int unit, bcm_l2_learn_limit_t *limit)
   8056 {
   8057     int32 max_limit;
   8058     uint32 type, action;
   8059     
   8060     BCM_TR3_L2_INIT(unit);
   8061 
   8062     if (!limit) {
   8063         return BCM_E_PARAM;
   8064     }
   8065 
   8066     max_limit = BCM_MAC_LIMIT_MAX(unit);
   8067 
   8068     if (limit->limit > max_limit) {
   8069         return BCM_E_PARAM;
   8070     }
   8071 
   8072     type = limit->flags &
   8073            (BCM_L2_LEARN_LIMIT_SYSTEM | BCM_L2_LEARN_LIMIT_VLAN | 
   8074             BCM_L2_LEARN_LIMIT_PORT | BCM_L2_LEARN_LIMIT_TRUNK);
   8075 
   8076     action = limit->flags & 
   8077              (BCM_L2_LEARN_LIMIT_ACTION_DROP | BCM_L2_LEARN_LIMIT_ACTION_CPU |
   8078               BCM_L2_LEARN_LIMIT_ACTION_PREFER);
   8079 
   8080     if (!type) {
   8081         return BCM_E_PARAM;
   8082     }
   8083 
   8084     if (type != BCM_L2_LEARN_LIMIT_SYSTEM &&
   8085         (action & BCM_L2_LEARN_LIMIT_ACTION_PREFER)) {
   8086         return BCM_E_PARAM;
   8087     }
   8088 
   8089     if (type & BCM_L2_LEARN_LIMIT_SYSTEM) {
   8090         BCM_IF_ERROR_RETURN(_bcm_tr3_l2_learn_limit_system_set(unit, action,
   8091                                                             limit->limit));
   8092     }
   8093 
   8094     if (type & BCM_L2_LEARN_LIMIT_PORT) {
   8095         int index;
   8096         if (BCM_GPORT_IS_SET(limit->port)) {
   8097             BCM_IF_ERROR_RETURN(
   8098                 bcm_esw_port_local_get(unit, limit->port, &(limit->port)));
   8099         }
   8100 
   8101         if (!SOC_PORT_VALID(unit, limit->port)) {
   8102             return BCM_E_PORT;
   8103         }
   8104             
   8105         /* BCM_L2_LEARN_LIMIT_ACTION_PREFER should be used only in system limit
   8106            and only for Raptor/Raven devices */
   8107         if (limit->flags & BCM_L2_LEARN_LIMIT_ACTION_PREFER) {
   8108             return BCM_E_PARAM;
   8109         }
   8110 
   8111         index = limit->port + soc_mem_index_count(unit, TRUNK_GROUPm);
   8112         BCM_IF_ERROR_RETURN
   8113             (_bcm_tr3_l2_learn_limit_set(unit, PORT_OR_TRUNK_MAC_LIMITm,
   8114                                         index, action, limit->limit));
   8115     }
   8116 
   8117     if (type & BCM_L2_LEARN_LIMIT_TRUNK) {
   8118         int index;
   8119         /* BCM_L2_LEARN_LIMIT_ACTION_PREFER should be used only in system limit
   8120            and only for Raptor/Raven devices */
   8121         if (limit->flags & BCM_L2_LEARN_LIMIT_ACTION_PREFER) {
   8122             return BCM_E_PARAM;
   8123         }
   8124 
   8125        if (limit->trunk < 0 ||
   8126            limit->trunk >= soc_mem_index_count(unit, TRUNK_GROUPm)) {
   8127            return BCM_E_PARAM;
   8128        }
   8129        index = limit->trunk;
   8130        BCM_IF_ERROR_RETURN
   8131            (_bcm_tr3_l2_learn_limit_set(unit, PORT_OR_TRUNK_MAC_LIMITm,
   8132                                        index, action, limit->limit));
   8133     }
   8134 
   8135     if (type & BCM_L2_LEARN_LIMIT_VLAN) {
   8136         int index, vfi;
   8137         /* BCM_L2_LEARN_LIMIT_ACTION_PREFER should be used only in system limit
   8138            and only for Raptor/Raven devices */
   8139         if (limit->flags & BCM_L2_LEARN_LIMIT_ACTION_PREFER) {
   8140             return BCM_E_PARAM;
   8141         }
   8142 
   8143 
   8144     if (_BCM_VPN_VFI_IS_SET(limit->vlan)) {
   8145             vfi = 0;
   8146         _BCM_VPN_GET(vfi, _BCM_VPN_TYPE_VFI, limit->vlan);
   8147         if (vfi >= soc_mem_index_count(unit, VFIm)) {
   8148             return BCM_E_PARAM;
   8149         }
   8150         index = vfi + soc_mem_index_count(unit, VLAN_TABm);
   8151     } else {
   8152             if (limit->vlan >= soc_mem_index_count(unit, VLAN_TABm)) {
   8153                 return BCM_E_PARAM;
   8154             }
   8155             index = limit->vlan;
   8156         }
   8157         BCM_IF_ERROR_RETURN
   8158             (_bcm_tr3_l2_learn_limit_set(unit, VLAN_OR_VFI_MAC_LIMITm,
   8159                                         index, action, limit->limit));
   8160     }
   8161 
   8162     return BCM_E_NONE;
   8163 }
   8164 
   8165 /*
   8166  * Function:
   8167  *      bcm_tr3_l2_learn_limit_get
   8168  * Purpose:
   8169  *      Get L2 addresses learn limit.
   8170  * Parameters:
   8171  *      unit - (IN) Unit number.
   8172  *      limit - (IN/OUT) <UNDEF>
   8173  * Returns:
   8174  *      BCM_E_xxx
   8175  * Notes:
   8176  */
   8177 int 
   8178 bcm_tr3_l2_learn_limit_get(int unit, bcm_l2_learn_limit_t *limit)
   8179 {
   8180     uint32 type;
   8181     int index, vfi;
   8182 
   8183     BCM_TR3_L2_INIT(unit);
   8184 
   8185     if (!limit) {
   8186         return BCM_E_PARAM;
   8187     }
   8188 
   8189     type = limit->flags &
   8190            (BCM_L2_LEARN_LIMIT_SYSTEM | BCM_L2_LEARN_LIMIT_VLAN | 
   8191             BCM_L2_LEARN_LIMIT_PORT | BCM_L2_LEARN_LIMIT_TRUNK);
   8192 
   8193     switch (type) {
   8194       case BCM_L2_LEARN_LIMIT_SYSTEM:
   8195         return _bcm_tr3_l2_learn_limit_system_get(unit, &limit->flags,
   8196                                                  &limit->limit);
   8197         break;
   8198       case BCM_L2_LEARN_LIMIT_PORT:
   8199         if (BCM_GPORT_IS_SET(limit->port)) {
   8200             BCM_IF_ERROR_RETURN(
   8201                 bcm_esw_port_local_get(unit, limit->port, &(limit->port)));
   8202         }
   8203 
   8204         if (!SOC_PORT_VALID(unit, limit->port)) {
   8205             return BCM_E_PORT;
   8206         }
   8207         index = limit->port + soc_mem_index_count(unit, TRUNK_GROUPm);
   8208         return _bcm_tr3_l2_learn_limit_get(unit, PORT_OR_TRUNK_MAC_LIMITm,
   8209                                           index, &limit->flags,
   8210                                           &limit->limit);
   8211         break;
   8212       case BCM_L2_LEARN_LIMIT_TRUNK:
   8213 
   8214         if (limit->trunk < 0 ||
   8215             limit->trunk >= soc_mem_index_count(unit, TRUNK_GROUPm)) {
   8216             return BCM_E_PARAM;
   8217         }
   8218         index = limit->trunk;
   8219         return _bcm_tr3_l2_learn_limit_get(unit, PORT_OR_TRUNK_MAC_LIMITm,
   8220                                           index, &limit->flags,
   8221                                           &limit->limit);
   8222         break;
   8223       case BCM_L2_LEARN_LIMIT_VLAN:
   8224         if (_BCM_VPN_VFI_IS_SET(limit->vlan)) {
   8225              vfi = 0;
   8226              _BCM_VPN_GET(vfi, _BCM_VPN_TYPE_VFI, limit->vlan);
   8227              if (vfi >= soc_mem_index_count(unit, VFIm)) {
   8228                 return BCM_E_PARAM;
   8229              }
   8230              index = vfi + soc_mem_index_count(unit, VLAN_TABm);
   8231         } else {
   8232             if (limit->vlan >= soc_mem_index_count(unit, VLAN_TABm)) {
   8233                 return BCM_E_PARAM;
   8234             }
   8235             index = limit->vlan;
   8236         }
   8237         return _bcm_tr3_l2_learn_limit_get(unit, VLAN_OR_VFI_MAC_LIMITm,
   8238                                           index, &limit->flags,
   8239                                           &limit->limit);
   8240         break;
   8241       default:
   8242         return BCM_E_PARAM;
   8243     }
   8244 
   8245     return BCM_E_UNAVAIL;
   8246 }
   8247 
   8248 /*
   8249  * Function:
   8250  *      bcm_tr3_l2_learn_class_set
   8251  * Purpose:
   8252  *      Set/Get attributes for the specified L2 learning class.
   8253  * Parameters:
   8254  *      unit - (IN) Unit number.
   8255  *      lclass - (IN) <UNDEF>
   8256  *      lclass_prio - (IN) <UNDEF>
   8257  *      flags - (IN) <UNDEF>
   8258  * Returns:
   8259  *      BCM_E_xxx
   8260  * Notes:
   8261  */
   8262 int 
   8263 bcm_tr3_l2_learn_class_set(int unit, int lclass, int lclass_prio, uint32 flags)
   8264 {
   8265     uint32 data;
   8266 
   8267     BCM_TR3_L2_INIT(unit);
   8268 
   8269     if (lclass < 0 || lclass >= SOC_REG_NUMELS(unit, CBL_ATTRIBUTEr) ||
   8270         lclass_prio < 0 ||
   8271         lclass_prio >= (1 << soc_reg_field_length(unit, CBL_ATTRIBUTEr,
   8272                                                   PORT_LEARNING_PRIORITYf))) {
   8273         return (BCM_E_PARAM);
   8274     }
   8275 
   8276     BCM_IF_ERROR_RETURN(READ_CBL_ATTRIBUTEr(unit, lclass, &data));
   8277     soc_reg_field_set(unit, CBL_ATTRIBUTEr, &data, PORT_LEARNING_PRIORITYf,
   8278                       lclass_prio);
   8279     soc_reg_field_set(unit, CBL_ATTRIBUTEr, &data, ALLOW_MOVE_IN_CLASSf,
   8280                       flags & BCM_L2_LEARN_CLASS_MOVE ? 1 : 0);
   8281     BCM_IF_ERROR_RETURN(WRITE_CBL_ATTRIBUTEr(unit, lclass, data));
   8282 
   8283     return BCM_E_NONE;
   8284 }
   8285 
   8286 /*
   8287  * Function:
   8288  *      bcm_tr3_l2_learn_class_get
   8289  * Purpose:
   8290  *      Set/Get attributes for the specified L2 learning class.
   8291  * Parameters:
   8292  *      unit - (IN) Unit number.
   8293  *      lclass - (IN) <UNDEF>
   8294  *      lclass_prio - (OUT) <UNDEF>
   8295  *      flags - (OUT) <UNDEF>
   8296  * Returns:
   8297  *      BCM_E_xxx
   8298  * Notes:
   8299  */
   8300 int 
   8301 bcm_tr3_l2_learn_class_get(int unit, int lclass, int *lclass_pri, uint32 *flags)
   8302 {
   8303     uint32 data;
   8304 
   8305     BCM_TR3_L2_INIT(unit);
   8306 
   8307     if (!soc_feature(unit, soc_feature_class_based_learning)) {
   8308         return (BCM_E_UNAVAIL);
   8309     }
   8310 
   8311     if (lclass < 0 || lclass >= SOC_REG_NUMELS(unit, CBL_ATTRIBUTEr) ||
   8312         lclass_pri == NULL || flags == NULL) {
   8313         return (BCM_E_PARAM);
   8314     }
   8315 
   8316     BCM_IF_ERROR_RETURN(READ_CBL_ATTRIBUTEr(unit, lclass, &data));
   8317     *lclass_pri = soc_reg_field_get(unit, CBL_ATTRIBUTEr, data,
   8318                                      PORT_LEARNING_PRIORITYf);
   8319     *flags = 0;
   8320     if (soc_reg_field_get(unit, CBL_ATTRIBUTEr, data, ALLOW_MOVE_IN_CLASSf)) {
   8321         *flags |= BCM_L2_LEARN_CLASS_MOVE;
   8322     }
   8323 
   8324     return (BCM_E_NONE);
   8325 }
   8326 
   8327 /*
   8328  * Function:
   8329  *      bcm_tr3_l2_learn_port_class_set
   8330  * Purpose:
   8331  *      Set/Get L2 learning class for the specified port.
   8332  * Parameters:
   8333  *      unit - (IN) Unit number.
   8334  *      port - (IN) <UNDEF>
   8335  *      lclass - (IN) <UNDEF>
   8336  * Returns:
   8337  *      BCM_E_xxx
   8338  * Notes:
   8339  */
   8340 int 
   8341 bcm_tr3_l2_learn_port_class_set(int unit, bcm_gport_t port, int lclass)
   8342 {
   8343     int gport_id;
   8344     bcm_module_t mod_out;
   8345     bcm_port_t port_out;
   8346     bcm_trunk_t trunk_id;
   8347     soc_profile_mem_t *profile;
   8348     port_cbl_table_modbase_entry_t base_entry;
   8349     port_cbl_table_entry_t cbl_entries[128];
   8350     void *entries[1];
   8351     uint32 old_index, index;
   8352     int rv;
   8353     profile = _bcm_l2_tr3_port_cbl_profile[unit];
   8354     entries[0] = &cbl_entries;
   8355 
   8356     BCM_TR3_L2_INIT(unit);
   8357 
   8358     if (!soc_feature(unit, soc_feature_class_based_learning)) {
   8359         return (BCM_E_UNAVAIL);
   8360     }
   8361 
   8362     BCM_L2_LEARN_CLASSID_VALID(lclass);
   8363 
   8364     BCM_IF_ERROR_RETURN
   8365         (_bcm_esw_gport_resolve(unit, port, &mod_out, &port_out, &trunk_id,
   8366                                 &gport_id));
   8367 
   8368     if (gport_id != -1) {
   8369         if (!BCM_GPORT_IS_MPLS_PORT(port) &&
   8370             !BCM_GPORT_IS_SUBPORT_GROUP(port) &&
   8371             !BCM_GPORT_IS_SUBPORT_PORT(port) &&
   8372             !BCM_GPORT_IS_MIM_PORT(port) &&
   8373             !BCM_GPORT_IS_VLAN_PORT(port) &&
   8374             !BCM_GPORT_IS_WLAN_PORT(port) &&
   8375             !BCM_GPORT_IS_TRILL_PORT(port) &&
   8376             !BCM_GPORT_IS_NIV_PORT(port) &&
   8377             !BCM_GPORT_IS_L2GRE_PORT(port) &&
   8378             !BCM_GPORT_IS_EXTENDER_PORT(port)) {
   8379             return BCM_E_PARAM;
   8380         }
   8381         return soc_mem_field32_modify(unit, PORT_CBL_TABLEm, gport_id,
   8382                                       VIRTUAL_PORT_LEARNING_CLASSf, lclass);
   8383     } else if (trunk_id != -1) {
   8384         return soc_mem_field32_modify(unit, TRUNK_CBL_TABLEm, trunk_id,
   8385                                       PORT_LEARNING_CLASSf, lclass);
   8386     } else {
   8387 
   8388         soc_mem_lock(unit, PORT_CBL_TABLE_MODBASEm);
   8389 
   8390         rv = soc_mem_read(unit, PORT_CBL_TABLE_MODBASEm, MEM_BLOCK_ALL, mod_out,
   8391                           &base_entry);
   8392         if (SOC_FAILURE(rv)) {
   8393             soc_mem_unlock(unit, PORT_CBL_TABLE_MODBASEm);
   8394             return rv;
   8395         }
   8396         old_index = soc_mem_field32_get(unit, PORT_CBL_TABLE_MODBASEm,
   8397                                         &base_entry, BASEf);
   8398         rv = soc_profile_mem_get(unit, profile, old_index,
   8399                                  SOC_PORT_ADDR_MAX(unit) + 1, entries);
   8400         if (BCM_FAILURE(rv)) {
   8401             soc_mem_unlock(unit, PORT_CBL_TABLE_MODBASEm);
   8402             return rv;
   8403         }
   8404         soc_mem_field32_set(unit, PORT_CBL_TABLEm, &cbl_entries[port_out],
   8405                             PORT_LEARNING_CLASSf, lclass);
   8406         rv = soc_profile_mem_add(unit, profile, entries,
   8407                                  SOC_PORT_ADDR_MAX(unit) + 1, &index);
   8408         if (BCM_FAILURE(rv)) {
   8409             soc_mem_unlock(unit, PORT_CBL_TABLE_MODBASEm);
   8410             return rv;
   8411         }
   8412         rv = soc_mem_field32_modify(unit, PORT_CBL_TABLE_MODBASEm, mod_out,
   8413                                     BASEf, index);
   8414         if (BCM_FAILURE(rv)) {
   8415             soc_mem_unlock(unit, PORT_CBL_TABLE_MODBASEm);
   8416             return rv;
   8417         }
   8418         rv = soc_profile_mem_delete(unit, profile, old_index);
   8419 
   8420         soc_mem_unlock(unit, PORT_CBL_TABLE_MODBASEm);
   8421     }
   8422 
   8423     return rv;
   8424 }
   8425 
   8426 /*
   8427  * Function:
   8428  *      bcm_tr3_l2_learn_port_class_get
   8429  * Purpose:
   8430  *      Set/Get L2 learning class for the specified port.
   8431  * Parameters:
   8432  *      unit - (IN) Unit number.
   8433  *      port - (IN) Ingress generic port
   8434  *      lclass - (OUT) learning class id (0 - 3)
   8435  * Returns:
   8436  *      BCM_E_xxx
   8437  * Notes:
   8438  */
   8439 int 
   8440 bcm_tr3_l2_learn_port_class_get(int unit, 
   8441     bcm_gport_t port, 
   8442     int *lclass)
   8443 {
   8444     int gport_id;
   8445     bcm_module_t mod_out;
   8446     bcm_port_t port_out;
   8447     bcm_trunk_t trunk_id;
   8448     soc_profile_mem_t *profile;
   8449     port_cbl_table_modbase_entry_t base_entry;
   8450     port_cbl_table_entry_t cbl_entries[128];
   8451     void *entries[1];
   8452     uint32 index;
   8453     port_cbl_table_entry_t port_entry;
   8454     trunk_cbl_table_entry_t trunk_entry;
   8455 
   8456     BCM_TR3_L2_INIT(unit);
   8457 
   8458     BCM_IF_ERROR_RETURN
   8459         (_bcm_esw_gport_resolve(unit, port, &mod_out, &port_out, &trunk_id,
   8460                                 &gport_id));
   8461 
   8462     if (lclass == NULL) {
   8463         return (BCM_E_PARAM);
   8464     }
   8465 
   8466     if (gport_id != -1) {
   8467         if (!BCM_GPORT_IS_MPLS_PORT(port) &&
   8468             !BCM_GPORT_IS_SUBPORT_GROUP(port) &&
   8469             !BCM_GPORT_IS_SUBPORT_PORT(port) &&
   8470             !BCM_GPORT_IS_MIM_PORT(port) &&
   8471             !BCM_GPORT_IS_VLAN_PORT(port) &&
   8472             !BCM_GPORT_IS_WLAN_PORT(port) &&
   8473             !BCM_GPORT_IS_TRILL_PORT(port) &&
   8474             !BCM_GPORT_IS_NIV_PORT(port) &&
   8475             !BCM_GPORT_IS_L2GRE_PORT(port) &&
   8476             !BCM_GPORT_IS_EXTENDER_PORT(port)) {
   8477             return BCM_E_PARAM;
   8478         }
   8479         BCM_IF_ERROR_RETURN
   8480             (READ_PORT_CBL_TABLEm(unit, MEM_BLOCK_ALL, gport_id, &port_entry));
   8481         *lclass = soc_mem_field32_get(unit, PORT_CBL_TABLEm, &port_entry,
   8482                                       VIRTUAL_PORT_LEARNING_CLASSf);
   8483     } else if (trunk_id != -1) {
   8484         BCM_IF_ERROR_RETURN
   8485             (READ_TRUNK_CBL_TABLEm(unit, MEM_BLOCK_ALL, trunk_id, &trunk_entry));
   8486         *lclass = soc_mem_field32_get(unit, TRUNK_CBL_TABLEm, &trunk_entry,
   8487                                       PORT_LEARNING_CLASSf);
   8488     } else {
   8489         profile = _bcm_l2_tr3_port_cbl_profile[unit];
   8490         entries[0] = &cbl_entries;
   8491 
   8492         BCM_IF_ERROR_RETURN
   8493             (soc_mem_read(unit, PORT_CBL_TABLE_MODBASEm, MEM_BLOCK_ALL, mod_out,
   8494                           &base_entry));
   8495         index = soc_mem_field32_get(unit, PORT_CBL_TABLE_MODBASEm, &base_entry,
   8496                                     BASEf);
   8497 
   8498         BCM_IF_ERROR_RETURN
   8499             (soc_profile_mem_get(unit, profile, index,
   8500                                  SOC_PORT_ADDR_MAX(unit) + 1, entries));
   8501         *lclass = soc_mem_field32_get(unit, PORT_CBL_TABLEm,
   8502                                       &cbl_entries[port_out],
   8503                                       PORT_LEARNING_CLASSf);
   8504     }
   8505 
   8506     return (BCM_E_NONE);
   8507 }
   8508 
   8509 /*
   8510  * Function:
   8511  *     _bcm_tr3_l2_traverse_int_cb
   8512  * Description:
   8513  *      Simple internal callback function for bcm_l2_traverse API
   8514  *      just to call a user provided callback on a given entry.
   8515  * Parameters:
   8516  *      unit         device number
   8517  *      trav_st      traverse structure
   8518  * Return:
   8519  *     BCM_E_XXX
   8520  */
   8521 
   8522 int
   8523 _bcm_tr3_l2_traverse_int_cb(int unit, void *trav_st)
   8524 {
   8525     _bcm_l2_traverse_t *trv;
   8526     bcm_l2_addr_t      l2_addr;
   8527 
   8528     trv = (_bcm_l2_traverse_t *)trav_st;
   8529 
   8530     switch(trv->mem) {
   8531     case L2_ENTRY_1m:
   8532         BCM_IF_ERROR_RETURN
   8533             (_bcm_tr3_l2_from_l2_1(unit, &l2_addr,
   8534                                    (l2_entry_1_entry_t *)trv->data));
   8535         if (_l2_addr_counts.flags & L2_DUMP_COUNT) {
   8536             _l2_addr_counts.l2_count.l2_entry_1++;
   8537         }
   8538         break;
   8539     case L2_ENTRY_2m:
   8540         BCM_IF_ERROR_RETURN
   8541             (_bcm_tr3_l2_from_l2_2(unit, &l2_addr,
   8542                                    (l2_entry_2_entry_t *)trv->data));
   8543         if (_l2_addr_counts.flags & L2_DUMP_COUNT) {
   8544             _l2_addr_counts.l2_count.l2_entry_2++;
   8545         }
   8546         break;
   8547     case EXT_L2_ENTRY_1m:
   8548         BCM_IF_ERROR_RETURN
   8549             (_bcm_tr3_l2_from_ext_l2_1(unit, &l2_addr,
   8550                                        (ext_l2_entry_1_entry_t *)trv->data));
   8551         if (_l2_addr_counts.flags & L2_DUMP_COUNT) {
   8552             _l2_addr_counts.l2_count.ext_l2_entry_1++;
   8553         }
   8554         break;
   8555     case EXT_L2_ENTRY_2m:
   8556         BCM_IF_ERROR_RETURN
   8557             (_bcm_tr3_l2_from_ext_l2_2(unit, &l2_addr,
   8558                                        (ext_l2_entry_2_entry_t *)trv->data));
   8559         if (_l2_addr_counts.flags & L2_DUMP_COUNT) {
   8560             _l2_addr_counts.l2_count.ext_l2_entry_2++;
   8561         }
   8562         break;
   8563     default:
   8564         return BCM_E_INTERNAL;
   8565     }
   8566 
   8567     return trv->user_cb(unit, &l2_addr, trv->user_data);
   8568 }
   8569 
   8570 /*
   8571  * Function:
   8572  *      bcm_tr3_l2_traverse
   8573  * Purpose:
   8574  *      Traverse L2 table
   8575  * Parameters:
   8576  *      unit - (IN) Unit number.
   8577  *      trav_st      Traverse structure with all the data.
   8578  * Returns:
   8579  *      BCM_E_xxx
   8580  * Notes:
   8581  */
   8582 int 
   8583 bcm_tr3_l2_traverse(int unit, _bcm_l2_traverse_t *trav_st)
   8584 {
   8585     /* Override generic ESW traverse callback with TR3 version */
   8586     trav_st->int_cb = _bcm_tr3_l2_traverse_int_cb;
   8587 
   8588     return (_bcm_tr3_l2_traverse(unit, trav_st));
   8589 }
   8590 
   8591 STATIC int
   8592 _bcm_tr3_l2e_ppa_match(int unit, _soc_tr3_l2_replace_t *rep_st, int mem)
   8593 {
   8594     _soc_tr3_l2e_ppa_info_t *ppa_info;
   8595     _soc_tr3_l2e_ppa_vlan_t *ppa_vlan;
   8596     ext_l2_entry_1_entry_t  l2_entry_1, old_l2_entry_1;
   8597     ext_l2_entry_2_entry_t  l2_entry_2, old_l2_entry_2;
   8598     int                     i, imin, imax, rv, nmatches;
   8599     uint32                  entdata, entmask, entvalue;
   8600     soc_memacc_t            *memacc;
   8601 
   8602     if (SOC_CONTROL(unit)->l2x_mode == L2MODE_POLL) {
   8603         return BCM_E_UNAVAIL;
   8604     }
   8605 
   8606     if (mem == EXT_L2_ENTRY_1m) {
   8607         /* EXT_L2_ENTRY_1 */
   8608         ppa_info = SOC_CONTROL(unit)->ext_l2_ppa_info;
   8609         ppa_vlan = SOC_CONTROL(unit)->ext_l2_ppa_vlan;
   8610         if (ppa_info == NULL) {
   8611             return BCM_E_NONE;
   8612         }
   8613 
   8614         imin = soc_mem_index_min(unit, mem);
   8615         imax = soc_mem_index_max(unit, mem);
   8616 
   8617         /* convert match data */
   8618         entdata = _SOC_TR3_L2E_VALID;
   8619         entmask = _SOC_TR3_L2E_VALID;
   8620         if (!(rep_st->flags & BCM_L2_REPLACE_MATCH_STATIC)) {
   8621             entdata |= 0x00000000;
   8622             entmask |= _SOC_TR3_L2E_STATIC;
   8623         }
   8624         if (rep_st->flags & BCM_L2_REPLACE_MATCH_VLAN) {
   8625             entdata |= (rep_st->key_vlan & _SOC_TR3_L2E_VLAN_MASK) <<
   8626                 _SOC_TR3_L2E_VLAN_SHIFT;
   8627             entmask |= _SOC_TR3_L2E_VLAN_MASK << _SOC_TR3_L2E_VLAN_SHIFT;
   8628             imin = ppa_vlan->vlan_min[rep_st->key_vlan];
   8629             imax = ppa_vlan->vlan_max[rep_st->key_vlan];
   8630         }
   8631         if (rep_st->flags & BCM_L2_REPLACE_MATCH_DEST) {
   8632             if (rep_st->match_dest.trunk != -1) {
   8633                 entdata |= _SOC_TR3_L2E_T |
   8634                     ((rep_st->match_dest.trunk & _SOC_TR3_L2E_TRUNK_MASK)
   8635                      << _SOC_TR3_L2E_TRUNK_SHIFT);
   8636                 entmask |= _SOC_TR3_L2E_T |
   8637                     (_SOC_TR3_L2E_TRUNK_MASK << _SOC_TR3_L2E_TRUNK_SHIFT);
   8638             } else if (rep_st->match_dest.vp != -1) {
   8639                 entdata |= _SOC_TR3_L2E_VP |
   8640                     ((rep_st->match_dest.vp & _SOC_TR3_L2E_DESTINATION_MASK)
   8641                      << _SOC_TR3_L2E_DESTINATION_SHIFT);
   8642                 entmask |= _SOC_TR3_L2E_VP |
   8643                     (_SOC_TR3_L2E_DESTINATION_MASK << 
   8644                      _SOC_TR3_L2E_DESTINATION_SHIFT);
   8645             } else {
   8646                 entdata |= 
   8647                     ((rep_st->match_dest.module & _SOC_TR3_L2E_MOD_MASK) <<
   8648                      _SOC_TR3_L2E_MOD_SHIFT) |
   8649                     ((rep_st->match_dest.port & _SOC_TR3_L2E_PORT_MASK) <<
   8650                      _SOC_TR3_L2E_PORT_SHIFT);
   8651                 entmask |= _SOC_TR3_L2E_T | _SOC_TR3_L2E_VP |
   8652                     (_SOC_TR3_L2E_MOD_MASK << _SOC_TR3_L2E_MOD_SHIFT) |
   8653                     (_SOC_TR3_L2E_PORT_MASK << _SOC_TR3_L2E_PORT_SHIFT);
   8654             }
   8655         }
   8656 
   8657         nmatches = 0;
   8658 
   8659         if (imin >= 0) {
   8660             if ((imax - imin) > SOC_CONTROL(unit)->ext_l2_ppa_threshold) {
   8661                 return BCM_E_UNAVAIL;
   8662             }
   8663             for (i = imin; i <= imax; i++) {
   8664                 entvalue = ppa_info[i].data;
   8665                 if ((entvalue & entmask) != entdata) {
   8666                     continue;
   8667                 }
   8668                 if (rep_st->flags & BCM_L2_REPLACE_MATCH_MAC) {
   8669                     if (ENET_CMP_MACADDR(rep_st->key_mac, ppa_info[i].mac)) {
   8670                         continue;
   8671                     }
   8672                 }
   8673                 nmatches += 1;
   8674 
   8675                 /* lookup the matched entry */
   8676                 sal_memset(&l2_entry_1, 0, sizeof(l2_entry_1));
   8677                 memacc = _BCM_TR3_L2_MEMACC(unit, EXT_L2_ENTRY_1,
   8678                                             _BCM_TR3_L2_MEMACC_VLAN_ID);
   8679                 soc_memacc_field32_set(memacc, &l2_entry_1, (entvalue >> 16) & 0xfff);
   8680                 memacc = _BCM_TR3_L2_MEMACC(unit, EXT_L2_ENTRY_1,
   8681                                         _BCM_TR3_L2_MEMACC_MAC_ADDR);
   8682                 soc_memacc_mac_addr_set(memacc, &l2_entry_1, 
   8683                                         ppa_info[i].mac);
   8684 
   8685                 /* In case of a VP entry, also assign the KEY_TYPE */
   8686                 if(entvalue & _SOC_TR3_L2E_VP) {
   8687                     memacc = _BCM_TR3_L2_MEMACC(unit, EXT_L2_ENTRY_1,
   8688                                                 _BCM_TR3_L2_MEMACC_KEY_TYPE);
   8689                     soc_memacc_field32_set(memacc, &l2_entry_1, rep_st->ext_key_type);
   8690                 }
   8691 
   8692                 /* operate on matched entry */
   8693                 if (rep_st->flags & BCM_L2_REPLACE_DELETE) {
   8694                     rv = soc_mem_generic_delete(unit, mem, MEM_BLOCK_ANY, 0,
   8695                                                 &l2_entry_1, &l2_entry_1, NULL);
   8696                     if (rv < 0) {
   8697                         return rv;
   8698                     }
   8699                 } else {
   8700                     /* replace destination fields */
   8701                     rv = soc_mem_generic_lookup(unit, mem, MEM_BLOCK_ANY, 0,
   8702                                                 &l2_entry_1, &l2_entry_1, NULL);
   8703                     if (rep_st->flags & BCM_L2_REPLACE_NEW_TRUNK) {
   8704                         memacc = _BCM_TR3_L2_MEMACC(unit, EXT_L2_ENTRY_1,
   8705                                                     _BCM_TR3_L2_MEMACC_DEST_TYPE);
   8706                         soc_memacc_field32_set(memacc, &l2_entry_1, 1);
   8707                         memacc = _BCM_TR3_L2_MEMACC(unit, EXT_L2_ENTRY_1,
   8708                                                     _BCM_TR3_L2_MEMACC_TGID);
   8709                         soc_memacc_field32_set(memacc, &l2_entry_1, rep_st->new_dest.trunk);
   8710                     } else {
   8711                         memacc = _BCM_TR3_L2_MEMACC(unit, EXT_L2_ENTRY_1,
   8712                                                     _BCM_TR3_L2_MEMACC_MODULE_ID);
   8713                         soc_memacc_field32_set(memacc, &l2_entry_1, rep_st->new_dest.module);
   8714                         memacc = _BCM_TR3_L2_MEMACC(unit, EXT_L2_ENTRY_1,
   8715                                                     _BCM_TR3_L2_MEMACC_PORT_NUM);
   8716                         soc_memacc_field32_set(memacc, &l2_entry_1, rep_st->new_dest.port);
   8717                     }
   8718                     /* re-insert entry */
   8719                     rv = soc_mem_generic_insert(unit, mem, MEM_BLOCK_ANY, 0,
   8720                                                 &l2_entry_1, &old_l2_entry_1, NULL);
   8721                     if (rv == BCM_E_EXISTS) {
   8722                         rv = BCM_E_NONE;
   8723                     }
   8724                     if (rv < 0) {
   8725                         return rv;
   8726                     }
   8727                 }
   8728             }
   8729         }
   8730         LOG_VERBOSE(BSL_LS_SOC_COMMON,
   8731                     (BSL_META_U(unit,
   8732                                 "tr_l2e_ppa_match 1: imin=%d imax=%d nmatches=%d flags=0x%x\n"),
   8733                      imin, imax, nmatches, rep_st->flags));
   8734     } else {
   8735         /* EXT_L2_ENTRY_2 */
   8736         ppa_info = SOC_CONTROL(unit)->ext_l2_ppa_info_2;
   8737         ppa_vlan = SOC_CONTROL(unit)->ext_l2_ppa_vlan_2;
   8738         if (ppa_info == NULL) {
   8739             return BCM_E_NONE;
   8740         }
   8741 
   8742         mem = EXT_L2_ENTRY_2m;
   8743         imin = soc_mem_index_min(unit, mem);
   8744         imax = soc_mem_index_max(unit, mem);
   8745 
   8746         /* convert match data */
   8747         entdata = _SOC_TR3_L2E_VALID;
   8748         entmask = _SOC_TR3_L2E_VALID;
   8749         if (!(rep_st->flags & BCM_L2_REPLACE_MATCH_STATIC)) {
   8750             entdata |= 0x00000000;
   8751             entmask |= _SOC_TR3_L2E_STATIC;
   8752         }
   8753         if (rep_st->flags & BCM_L2_REPLACE_MATCH_VLAN) {
   8754             entdata |= (rep_st->key_vlan & _SOC_TR3_L2E_VLAN_MASK) <<
   8755                 _SOC_TR3_L2E_VLAN_SHIFT;
   8756             entmask |= _SOC_TR3_L2E_VLAN_MASK << _SOC_TR3_L2E_VLAN_SHIFT;
   8757             imin = ppa_vlan->vlan_min[rep_st->key_vlan];
   8758             imax = ppa_vlan->vlan_max[rep_st->key_vlan];
   8759         }
   8760         if (rep_st->flags & BCM_L2_REPLACE_MATCH_DEST) {
   8761             if (rep_st->match_dest.trunk != -1) {
   8762                 entdata |= _SOC_TR3_L2E_T |
   8763                     ((rep_st->match_dest.trunk & _SOC_TR3_L2E_TRUNK_MASK)
   8764                      << _SOC_TR3_L2E_TRUNK_SHIFT);
   8765                 entmask |= _SOC_TR3_L2E_T |
   8766                     (_SOC_TR3_L2E_TRUNK_MASK << _SOC_TR3_L2E_TRUNK_SHIFT);
   8767             } else if (rep_st->match_dest.vp != -1) {
   8768                 entdata |= _SOC_TR3_L2E_VP |
   8769                     ((rep_st->match_dest.vp & _SOC_TR3_L2E_DESTINATION_MASK)
   8770                      << _SOC_TR3_L2E_DESTINATION_SHIFT);
   8771                 entmask |= _SOC_TR3_L2E_VP |
   8772                     (_SOC_TR3_L2E_DESTINATION_MASK << 
   8773                      _SOC_TR3_L2E_DESTINATION_SHIFT);
   8774             } else {
   8775                 entdata |= 
   8776                     ((rep_st->match_dest.module & _SOC_TR3_L2E_MOD_MASK) <<
   8777                      _SOC_TR3_L2E_MOD_SHIFT) |
   8778                     ((rep_st->match_dest.port & _SOC_TR3_L2E_PORT_MASK) <<
   8779                      _SOC_TR3_L2E_PORT_SHIFT);
   8780                 entmask |= _SOC_TR3_L2E_T | _SOC_TR3_L2E_VP |
   8781                     (_SOC_TR3_L2E_MOD_MASK << _SOC_TR3_L2E_MOD_SHIFT) |
   8782                     (_SOC_TR3_L2E_PORT_MASK << _SOC_TR3_L2E_PORT_SHIFT);
   8783             }
   8784         }
   8785 
   8786         nmatches = 0;
   8787 
   8788         if (imin >= 0) {
   8789             if ((imax - imin) > SOC_CONTROL(unit)->ext_l2_ppa_threshold) {
   8790                 return BCM_E_UNAVAIL;
   8791             }
   8792             for (i = imin; i <= imax; i++) {
   8793                 entvalue = ppa_info[i].data;
   8794                 if ((entvalue & entmask) != entdata) {
   8795                     continue;
   8796                 }
   8797                 if (rep_st->flags & BCM_L2_REPLACE_MATCH_MAC) {
   8798                     if (ENET_CMP_MACADDR(rep_st->key_mac, ppa_info[i].mac)) {
   8799                         continue;
   8800                     }
   8801                 }
   8802                 nmatches += 1;
   8803 
   8804                 /* lookup the matched entry */
   8805                 sal_memset(&l2_entry_2, 0, sizeof(l2_entry_2));
   8806                 memacc = _BCM_TR3_L2_MEMACC(unit, EXT_L2_ENTRY_2,
   8807                                             _BCM_TR3_L2_MEMACC_VLAN_ID);
   8808                 soc_memacc_field32_set(memacc, &l2_entry_2, (entvalue >> 16) & 0xfff);
   8809                 memacc = _BCM_TR3_L2_MEMACC(unit, EXT_L2_ENTRY_2,
   8810                                         _BCM_TR3_L2_MEMACC_MAC_ADDR);
   8811                 soc_memacc_mac_addr_set(memacc, &l2_entry_2, 
   8812                                         ppa_info[i].mac);
   8813 
   8814                 /* In case of a VP entry, also assign the KEY_TYPE */
   8815                 if(entvalue & _SOC_TR3_L2E_VP) {
   8816                     memacc = _BCM_TR3_L2_MEMACC(unit, EXT_L2_ENTRY_2,
   8817                                                 _BCM_TR3_L2_MEMACC_KEY_TYPE);
   8818                     soc_memacc_field32_set(memacc, &l2_entry_1, rep_st->ext_key_type);
   8819                 }
   8820 
   8821                 /* operate on matched entry */
   8822                 if (rep_st->flags & BCM_L2_REPLACE_DELETE) {
   8823                     rv = soc_mem_generic_delete(unit, mem, MEM_BLOCK_ANY, 0,
   8824                                                 &l2_entry_2, &l2_entry_2, NULL);
   8825                     if (rv < 0) {
   8826                         return rv;
   8827                     }
   8828                 } else {
   8829                     /* replace destination fields */
   8830                     rv = soc_mem_generic_lookup(unit, mem, MEM_BLOCK_ANY, 0,
   8831                                                 &l2_entry_2, &l2_entry_2, NULL);
   8832                     if (rep_st->flags & BCM_L2_REPLACE_NEW_TRUNK) {
   8833                         memacc = _BCM_TR3_L2_MEMACC(unit, EXT_L2_ENTRY_2,
   8834                                                     _BCM_TR3_L2_MEMACC_DEST_TYPE);
   8835                         soc_memacc_field32_set(memacc, &l2_entry_2, 1);
   8836                         memacc = _BCM_TR3_L2_MEMACC(unit, EXT_L2_ENTRY_2,
   8837                                                     _BCM_TR3_L2_MEMACC_TGID);
   8838                         soc_memacc_field32_set(memacc, &l2_entry_2, rep_st->new_dest.trunk);
   8839                     } else {
   8840                         memacc = _BCM_TR3_L2_MEMACC(unit, EXT_L2_ENTRY_2,
   8841                                                     _BCM_TR3_L2_MEMACC_MODULE_ID);
   8842                         soc_memacc_field32_set(memacc, &l2_entry_2, rep_st->new_dest.module);
   8843                         memacc = _BCM_TR3_L2_MEMACC(unit, EXT_L2_ENTRY_2,
   8844                                                     _BCM_TR3_L2_MEMACC_PORT_NUM);
   8845                         soc_memacc_field32_set(memacc, &l2_entry_2, rep_st->new_dest.port);
   8846                     }
   8847                     /* re-insert entry */
   8848                     rv = soc_mem_generic_insert(unit, mem, MEM_BLOCK_ANY, 0,
   8849                                                 &l2_entry_2, &old_l2_entry_2, NULL);
   8850                     if (rv == BCM_E_EXISTS) {
   8851                         rv = BCM_E_NONE;
   8852                     }
   8853                     if (rv < 0) {
   8854                         return rv;
   8855                     }
   8856                 }
   8857             }
   8858         }
   8859         LOG_VERBOSE(BSL_LS_SOC_COMMON,
   8860                     (BSL_META_U(unit,
   8861                                 "tr_l2e_ppa_match 2: imin=%d imax=%d nmatches=%d flags=0x%x\n"),
   8862                      imin, imax, nmatches, rep_st->flags));
   8863     }
   8864     return BCM_E_NONE;
   8865 }
   8866 
   8867 /*
   8868  * Function:
   8869  *     _bcm_tr3_l2_bulk_control
   8870  * Description:
   8871  *     Setup hardware L2 bulk control registers
   8872  * Parameters:
   8873  *     unit         device number
   8874  *     rep_st       structure with information of what to replace
   8875  * Return:
   8876  *     BCM_E_XXX
   8877  */
   8878 STATIC int
   8879 _bcm_tr3_l2_bulk_control(int unit, _soc_tr3_l2_replace_t *rep_st)
   8880 {
   8881     int rv = BCM_E_NONE;
   8882     uint32 rval;
   8883 
   8884     SOC_IF_ERROR_RETURN(READ_L2_BULK_CONTROLr(unit, &rval));
   8885     if (SOC_CONTROL(unit)->l2x_mode == L2MODE_FIFO) {
   8886         soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, L2_MOD_FIFO_RECORDf,
   8887                           ((rep_st->flags & BCM_L2_REPLACE_NO_CALLBACKS) ? 0 : 1));
   8888     } else {
   8889         soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, L2_MOD_FIFO_RECORDf, 0);
   8890     }
   8891     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ACTIONf,
   8892                       (rep_st->flags & BCM_L2_REPLACE_AGE ? 3: (rep_st->flags & BCM_L2_REPLACE_DELETE ? 1 : 2)));
   8893     
   8894     /* First work on L2_ENTRY_1m */
   8895     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, BURST_ENTRIESf, 
   8896                       _SOC_TR3_L2_BULK_BURST_MAX);
   8897     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ENTRY_WIDTHf, 0);
   8898     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, NUM_ENTRIESf, 
   8899                       soc_mem_index_count(unit, L2_ENTRY_1m));
   8900     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, EXTERNAL_L2_ENTRYf, 0);
   8901     SOC_IF_ERROR_RETURN(WRITE_L2_BULK_CONTROLr(unit, rval));
   8902 
   8903     /* Set match mask */
   8904     BCM_IF_ERROR_RETURN
   8905         (WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 1, &rep_st->match_mask1));
   8906     /* Set match data */
   8907     BCM_IF_ERROR_RETURN
   8908         (WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 0, &rep_st->match_data1));
   8909     /* Set replace mask */
   8910     BCM_IF_ERROR_RETURN
   8911         (WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 3, &rep_st->new_mask1));
   8912     /* Set replace data */
   8913     BCM_IF_ERROR_RETURN
   8914         (WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 2, &rep_st->new_data1));
   8915     
   8916     BCM_IF_ERROR_RETURN(soc_tr3_l2_port_age(unit, L2_BULK_CONTROLr, INVALIDr));
   8917     
   8918     /* Then work on L2_ENTRY_2 */
   8919     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ENTRY_WIDTHf, 1);
   8920     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, NUM_ENTRIESf, 
   8921                       soc_mem_index_count(unit, L2_ENTRY_2m));
   8922     SOC_IF_ERROR_RETURN(WRITE_L2_BULK_CONTROLr(unit, rval));
   8923 
   8924     /* Set match mask */
   8925     BCM_IF_ERROR_RETURN
   8926         (WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 1, &rep_st->match_mask2));
   8927     /* Set match data */
   8928     BCM_IF_ERROR_RETURN
   8929         (WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 0, &rep_st->match_data2));
   8930     /* Set replace mask */
   8931     BCM_IF_ERROR_RETURN
   8932         (WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 3, &rep_st->new_mask2));
   8933     /* Set replace data */
   8934     BCM_IF_ERROR_RETURN
   8935         (WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 2, &rep_st->new_data2));
   8936     
   8937     BCM_IF_ERROR_RETURN(soc_tr3_l2_port_age(unit, L2_BULK_CONTROLr, INVALIDr));
   8938 
   8939     if (!soc_feature(unit, soc_feature_esm_support)) {
   8940         return BCM_E_NONE;
   8941     }
   8942     
   8943     /* First work on EXT_L2_ENTRY_1 */
   8944     if (SOC_CONTROL(unit)->l2e_ppa) {
   8945         rv = _bcm_tr3_l2e_ppa_match(unit, rep_st, EXT_L2_ENTRY_1m);
   8946         if (BCM_FAILURE(rv) && (rv != BCM_E_UNAVAIL)) {
   8947             return rv;
   8948         }
   8949     }
   8950     if (!SOC_CONTROL(unit)->l2e_ppa || (rv == BCM_E_UNAVAIL)) {
   8951         soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, BURST_ENTRIESf, 
   8952                           _SOC_TR3_L2_BULK_BURST_MAX);
   8953         soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ENTRY_WIDTHf, 0);
   8954         soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, NUM_ENTRIESf, 
   8955                           SOC_MEM_TR3_EXT_L2_MAX_ENTRIES);
   8956         soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, EXTERNAL_L2_ENTRYf, 1);
   8957         SOC_IF_ERROR_RETURN(WRITE_L2_BULK_CONTROLr(unit, rval));
   8958 
   8959         /* Set match mask */
   8960         BCM_IF_ERROR_RETURN
   8961             (WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 1, &rep_st->ext_match_mask1));
   8962         /* Set match data */
   8963         BCM_IF_ERROR_RETURN
   8964             (WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 0, &rep_st->ext_match_data1));
   8965         /* Set replace mask */
   8966         BCM_IF_ERROR_RETURN
   8967             (WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 3, &rep_st->ext_new_mask1));
   8968         /* Set replace data */
   8969         BCM_IF_ERROR_RETURN
   8970             (WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 2, &rep_st->ext_new_data1));
   8971 
   8972         BCM_IF_ERROR_RETURN(soc_tr3_l2_port_age(unit, L2_BULK_CONTROLr, INVALIDr));
   8973         SOC_IF_ERROR_RETURN(WRITE_ETU_EXT_L2_BULK_INFOr(unit, 0));
   8974         /* Issue dummy op */
   8975         soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ACTIONf, 0);
   8976         soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ENTRY_WIDTHf, 0);
   8977         soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, NUM_ENTRIESf, 1);
   8978         SOC_IF_ERROR_RETURN(WRITE_L2_BULK_CONTROLr(unit, rval));
   8979         SOC_IF_ERROR_RETURN(soc_tr3_l2_port_age(unit, L2_BULK_CONTROLr, INVALIDr));
   8980         SOC_IF_ERROR_RETURN(WRITE_ETU_EXT_L2_BULK_INFOr(unit, 0));
   8981     }
   8982     
   8983     rv = BCM_E_NONE;
   8984     /* Then work on EXT_L2_ENTRY_2 */
   8985     if (SOC_CONTROL(unit)->l2e_ppa) {
   8986         rv = _bcm_tr3_l2e_ppa_match(unit, rep_st, EXT_L2_ENTRY_2m);
   8987         if (BCM_FAILURE(rv) && (rv != BCM_E_UNAVAIL)) {
   8988             return rv;
   8989         }
   8990     }
   8991     if (!SOC_CONTROL(unit)->l2e_ppa || (rv == BCM_E_UNAVAIL)) {
   8992         soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ACTIONf,
   8993                           (rep_st->flags & BCM_L2_REPLACE_AGE ? 
   8994                           3 : (rep_st->flags & BCM_L2_REPLACE_DELETE ? 1 : 2)));
   8995         soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ENTRY_WIDTHf, 1);
   8996         soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, NUM_ENTRIESf, 
   8997                           SOC_MEM_TR3_EXT_L2_MAX_ENTRIES);
   8998         SOC_IF_ERROR_RETURN(WRITE_L2_BULK_CONTROLr(unit, rval));
   8999 
   9000         /* Set match mask */
   9001         BCM_IF_ERROR_RETURN
   9002             (WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 1, &rep_st->ext_match_mask2));
   9003         /* Set match data */
   9004         BCM_IF_ERROR_RETURN
   9005             (WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 0, &rep_st->ext_match_data2));
   9006         /* Set replace mask */
   9007         BCM_IF_ERROR_RETURN
   9008             (WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 3, &rep_st->ext_new_mask2));
   9009         /* Set replace data */
   9010         BCM_IF_ERROR_RETURN
   9011             (WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 2, &rep_st->ext_new_data2));
   9012 
   9013         BCM_IF_ERROR_RETURN(soc_tr3_l2_port_age(unit, L2_BULK_CONTROLr, INVALIDr));
   9014         SOC_IF_ERROR_RETURN(WRITE_ETU_EXT_L2_BULK_INFOr(unit, 0));
   9015         /* Issue dummy op */
   9016         soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ACTIONf, 0);
   9017         soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ENTRY_WIDTHf, 0);
   9018         soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, NUM_ENTRIESf, 1);
   9019         SOC_IF_ERROR_RETURN(WRITE_L2_BULK_CONTROLr(unit, rval));
   9020         SOC_IF_ERROR_RETURN(soc_tr3_l2_port_age(unit, L2_BULK_CONTROLr, INVALIDr));
   9021         SOC_IF_ERROR_RETURN(WRITE_ETU_EXT_L2_BULK_INFOr(unit, 0));
   9022     }
   9023     
   9024     return BCM_E_NONE;
   9025 }
   9026 
   9027 /*
   9028  * Function:
   9029  *     _bcm_tr3_l2_replace_by_hw
   9030  * Description:
   9031  *     Helper function to _bcm_tr3_l2_replace_by_hw
   9032  * Parameters:
   9033  *     unit         device number
   9034  *     rep_st       structure with information of what to replace
   9035  * Return:
   9036  *     BCM_E_XXX
   9037  */
   9038 STATIC int
   9039 _bcm_tr3_l2_replace_by_hw(int unit, _soc_tr3_l2_replace_t *rep_st)
   9040 {
   9041     int rv, seconds, enabled;
   9042 
   9043     if (NULL == rep_st) {
   9044         return BCM_E_PARAM;
   9045     }
   9046     /* Read l2 aging interval. */
   9047     SOC_IF_ERROR_RETURN
   9048         (SOC_FUNCTIONS(unit)->soc_age_timer_get(unit, &seconds, &enabled));
   9049     if (enabled) {
   9050         SOC_IF_ERROR_RETURN(soc_tr3_l2_bulk_age_stop(unit));
   9051     }
   9052     _BCM_ALL_L2X_MEM_LOCK(unit);
   9053     rv = _bcm_tr3_l2_bulk_control(unit, rep_st);
   9054     _BCM_ALL_L2X_MEM_UNLOCK(unit);
   9055     if (BCM_FAILURE(rv)) {
   9056         if (enabled) {
   9057             SOC_IF_ERROR_RETURN(soc_tr3_l2_bulk_age_start(unit, seconds));
   9058         }
   9059         return rv;
   9060     }
   9061 
   9062     if (!(rep_st->flags & BCM_L2_REPLACE_DELETE)) {
   9063         if(enabled) {
   9064             SOC_IF_ERROR_RETURN(soc_tr3_l2_bulk_age_start(unit, seconds));
   9065         }
   9066         return BCM_E_NONE;
   9067     }
   9068 
   9069     if (SOC_L2_DEL_SYNC_LOCK(SOC_CONTROL(unit)) < 0) {
   9070         if (enabled) {
   9071             SOC_IF_ERROR_RETURN(soc_tr3_l2_bulk_age_start(unit, seconds));
   9072         }
   9073         return BCM_E_RESOURCE;
   9074     }
   9075     rv = _soc_tr3_l2x_sync_replace(unit, rep_st,
   9076                                    rep_st->flags & BCM_L2_REPLACE_NO_CALLBACKS ?
   9077                                    SOC_L2X_NO_CALLBACKS : 0);
   9078     SOC_L2_DEL_SYNC_UNLOCK(SOC_CONTROL(unit));
   9079     if (enabled) {
   9080         SOC_IF_ERROR_RETURN(soc_tr3_l2_bulk_age_start(unit, seconds));
   9081     }
   9082     return rv;
   9083 }
   9084 
   9085 /*
   9086  * Function:
   9087  *     _bcm_tr3_l2_replace_dest_setup
   9088  * Description:
   9089  *     Helper function to bcm_l2_replace API to setup a destination
   9090  */
   9091 STATIC int
   9092 _bcm_tr3_l2_replace_dest_setup(int unit, bcm_module_t module, bcm_port_t port,
   9093                                bcm_trunk_t trunk, int is_trunk,
   9094                                _soc_tr3_l2_replace_dest_t *dest)
   9095 {
   9096     /* If all are -1, means ignore the replacement with new destination */
   9097     if (module == -1 && port == -1 && trunk == -1) {
   9098         dest->module = dest->port = dest->trunk = dest->vp = -1;
   9099         return BCM_E_NONE;
   9100     }
   9101 
   9102     if (BCM_GPORT_IS_SET(port)) {
   9103         if (BCM_GPORT_IS_MPLS_PORT(port) ||
   9104             BCM_GPORT_IS_SUBPORT_GROUP(port) ||
   9105             BCM_GPORT_IS_SUBPORT_PORT(port) ||
   9106             BCM_GPORT_IS_MIM_PORT(port) ||
   9107             BCM_GPORT_IS_VLAN_PORT(port) ||
   9108             BCM_GPORT_IS_WLAN_PORT(port) ||
   9109             BCM_GPORT_IS_TRILL_PORT(port) ||
   9110             BCM_GPORT_IS_NIV_PORT(port) ||
   9111             BCM_GPORT_IS_L2GRE_PORT(port) ||
   9112             BCM_GPORT_IS_EXTENDER_PORT(port)) {
   9113             /* all these gport has similar encoding format */
   9114             dest->vp = port & 0xffffff;
   9115         } else {
   9116             BCM_IF_ERROR_RETURN
   9117                 (_bcm_esw_gport_resolve(unit, port, &dest->module, &dest->port,
   9118                                         &dest->trunk, &dest->vp));
   9119         }
   9120     } else if (is_trunk) {
   9121         BCM_IF_ERROR_RETURN(_bcm_trunk_id_validate(unit, trunk));
   9122         dest->trunk = trunk;
   9123         dest->vp = -1;
   9124     } else {
   9125         PORT_DUALMODID_VALID(unit, port);
   9126         BCM_IF_ERROR_RETURN
   9127             (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_SET, module, port,
   9128                                      &dest->module, &dest->port));
   9129         if (!SOC_MODID_ADDRESSABLE(unit, dest->module)) {
   9130             return BCM_E_BADID;
   9131         }
   9132         if (!SOC_PORT_ADDRESSABLE(unit, dest->port)) {
   9133             return BCM_E_PORT;
   9134         }
   9135         dest->trunk = -1;
   9136         dest->vp = -1;
   9137     }
   9138 
   9139     return BCM_E_NONE;
   9140 }
   9141 
   9142 STATIC int
   9143 _bcm_tr3_l2_replace_data_mask_setup(int unit, _soc_tr3_l2_replace_t *rep)
   9144 {
   9145     bcm_mac_t mac_mask;
   9146     bcm_mac_t mac_data;
   9147     int key_type;
   9148     int field_len;
   9149 
   9150     sal_memset(&rep->match_mask1, 0, sizeof(l2_entry_1_entry_t));
   9151     sal_memset(&rep->match_data1, 0, sizeof(l2_entry_1_entry_t));
   9152     sal_memset(&rep->new_mask1, 0, sizeof(l2_entry_1_entry_t));
   9153     sal_memset(&rep->new_data1, 0, sizeof(l2_entry_1_entry_t));
   9154     sal_memset(&rep->match_mask2, 0, sizeof(l2_entry_2_entry_t));
   9155     sal_memset(&rep->match_data2, 0, sizeof(l2_entry_2_entry_t));
   9156     sal_memset(&rep->new_mask2, 0, sizeof(l2_entry_2_entry_t));
   9157     sal_memset(&rep->new_data2, 0, sizeof(l2_entry_2_entry_t));
   9158     
   9159     if (soc_feature(unit, soc_feature_esm_support)) {
   9160         sal_memset(&rep->ext_match_mask1, 0, sizeof(ext_l2_entry_1_entry_t));
   9161         sal_memset(&rep->ext_match_data1, 0, sizeof(ext_l2_entry_1_entry_t));
   9162         sal_memset(&rep->ext_new_mask1, 0, sizeof(ext_l2_entry_1_entry_t));
   9163         sal_memset(&rep->ext_new_data1, 0, sizeof(ext_l2_entry_1_entry_t));
   9164         sal_memset(&rep->ext_match_mask2, 0, sizeof(ext_l2_entry_2_entry_t));
   9165         sal_memset(&rep->ext_match_data2, 0, sizeof(ext_l2_entry_2_entry_t));
   9166         sal_memset(&rep->ext_new_mask2, 0, sizeof(ext_l2_entry_2_entry_t));
   9167         sal_memset(&rep->ext_new_data2, 0, sizeof(ext_l2_entry_2_entry_t));
   9168     }
   9169     /* First work on Internal L2 */
   9170     /* First work on L2_ENTRY_1m */
   9171     soc_mem_field32_set(unit, L2_ENTRY_1m, &rep->match_mask1, VALIDf, 1);
   9172     soc_mem_field32_set(unit, L2_ENTRY_1m, &rep->match_data1, VALIDf, 1);
   9173 
   9174     soc_mem_field32_set(unit, L2_ENTRY_1m, &rep->match_mask1, WIDEf, 1);
   9175     soc_mem_field32_set(unit, L2_ENTRY_1m, &rep->match_data1, WIDEf, 0);
   9176 
   9177     field_len = soc_mem_field_length(unit, L2_ENTRY_1m, KEY_TYPEf);
   9178     soc_mem_field32_set(unit, L2_ENTRY_1m, &rep->match_mask1, KEY_TYPEf,
   9179                         (1 << field_len) - 1);
   9180     soc_mem_field32_set(unit, L2_ENTRY_1m, &rep->match_data1, KEY_TYPEf,
   9181                         rep->key_type);
   9182 
   9183     if (rep->flags & BCM_L2_REPLACE_MATCH_VLAN) {
   9184         if (rep->key_vfi != -1) {
   9185             field_len = soc_mem_field_length(unit, L2_ENTRY_1m, L2__VFIf);
   9186             soc_mem_field32_set(unit, L2_ENTRY_1m, &rep->match_mask1, L2__VFIf,
   9187                                 (1 << field_len) - 1);
   9188             soc_mem_field32_set(unit, L2_ENTRY_1m, &rep->match_data1, L2__VFIf,
   9189                                 rep->key_vfi);
   9190         } else {
   9191             soc_mem_field32_set(unit, L2_ENTRY_1m, &rep->match_mask1,
   9192                                 L2__VLAN_IDf, 0xfff);
   9193             soc_mem_field32_set(unit, L2_ENTRY_1m, &rep->match_data1,
   9194                                 L2__VLAN_IDf, rep->key_vlan);
   9195         }
   9196     }
   9197 
   9198     if (rep->flags & BCM_L2_REPLACE_MATCH_MAC) {
   9199         sal_memset(&mac_mask, 0xff, sizeof(mac_mask));
   9200         soc_mem_mac_addr_set(unit, L2_ENTRY_1m, &rep->match_mask1,
   9201                              L2__MAC_ADDRf, mac_mask);
   9202         soc_mem_mac_addr_set(unit, L2_ENTRY_1m, &rep->match_data1,
   9203                              L2__MAC_ADDRf, rep->key_mac);
   9204     }
   9205 
   9206     if ((rep->flags & BCM_L2_REPLACE_MATCH_UC) && 
   9207         !(rep->flags & BCM_L2_REPLACE_MATCH_MC)) {
   9208         /* The 40th bit of Unicast must be 0 */
   9209         sal_memset(&mac_mask, 0x00, sizeof(mac_mask));
   9210         mac_mask[0] = 0x01;
   9211         sal_memset(&mac_data, 0x00, sizeof(mac_data));
   9212         soc_mem_mac_addr_set(unit, L2_ENTRY_1m, &rep->match_mask1, L2__MAC_ADDRf,
   9213                              mac_mask);
   9214         soc_mem_mac_addr_set(unit, L2_ENTRY_1m, &rep->match_data1, L2__MAC_ADDRf,
   9215                              mac_data);
   9216     } else if ((rep->flags & BCM_L2_REPLACE_MATCH_MC) &&
   9217          !(rep->flags & BCM_L2_REPLACE_MATCH_UC)) {
   9218         /* The 40th bit of Multicast must be 1 */
   9219         sal_memset(&mac_mask, 0x00, sizeof(mac_mask));
   9220         mac_mask[0] = 0x01;
   9221         sal_memset(&mac_data, 0x00, sizeof(mac_data));
   9222         mac_data[0] = 0x01;
   9223         soc_mem_mac_addr_set(unit, L2_ENTRY_1m, &rep->match_mask1, L2__MAC_ADDRf,
   9224                              mac_mask);
   9225         soc_mem_mac_addr_set(unit, L2_ENTRY_1m, &rep->match_data1, L2__MAC_ADDRf,
   9226                              mac_data);
   9227     }
   9228 
   9229     if (rep->flags & BCM_L2_REPLACE_MATCH_DEST) {
   9230         field_len = soc_mem_field_length(unit, L2_ENTRY_1m, L2__DEST_TYPEf);
   9231         soc_mem_field32_set(unit, L2_ENTRY_1m, &rep->match_mask1,
   9232                             L2__DEST_TYPEf, (1 << field_len) - 1);
   9233         if (rep->match_dest.vp != -1) {
   9234             soc_mem_field32_set(unit, L2_ENTRY_1m, &rep->match_data1,
   9235                                 L2__DEST_TYPEf, 2);
   9236 
   9237             field_len = soc_mem_field_length(unit, L2_ENTRY_1m,
   9238                                              L2__DESTINATIONf);
   9239             soc_mem_field32_set(unit, L2_ENTRY_1m, &rep->match_mask1,
   9240                                 L2__DESTINATIONf, (1 << field_len) - 1);
   9241             soc_mem_field32_set(unit, L2_ENTRY_1m, &rep->match_data1,
   9242                                 L2__DESTINATIONf, rep->match_dest.vp);
   9243         } else if (rep->match_dest.trunk != -1) {
   9244             soc_mem_field32_set(unit, L2_ENTRY_1m, &rep->match_data1,
   9245                                 L2__DEST_TYPEf, 1);
   9246 
   9247             field_len = soc_mem_field_length(unit, L2_ENTRY_1m, L2__TGIDf);
   9248             soc_mem_field32_set(unit, L2_ENTRY_1m, &rep->match_mask1,
   9249                                 L2__TGIDf, (1 << field_len) - 1);
   9250             soc_mem_field32_set(unit, L2_ENTRY_1m, &rep->match_data1,
   9251                                 L2__TGIDf, rep->match_dest.trunk);
   9252         } else {
   9253             /* L2__DEST_TYPEf == 0 */
   9254 
   9255             field_len = soc_mem_field_length(unit, L2_ENTRY_1m,
   9256                                              L2__MODULE_IDf);
   9257             soc_mem_field32_set(unit, L2_ENTRY_1m, &rep->match_mask1,
   9258                                 L2__MODULE_IDf, (1 << field_len) - 1);
   9259             soc_mem_field32_set(unit, L2_ENTRY_1m, &rep->match_data1,
   9260                                 L2__MODULE_IDf, rep->match_dest.module);
   9261 
   9262             field_len = soc_mem_field_length(unit, L2_ENTRY_1m, L2__PORT_NUMf);
   9263             soc_mem_field32_set(unit, L2_ENTRY_1m, &rep->match_mask1,
   9264                                 L2__PORT_NUMf, (1 << field_len) - 1);
   9265             soc_mem_field32_set(unit, L2_ENTRY_1m, &rep->match_data1,
   9266                                 L2__PORT_NUMf, rep->match_dest.port);
   9267         }
   9268     }
   9269 
   9270     if (!(rep->flags & BCM_L2_REPLACE_MATCH_STATIC)) {
   9271         soc_mem_field32_set(unit, L2_ENTRY_1m, &rep->match_mask1, STATIC_BITf,
   9272                             1);
   9273         /* STATIC_BIT field in data is 0 */
   9274     }
   9275 
   9276     soc_mem_field32_set(unit, L2_ENTRY_1m, &rep->match_mask1, L2__PENDINGf, 1);
   9277     if (rep->flags & BCM_L2_REPLACE_PENDING) {
   9278         soc_mem_field32_set(unit, L2_ENTRY_1m, &rep->match_data1, L2__PENDINGf,
   9279                             1);
   9280     }
   9281 
   9282     if (!(rep->flags & (BCM_L2_REPLACE_DELETE|BCM_L2_REPLACE_AGE))) {
   9283         if (rep->new_dest.vp != -1) {
   9284             field_len = soc_mem_field_length(unit, L2_ENTRY_1m, L2__DEST_TYPEf);
   9285             soc_mem_field32_set(unit, L2_ENTRY_1m, &rep->new_mask1,
   9286                                 L2__DEST_TYPEf, (1 << field_len) - 1);
   9287 
   9288             soc_mem_field32_set(unit, L2_ENTRY_1m, &rep->new_data1,
   9289                                 L2__DEST_TYPEf, 2);
   9290 
   9291             field_len = soc_mem_field_length(unit, L2_ENTRY_1m,
   9292                                              L2__DESTINATIONf);
   9293             soc_mem_field32_set(unit, L2_ENTRY_1m, &rep->new_mask1,
   9294                                 L2__DESTINATIONf, (1 << field_len) - 1);
   9295             soc_mem_field32_set(unit, L2_ENTRY_1m, &rep->new_data1,
   9296                                 L2__DESTINATIONf, rep->new_dest.vp);
   9297         } else if (rep->new_dest.trunk != -1) {
   9298             field_len = soc_mem_field_length(unit, L2_ENTRY_1m, L2__DEST_TYPEf);
   9299             soc_mem_field32_set(unit, L2_ENTRY_1m, &rep->new_mask1,
   9300                                 L2__DEST_TYPEf, (1 << field_len) - 1);
   9301 
   9302             soc_mem_field32_set(unit, L2_ENTRY_1m, &rep->new_data1,
   9303                                 L2__DEST_TYPEf, 1);
   9304 
   9305             field_len = soc_mem_field_length(unit, L2_ENTRY_1m, L2__TGIDf);
   9306             soc_mem_field32_set(unit, L2_ENTRY_1m, &rep->new_mask1,
   9307                                 L2__TGIDf, (1 << field_len) - 1);
   9308             soc_mem_field32_set(unit, L2_ENTRY_1m, &rep->new_data1,
   9309                                 L2__TGIDf, rep->new_dest.trunk);
   9310         } else if (rep->new_dest.port != -1 
   9311                    && rep->new_dest.module != -1) {
   9312             /* L2__DEST_TYPEf == 0 */
   9313             field_len = soc_mem_field_length(unit, L2_ENTRY_1m, L2__DEST_TYPEf);
   9314             soc_mem_field32_set(unit, L2_ENTRY_1m, &rep->new_mask1,
   9315                                 L2__DEST_TYPEf, (1 << field_len) - 1);
   9316 
   9317             field_len = soc_mem_field_length(unit, L2_ENTRY_1m,
   9318                                              L2__MODULE_IDf);
   9319             soc_mem_field32_set(unit, L2_ENTRY_1m, &rep->new_mask1,
   9320                                 L2__MODULE_IDf, (1 << field_len) - 1);
   9321             soc_mem_field32_set(unit, L2_ENTRY_1m, &rep->new_data1,
   9322                                 L2__MODULE_IDf, rep->new_dest.module);
   9323 
   9324             field_len = soc_mem_field_length(unit, L2_ENTRY_1m, L2__PORT_NUMf);
   9325             soc_mem_field32_set(unit, L2_ENTRY_1m, &rep->new_mask1,
   9326                                 L2__PORT_NUMf, (1 << field_len) - 1);
   9327             soc_mem_field32_set(unit, L2_ENTRY_1m, &rep->new_data1,
   9328                                 L2__PORT_NUMf, rep->new_dest.port);
   9329         }
   9330 
   9331         if (rep->flags & BCM_L2_REPLACE_DES_HIT_CLEAR) {
   9332             soc_mem_field32_set(unit, L2_ENTRY_1m, &rep->new_mask1,
   9333                                 HITDAf, 1);
   9334         }
   9335         if (rep->flags & BCM_L2_REPLACE_SRC_HIT_CLEAR) {
   9336             soc_mem_field32_set(unit, L2_ENTRY_1m, &rep->new_mask1,
   9337                                 HITSAf, 1);
   9338         }
   9339     }
   9340 
   9341     /* Then work on L2_ENTRY_2 */
   9342     soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->match_mask2, VALID_0f, 1);
   9343     soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->match_mask2, VALID_1f, 1);
   9344     soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->match_data2, VALID_0f, 1);
   9345     soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->match_data2, VALID_1f, 1);
   9346 
   9347     soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->match_mask2, WIDE_0f, 1);
   9348     soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->match_mask2, WIDE_1f, 1);
   9349     soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->match_data2, WIDE_0f, 1);
   9350     soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->match_data2, WIDE_1f, 1);
   9351 
   9352     field_len = soc_mem_field_length(unit, L2_ENTRY_2m, KEY_TYPE_0f);
   9353     soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->match_mask2, KEY_TYPE_0f,
   9354                         (1 << field_len) - 1);
   9355     soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->match_mask2, KEY_TYPE_1f,
   9356                         (1 << field_len) - 1);
   9357     if (rep->key_type == SOC_MEM_KEY_L2_ENTRY_1_L2_BRIDGE) {
   9358         key_type = SOC_MEM_KEY_L2_ENTRY_2_L2_BRIDGE;
   9359     } else if (rep->key_type == SOC_MEM_KEY_L2_ENTRY_1_L2_VFI) {
   9360         key_type = SOC_MEM_KEY_L2_ENTRY_2_L2_VFI;
   9361     } else {
   9362         key_type = rep->key_type;
   9363     }
   9364     soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->match_data2, KEY_TYPE_0f,
   9365                         key_type);
   9366     soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->match_data2, KEY_TYPE_1f,
   9367                         key_type);
   9368 
   9369     if (rep->flags & BCM_L2_REPLACE_MATCH_VLAN) {
   9370         if (rep->key_vfi != -1) {
   9371             field_len = soc_mem_field_length(unit, L2_ENTRY_2m, L2__VFIf);
   9372             soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->match_mask2, L2__VFIf,
   9373                                 (1 << field_len) - 1);
   9374             soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->match_data2, L2__VFIf,
   9375                                 rep->key_vfi);
   9376         } else {
   9377             soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->match_mask2,
   9378                                 L2__VLAN_IDf, 0xfff);
   9379             soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->match_data2,
   9380                                 L2__VLAN_IDf, rep->key_vlan);
   9381         }
   9382     }
   9383 
   9384     if (rep->flags & BCM_L2_REPLACE_MATCH_MAC) {
   9385         sal_memset(&mac_mask, 0xff, sizeof(mac_mask));
   9386         soc_mem_mac_addr_set(unit, L2_ENTRY_2m, &rep->match_mask2,
   9387                              L2__MAC_ADDRf, mac_mask);
   9388         soc_mem_mac_addr_set(unit, L2_ENTRY_2m, &rep->match_data2,
   9389                              L2__MAC_ADDRf, rep->key_mac);
   9390     }
   9391 
   9392     if (rep->flags & BCM_L2_REPLACE_MATCH_DEST) {
   9393         field_len = soc_mem_field_length(unit, L2_ENTRY_2m, L2__DEST_TYPEf);
   9394         soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->match_mask2,
   9395                             L2__DEST_TYPEf, (1 << field_len) - 1);
   9396         if (rep->match_dest.vp != -1) {
   9397             soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->match_data2,
   9398                                 L2__DEST_TYPEf, 2);
   9399 
   9400             field_len = soc_mem_field_length(unit, L2_ENTRY_2m,
   9401                                              L2__DESTINATIONf);
   9402             soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->match_mask2,
   9403                                 L2__DESTINATIONf, (1 << field_len) - 1);
   9404             soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->match_data2,
   9405                                 L2__DESTINATIONf, rep->match_dest.vp);
   9406         } else if (rep->match_dest.trunk != -1) {
   9407             soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->match_data2,
   9408                                 L2__DEST_TYPEf, 1);
   9409 
   9410             field_len = soc_mem_field_length(unit, L2_ENTRY_2m, L2__TGIDf);
   9411             soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->match_mask2,
   9412                                 L2__TGIDf, (1 << field_len) - 1);
   9413             soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->match_data2,
   9414                                 L2__TGIDf, rep->match_dest.trunk);
   9415         } else {
   9416             /* L2__DEST_TYPEf == 0 */
   9417 
   9418             field_len = soc_mem_field_length(unit, L2_ENTRY_2m,
   9419                                              L2__MODULE_IDf);
   9420             soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->match_mask2,
   9421                                 L2__MODULE_IDf, (1 << field_len) - 1);
   9422             soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->match_data2,
   9423                                 L2__MODULE_IDf, rep->match_dest.module);
   9424 
   9425             field_len = soc_mem_field_length(unit, L2_ENTRY_2m, L2__PORT_NUMf);
   9426             soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->match_mask2,
   9427                                 L2__PORT_NUMf, (1 << field_len) - 1);
   9428             soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->match_data2,
   9429                                 L2__PORT_NUMf, rep->match_dest.port);
   9430         }
   9431     }
   9432 
   9433     if (!(rep->flags & BCM_L2_REPLACE_MATCH_STATIC)) {
   9434         soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->match_mask2,
   9435                             STATIC_BIT_0f, 1);
   9436         soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->match_mask2,
   9437                             STATIC_BIT_1f, 1);
   9438         /* STATIC_BIT field in data is 0 */
   9439     }
   9440 
   9441     soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->match_mask2, L2__PENDINGf, 1);
   9442     if (rep->flags & BCM_L2_REPLACE_PENDING) {
   9443         soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->match_data2, L2__PENDINGf,
   9444                             1);
   9445     }
   9446 
   9447     if (!(rep->flags & (BCM_L2_REPLACE_DELETE|BCM_L2_REPLACE_AGE))) {
   9448         if (rep->new_dest.vp != -1) {
   9449             field_len = soc_mem_field_length(unit, L2_ENTRY_2m, L2__DEST_TYPEf);
   9450             soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->new_mask2,
   9451                                 L2__DEST_TYPEf, (1 << field_len) - 1);
   9452 
   9453             soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->new_data2,
   9454                                 L2__DEST_TYPEf, 2);
   9455 
   9456             field_len = soc_mem_field_length(unit, L2_ENTRY_2m,
   9457                                              L2__DESTINATIONf);
   9458             soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->new_mask2,
   9459                                 L2__DESTINATIONf, (1 << field_len) - 1);
   9460             soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->new_data2,
   9461                                 L2__DESTINATIONf, rep->new_dest.vp);
   9462         } else if (rep->new_dest.trunk != -1) {
   9463             field_len = soc_mem_field_length(unit, L2_ENTRY_2m, L2__DEST_TYPEf);
   9464             soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->new_mask2,
   9465                                 L2__DEST_TYPEf, (1 << field_len) - 1);
   9466 
   9467             soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->new_data2,
   9468                                 L2__DEST_TYPEf, 1);
   9469 
   9470             field_len = soc_mem_field_length(unit, L2_ENTRY_2m, L2__TGIDf);
   9471             soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->new_mask2,
   9472                                 L2__TGIDf, (1 << field_len) - 1);
   9473             soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->new_data2,
   9474                                 L2__TGIDf, rep->new_dest.trunk);
   9475         } else if (rep->new_dest.port != -1 
   9476                    && rep->new_dest.module != -1) {
   9477             /* L2__DEST_TYPEf == 0 */
   9478             field_len = soc_mem_field_length(unit, L2_ENTRY_2m, L2__DEST_TYPEf);
   9479             soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->new_mask2,
   9480                                 L2__DEST_TYPEf, (1 << field_len) - 1);
   9481 
   9482             field_len = soc_mem_field_length(unit, L2_ENTRY_2m,
   9483                                              L2__MODULE_IDf);
   9484             soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->new_mask2,
   9485                                 L2__MODULE_IDf, (1 << field_len) - 1);
   9486             soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->new_data2,
   9487                                 L2__MODULE_IDf, rep->new_dest.module);
   9488 
   9489             field_len = soc_mem_field_length(unit, L2_ENTRY_2m,
   9490                                              L2__PORT_NUMf);
   9491             soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->new_mask2,
   9492                                 L2__PORT_NUMf, (1 << field_len) - 1);
   9493             soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->new_data2,
   9494                                 L2__PORT_NUMf, rep->new_dest.port);
   9495         }
   9496 
   9497         if (rep->flags & BCM_L2_REPLACE_DES_HIT_CLEAR) {
   9498             soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->new_mask2,
   9499                                 HITDAf, 1);
   9500         }
   9501         if (rep->flags & BCM_L2_REPLACE_SRC_HIT_CLEAR) {
   9502             soc_mem_field32_set(unit, L2_ENTRY_2m, &rep->new_mask2,
   9503                                 HITSAf, 1);
   9504         }
   9505     }
   9506     
   9507     /* Then work on External L2 */
   9508     if (!soc_feature(unit, soc_feature_esm_support)) {
   9509         return BCM_E_NONE;
   9510     }
   9511 
   9512     /* First work on EXT_L2_ENTRY_1 */
   9513     field_len = soc_mem_field_length(unit, EXT_L2_ENTRY_1m, KEY_TYPEf);
   9514     soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &rep->ext_match_mask1, KEY_TYPEf,
   9515                         (1 << field_len) - 1);
   9516     soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &rep->ext_match_data1, KEY_TYPEf,
   9517                         rep->ext_key_type);
   9518 
   9519     if (rep->flags & BCM_L2_REPLACE_MATCH_VLAN) {
   9520         if (rep->key_vfi != -1) {
   9521             field_len = soc_mem_field_length(unit, EXT_L2_ENTRY_1m, VFIf);
   9522             soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &rep->ext_match_mask1, 
   9523                                 VFIf, (1 << field_len) - 1);
   9524             soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &rep->ext_match_data1, 
   9525                                 VFIf, rep->key_vfi);
   9526         } else {
   9527             soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &rep->ext_match_mask1,
   9528                                 VLAN_IDf, 0xfff);
   9529             soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &rep->ext_match_data1,
   9530                                 VLAN_IDf, rep->key_vlan);
   9531         }
   9532     }
   9533 
   9534     if (rep->flags & BCM_L2_REPLACE_MATCH_MAC) {
   9535         sal_memset(&mac_mask, 0xff, sizeof(mac_mask));
   9536         soc_mem_mac_addr_set(unit, EXT_L2_ENTRY_1m, &rep->ext_match_mask1,
   9537                              MAC_ADDRf, mac_mask);
   9538         soc_mem_mac_addr_set(unit, EXT_L2_ENTRY_1m, &rep->ext_match_data1,
   9539                              MAC_ADDRf, rep->key_mac);
   9540     }
   9541 
   9542     if (rep->flags & BCM_L2_REPLACE_MATCH_DEST) {
   9543         field_len = soc_mem_field_length(unit, EXT_L2_ENTRY_1m, DEST_TYPEf);
   9544         soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &rep->ext_match_mask1,
   9545                             DEST_TYPEf, (1 << field_len) - 1);
   9546         if (rep->match_dest.vp != -1) {
   9547             soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &rep->ext_match_data1,
   9548                                 DEST_TYPEf, 2);
   9549 
   9550             field_len = soc_mem_field_length(unit, EXT_L2_ENTRY_1m,
   9551                                              DESTINATIONf);
   9552             soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &rep->ext_match_mask1,
   9553                                 DESTINATIONf, (1 << field_len) - 1);
   9554             soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &rep->ext_match_data1,
   9555                                 DESTINATIONf, rep->match_dest.vp);
   9556         } else if (rep->match_dest.trunk != -1) {
   9557             soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &rep->ext_match_data1,
   9558                                 DEST_TYPEf, 1);
   9559 
   9560             field_len = soc_mem_field_length(unit, EXT_L2_ENTRY_1m, TGIDf);
   9561             soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &rep->ext_match_mask1,
   9562                                 TGIDf, (1 << field_len) - 1);
   9563             soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &rep->ext_match_data1,
   9564                                 TGIDf, rep->match_dest.trunk);
   9565         } else {
   9566             /* DEST_TYPEf == 0 */
   9567             field_len = soc_mem_field_length(unit, EXT_L2_ENTRY_1m,
   9568                                              MODULE_IDf);
   9569             soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &rep->ext_match_mask1,
   9570                                 MODULE_IDf, (1 << field_len) - 1);
   9571             soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &rep->ext_match_data1,
   9572                                 MODULE_IDf, rep->match_dest.module);
   9573 
   9574             field_len = soc_mem_field_length(unit, EXT_L2_ENTRY_1m, PORT_NUMf);
   9575             soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &rep->ext_match_mask1,
   9576                                 PORT_NUMf, (1 << field_len) - 1);
   9577             soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &rep->ext_match_data1,
   9578                                 PORT_NUMf, rep->match_dest.port);
   9579         }
   9580     }
   9581 
   9582     if (!(rep->flags & BCM_L2_REPLACE_MATCH_STATIC)) {
   9583         soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &rep->ext_match_mask1, 
   9584                             STATIC_BITf, 1);
   9585         /* STATIC_BIT field in data is 0 */
   9586     }
   9587 
   9588     soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &rep->ext_match_mask1, PENDINGf,
   9589                         1);
   9590     if (rep->flags & BCM_L2_REPLACE_PENDING) {
   9591         soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &rep->ext_match_data1,
   9592                             PENDINGf, 1);
   9593     }
   9594 
   9595     if (!(rep->flags & (BCM_L2_REPLACE_DELETE|BCM_L2_REPLACE_AGE))) {
   9596         if (rep->new_dest.vp != -1) {
   9597             field_len = soc_mem_field_length(unit, EXT_L2_ENTRY_1m, DEST_TYPEf);
   9598             soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &rep->ext_new_mask1,
   9599                                 DEST_TYPEf, (1 << field_len) - 1);
   9600 
   9601             soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &rep->ext_new_data1,
   9602                                 DEST_TYPEf, 2);
   9603 
   9604             field_len = soc_mem_field_length(unit, EXT_L2_ENTRY_1m,
   9605                                              DESTINATIONf);
   9606             soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &rep->ext_new_mask1,
   9607                                 DESTINATIONf, (1 << field_len) - 1);
   9608             soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &rep->ext_new_data1,
   9609                                 DESTINATIONf, rep->new_dest.vp);
   9610         } else if (rep->new_dest.trunk != -1) {
   9611             field_len = soc_mem_field_length(unit, EXT_L2_ENTRY_1m, DEST_TYPEf);
   9612             soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &rep->ext_new_mask1,
   9613                                 DEST_TYPEf, (1 << field_len) - 1);
   9614 
   9615             soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &rep->ext_new_data1,
   9616                                 DEST_TYPEf, 1);
   9617 
   9618             field_len = soc_mem_field_length(unit, EXT_L2_ENTRY_1m, TGIDf);
   9619             soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &rep->ext_new_mask1,
   9620                                 TGIDf, (1 << field_len) - 1);
   9621             soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &rep->ext_new_data1,
   9622                                 TGIDf, rep->new_dest.trunk);
   9623         } else if (rep->new_dest.port != -1 
   9624                    && rep->new_dest.module != -1) {
   9625             /* DEST_TYPEf == 0 */
   9626             field_len = soc_mem_field_length(unit, EXT_L2_ENTRY_1m, DEST_TYPEf);
   9627             soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &rep->ext_new_mask1,
   9628                                 DEST_TYPEf, (1 << field_len) - 1);
   9629 
   9630             field_len = soc_mem_field_length(unit, EXT_L2_ENTRY_1m,
   9631                                              MODULE_IDf);
   9632             soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &rep->ext_new_mask1,
   9633                                 MODULE_IDf, (1 << field_len) - 1);
   9634             soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &rep->ext_new_data1,
   9635                                 MODULE_IDf, rep->new_dest.module);
   9636 
   9637             field_len = soc_mem_field_length(unit, EXT_L2_ENTRY_1m, PORT_NUMf);
   9638             soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &rep->ext_new_mask1,
   9639                                 PORT_NUMf, (1 << field_len) - 1);
   9640             soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &rep->ext_new_data1,
   9641                                 PORT_NUMf, rep->new_dest.port);
   9642         }
   9643 
   9644         if (rep->flags & BCM_L2_REPLACE_DES_HIT_CLEAR) {
   9645             soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &rep->ext_new_mask1,
   9646                                 HITDAf, 1);
   9647         }
   9648         if (rep->flags & BCM_L2_REPLACE_SRC_HIT_CLEAR) {
   9649             soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &rep->ext_new_mask1,
   9650                                 HITSAf, 1);
   9651         }
   9652     }
   9653 
   9654     /* Then work on EXT_L2_ENTRY_2 */
   9655     field_len = soc_mem_field_length(unit, EXT_L2_ENTRY_2m, KEY_TYPEf);
   9656     soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &rep->ext_match_mask2, KEY_TYPEf,
   9657                         (1 << field_len) - 1);
   9658     soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &rep->ext_match_data2, KEY_TYPEf,
   9659                         rep->ext_key_type);
   9660 
   9661     if (rep->flags & BCM_L2_REPLACE_MATCH_VLAN) {
   9662         if (rep->key_vfi != -1) {
   9663             field_len = soc_mem_field_length(unit, EXT_L2_ENTRY_2m, VFIf);
   9664             soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &rep->ext_match_mask2, 
   9665                                 VFIf, (1 << field_len) - 1);
   9666             soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &rep->ext_match_data2, 
   9667                                 VFIf, rep->key_vfi);
   9668         } else {
   9669             soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &rep->ext_match_mask2,
   9670                                 VLAN_IDf, 0xfff);
   9671             soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &rep->ext_match_data2,
   9672                                 VLAN_IDf, rep->key_vlan);
   9673         }
   9674     }
   9675 
   9676     if (rep->flags & BCM_L2_REPLACE_MATCH_MAC) {
   9677         sal_memset(&mac_mask, 0xff, sizeof(mac_mask));
   9678         soc_mem_mac_addr_set(unit, EXT_L2_ENTRY_2m, &rep->ext_match_mask2,
   9679                              MAC_ADDRf, mac_mask);
   9680         soc_mem_mac_addr_set(unit, EXT_L2_ENTRY_2m, &rep->ext_match_data2,
   9681                              MAC_ADDRf, rep->key_mac);
   9682     }
   9683 
   9684     if (rep->flags & BCM_L2_REPLACE_MATCH_DEST) {
   9685         field_len = soc_mem_field_length(unit, EXT_L2_ENTRY_2m, DEST_TYPEf);
   9686         soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &rep->ext_match_mask2,
   9687                             DEST_TYPEf, (1 << field_len) - 1);
   9688         if (rep->match_dest.vp != -1) {
   9689             soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &rep->ext_match_data2,
   9690                                 DEST_TYPEf, 2);
   9691 
   9692             field_len = soc_mem_field_length(unit, EXT_L2_ENTRY_2m,
   9693                                              DESTINATIONf);
   9694             soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &rep->ext_match_mask2,
   9695                                 DESTINATIONf, (1 << field_len) - 1);
   9696             soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &rep->ext_match_data2,
   9697                                 DESTINATIONf, rep->match_dest.vp);
   9698         } else if (rep->match_dest.trunk != -1) {
   9699             soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &rep->ext_match_data2,
   9700                                 DEST_TYPEf, 1);
   9701 
   9702             field_len = soc_mem_field_length(unit, EXT_L2_ENTRY_2m, TGIDf);
   9703             soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &rep->ext_match_mask2,
   9704                                 TGIDf, (1 << field_len) - 1);
   9705             soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &rep->ext_match_data2,
   9706                                 TGIDf, rep->match_dest.trunk);
   9707         } else {
   9708             /* DEST_TYPEf == 0 */
   9709             field_len = soc_mem_field_length(unit, EXT_L2_ENTRY_2m,
   9710                                              MODULE_IDf);
   9711             soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &rep->ext_match_mask2,
   9712                                 MODULE_IDf, (1 << field_len) - 1);
   9713             soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &rep->ext_match_data2,
   9714                                 MODULE_IDf, rep->match_dest.module);
   9715 
   9716             field_len = soc_mem_field_length(unit, EXT_L2_ENTRY_2m, PORT_NUMf);
   9717             soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &rep->ext_match_mask2,
   9718                                 PORT_NUMf, (1 << field_len) - 1);
   9719             soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &rep->ext_match_data2,
   9720                                 PORT_NUMf, rep->match_dest.port);
   9721         }
   9722     }
   9723 
   9724     if (!(rep->flags & BCM_L2_REPLACE_MATCH_STATIC)) {
   9725         soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &rep->ext_match_mask2,
   9726                             STATIC_BITf, 1);
   9727         /* STATIC_BIT field in data is 0 */
   9728     }
   9729 
   9730     soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &rep->ext_match_mask2, PENDINGf,
   9731                         1);
   9732     if (rep->flags & BCM_L2_REPLACE_PENDING) {
   9733         soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &rep->ext_match_data2,
   9734                             PENDINGf, 1);
   9735     }
   9736 
   9737     if (!(rep->flags & (BCM_L2_REPLACE_DELETE|BCM_L2_REPLACE_AGE))) {
   9738         if (rep->new_dest.vp != -1) {
   9739             field_len = soc_mem_field_length(unit, EXT_L2_ENTRY_2m, DEST_TYPEf);
   9740             soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &rep->ext_new_mask2,
   9741                                 DEST_TYPEf, (1 << field_len) - 1);
   9742 
   9743             soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &rep->ext_new_data2,
   9744                                 DEST_TYPEf, 2);
   9745 
   9746             field_len = soc_mem_field_length(unit, EXT_L2_ENTRY_2m,
   9747                                              DESTINATIONf);
   9748             soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &rep->ext_new_mask2,
   9749                                 DESTINATIONf, (1 << field_len) - 1);
   9750             soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &rep->ext_new_data2,
   9751                                 DESTINATIONf, rep->new_dest.vp);
   9752         } else if (rep->new_dest.trunk != -1) {
   9753             field_len = soc_mem_field_length(unit, EXT_L2_ENTRY_2m, DEST_TYPEf);
   9754             soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &rep->ext_new_mask2,
   9755                                 DEST_TYPEf, (1 << field_len) - 1);
   9756 
   9757             soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &rep->ext_new_data2,
   9758                                 DEST_TYPEf, 1);
   9759 
   9760             field_len = soc_mem_field_length(unit, EXT_L2_ENTRY_2m, TGIDf);
   9761             soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &rep->ext_new_mask2,
   9762                                 TGIDf, (1 << field_len) - 1);
   9763             soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &rep->ext_new_data2,
   9764                                 TGIDf, rep->new_dest.trunk);
   9765         } else if (rep->new_dest.port != -1 
   9766                    && rep->new_dest.module != -1) {
   9767             /* DEST_TYPEf == 0 */
   9768             field_len = soc_mem_field_length(unit, EXT_L2_ENTRY_2m, DEST_TYPEf);
   9769             soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &rep->ext_new_mask2,
   9770                                 DEST_TYPEf, (1 << field_len) - 1);
   9771 
   9772             field_len = soc_mem_field_length(unit, EXT_L2_ENTRY_2m,
   9773                                              MODULE_IDf);
   9774             soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &rep->ext_new_mask2,
   9775                                 MODULE_IDf, (1 << field_len) - 1);
   9776             soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &rep->ext_new_data2,
   9777                                 MODULE_IDf, rep->new_dest.module);
   9778 
   9779             field_len = soc_mem_field_length(unit, EXT_L2_ENTRY_2m,
   9780                                              PORT_NUMf);
   9781             soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &rep->ext_new_mask2,
   9782                                 PORT_NUMf, (1 << field_len) - 1);
   9783             soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &rep->ext_new_data2,
   9784                                 PORT_NUMf, rep->new_dest.port);
   9785         }
   9786 
   9787         if (rep->flags & BCM_L2_REPLACE_DES_HIT_CLEAR) {
   9788             soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &rep->ext_new_mask2,
   9789                                 HITDAf, 1);
   9790         }
   9791         if (rep->flags & BCM_L2_REPLACE_SRC_HIT_CLEAR) {
   9792             soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &rep->ext_new_mask2,
   9793                                 HITSAf, 1);
   9794         }
   9795     }
   9796     return BCM_E_NONE;
   9797 }
   9798 
   9799 STATIC int
   9800 _soc_tr3_l2_sync_mem_cache(int unit, _soc_tr3_l2_replace_t *rep_st)
   9801 {
   9802     uint8 *vmap, *vmap1;
   9803     soc_mem_t mem = L2_ENTRY_1m, ov_mem = L2_ENTRY_2m;
   9804     uint32 *cache, *entry, *match_data, *match_mask;
   9805     uint32 *new_data, *new_mask;
   9806     int index_max, idx, i;
   9807     int entry_dw = soc_mem_entry_words(unit, mem);
   9808     int entry_words = soc_mem_entry_words(unit, mem);
   9809     int copyno = SOC_MEM_BLOCK_ANY(unit, mem);
   9810     
   9811     /* First work on L2_ENTRY_1m */
   9812     cache = SOC_MEM_STATE(unit, mem).cache[copyno];
   9813     if (cache == NULL) {
   9814         return BCM_E_NONE;
   9815     }
   9816     vmap = SOC_MEM_STATE(unit, mem).vmap[copyno];
   9817     vmap1 = SOC_MEM_STATE(unit, ov_mem).vmap[copyno];
   9818     index_max = soc_mem_index_max(unit, mem);
   9819     for (idx = 0; idx <= index_max; idx++) {
   9820         if (!CACHE_VMAP_TST(vmap, idx)) {
   9821             continue;
   9822         }
   9823         entry = cache + (idx * entry_dw);
   9824         if (!soc_mem_field32_get(unit, mem, entry, VALIDf)) {
   9825             continue;
   9826         }
   9827         if (!soc_mem_field32_get(unit, mem, entry, STATIC_BITf)) {
   9828             continue;
   9829         }
   9830         match_data = (uint32 *)&rep_st->match_data1;
   9831         match_mask = (uint32 *)&rep_st->match_mask1;
   9832         for (i = 0; i < entry_words; i++) {
   9833             if ((entry[i] ^ match_data[i]) & match_mask[i]) {
   9834                 break;
   9835             }
   9836         }
   9837         if (i != entry_words) {
   9838             continue;
   9839         }
   9840         /* Match found, delete or replace entry */
   9841         LOG_VERBOSE(BSL_LS_SOC_COMMON,
   9842                     (BSL_META_U(unit,
   9843                                 "Match found in L2_1 bulk cache op: %d\n"), idx));
   9844         if (rep_st->flags & BCM_L2_REPLACE_DELETE) {
   9845             /* Delete op - invalidate the entry */
   9846             CACHE_VMAP_CLR(vmap, idx);
   9847             CACHE_VMAP_CLR(vmap1, idx/2);
   9848         } else {
   9849             /* Replace op - update entry */
   9850             new_data = (uint32 *)&rep_st->new_data1;
   9851             new_mask = (uint32 *)&rep_st->new_mask1;
   9852             for (i = 0; i < entry_words; i++) {
   9853                 entry[i] ^= (entry[i] ^ new_data[i]) & new_mask[i];
   9854             }
   9855         }
   9856     }
   9857     
   9858     /* Then work on L2_ENTRY_2m */
   9859     mem = L2_ENTRY_2m;
   9860     ov_mem = L2_ENTRY_1m;
   9861     entry_dw = soc_mem_entry_words(unit, mem);
   9862     entry_words = soc_mem_entry_words(unit, mem);
   9863     copyno = SOC_MEM_BLOCK_ANY(unit, mem);
   9864     cache = SOC_MEM_STATE(unit, mem).cache[copyno];
   9865     if (cache == NULL) {
   9866         return BCM_E_NONE;
   9867     }
   9868     vmap = SOC_MEM_STATE(unit, mem).vmap[copyno];
   9869     vmap1 = SOC_MEM_STATE(unit, ov_mem).vmap[copyno];
   9870     index_max = soc_mem_index_max(unit, mem);
   9871     for (idx = 0; idx <= index_max; idx++) {
   9872         if (!CACHE_VMAP_TST(vmap, idx)) {
   9873             continue;
   9874         }
   9875         entry = cache + (idx * entry_dw);
   9876         if (!soc_mem_field32_get(unit, mem, entry, VALID_0f)) {
   9877             continue;
   9878         }
   9879         if (!soc_mem_field32_get(unit, mem, entry, STATIC_BIT_0f)) {
   9880             continue;
   9881         }
   9882         match_data = (uint32 *)&rep_st->match_data2;
   9883         match_mask = (uint32 *)&rep_st->match_mask2;
   9884         for (i = 0; i < entry_words; i++) {
   9885             if ((entry[i] ^ match_data[i]) & match_mask[i]) {
   9886                 break;
   9887             }
   9888         }
   9889         if (i != entry_words) {
   9890             continue;
   9891         }
   9892         /* Match found, delete or replace entry */
   9893         LOG_VERBOSE(BSL_LS_SOC_COMMON,
   9894                     (BSL_META_U(unit,
   9895                                 "Match found in L2_2 bulk cache op: %d\n"), idx));
   9896         if (rep_st->flags & BCM_L2_REPLACE_DELETE) {
   9897             /* Delete op - invalidate the entry */
   9898             CACHE_VMAP_CLR(vmap, idx);
   9899             CACHE_VMAP_CLR(vmap1, idx/2);
   9900         } else {
   9901             /* Replace op - update entry */
   9902             new_data = (uint32 *)&rep_st->new_data2;
   9903             new_mask = (uint32 *)&rep_st->new_mask2;
   9904             for (i = 0; i < entry_words; i++) {
   9905                 entry[i] ^= (entry[i] ^ new_data[i]) & new_mask[i];
   9906             }
   9907         }
   9908     }
   9909 
   9910     return BCM_E_NONE;
   9911 }
   9912 
   9913 STATIC int
   9914 _is_soc_tr3_l2_mem_cache_enabled(int unit)
   9915 {
   9916     soc_mem_t mem = L2_ENTRY_1m;
   9917     uint32 *cache;
   9918     int copyno = SOC_MEM_BLOCK_ANY(unit, mem);
   9919     
   9920  
   9921     cache = SOC_MEM_STATE(unit, mem).cache[copyno];
   9922     if (cache == NULL) {
   9923         return FALSE;
   9924     }
   9925 
   9926     return TRUE;
   9927 }
   9928 
   9929 STATIC int
   9930 _bcm_tr3_l2_replace(int unit, uint32 flags, bcm_l2_addr_t *match_addr,
   9931                     bcm_module_t new_module, bcm_port_t new_port,
   9932                     bcm_trunk_t new_trunk)
   9933 {
   9934     _soc_tr3_l2_replace_t rep_st;
   9935     int                   rv = BCM_E_UNAVAIL;
   9936     int                   mode;
   9937 
   9938     sal_memset(&rep_st, 0, sizeof(_soc_tr3_l2_replace_t));
   9939 
   9940     /*Either of BCM_L2_REPLACE_DELETE or BCM_L2_REPLACE_AGE can bet set, but not both*/
   9941     if ((flags & BCM_L2_REPLACE_DELETE) && (flags & BCM_L2_REPLACE_AGE )) {
   9942         return BCM_E_PARAM;
   9943     }
   9944 
   9945     rep_st.flags = flags;
   9946 
   9947     /*Set the detination in rep_st*/
   9948     if (0 == (flags & (BCM_L2_REPLACE_DELETE|BCM_L2_REPLACE_AGE))) {
   9949         BCM_IF_ERROR_RETURN(_bcm_tr3_l2_replace_dest_setup
   9950                             (unit, new_module, new_port, new_trunk,
   9951                              flags & BCM_L2_REPLACE_NEW_TRUNK,
   9952                              &rep_st.new_dest));
   9953     }
   9954 
   9955     /*Set the match criteria in rep_st*/
   9956     if (flags & BCM_L2_REPLACE_MATCH_DEST) {
   9957         BCM_IF_ERROR_RETURN(_bcm_tr3_l2_replace_dest_setup
   9958                             (unit, match_addr->modid, match_addr->port,
   9959                              match_addr->tgid,
   9960                              match_addr->flags & BCM_L2_TRUNK_MEMBER,
   9961                              &rep_st.match_dest));
   9962         if (rep_st.match_dest.vp != -1) {
   9963             if (!((BCM_GPORT_IS_WLAN_PORT(match_addr->port))  ||
   9964                   (BCM_GPORT_IS_NIV_PORT(match_addr->port))   ||
   9965                   (BCM_GPORT_IS_TRILL_PORT(match_addr->port)) ||
   9966                   (BCM_GPORT_IS_VLAN_PORT(match_addr->port)))) {
   9967                     /* Note: For MPLS, MiM, L2GRE, VXLAN VFI types only */
   9968                     rep_st.key_type = SOC_MEM_KEY_L2_ENTRY_1_L2_VFI;
   9969                     rep_st.ext_key_type = SOC_MEM_KEY_EXT_L2_ENTRY_1_L2_VFI;
   9970             }
   9971         }
   9972     }
   9973 
   9974     if (flags & BCM_L2_REPLACE_MATCH_VLAN) {
   9975         rep_st.key_vfi = -1;
   9976         if (_BCM_VPN_VFI_IS_SET(match_addr->vid)) {
   9977             _BCM_VPN_GET(rep_st.key_vfi, _BCM_VPN_TYPE_VFI, match_addr->vid);
   9978         }
   9979         if (rep_st.key_vfi != -1) {
   9980             if (rep_st.key_vfi > soc_mem_index_max(unit, VFIm)) {
   9981                 return BCM_E_PARAM;
   9982             }
   9983             rep_st.key_type = SOC_MEM_KEY_L2_ENTRY_1_L2_VFI;
   9984             rep_st.ext_key_type = SOC_MEM_KEY_EXT_L2_ENTRY_1_L2_VFI;
   9985         } else {
   9986             VLAN_CHK_ID(unit, match_addr->vid);
   9987             rep_st.key_vlan = match_addr->vid;
   9988         }
   9989     }
   9990 
   9991     if (flags & BCM_L2_REPLACE_MATCH_MAC) {
   9992         sal_memcpy(&rep_st.key_mac, match_addr->mac, sizeof(bcm_mac_t));
   9993             /* When replace L2 by MAC, key type must be provided. */
   9994             /* Key type is 0 by default for L2 Bridge. */
   9995             /* Here add support for explicitly assigned VFI type */
   9996         if (flags & BCM_L2_REPLACE_VPN_TYPE) {
   9997              rep_st.key_type      = SOC_MEM_KEY_L2_ENTRY_1_L2_VFI;  /* VFI Type */
   9998              rep_st.ext_key_type  = SOC_MEM_KEY_EXT_L2_ENTRY_1_L2_VFI;  /*EXT VFI Type */
   9999         }
  10000     }
  10001 
  10002     if ((NULL == match_addr) && (flags & BCM_L2_REPLACE_VPN_TYPE)) {
  10003         rep_st.key_type = SOC_MEM_KEY_L2_ENTRY_1_L2_VFI;
  10004         rep_st.ext_key_type = SOC_MEM_KEY_EXT_L2_ENTRY_1_L2_VFI;
  10005     }
  10006 
  10007     BCM_IF_ERROR_RETURN(_bcm_tr3_l2_replace_data_mask_setup(unit, &rep_st));
  10008 
  10009     mode = SOC_CONTROL(unit)->l2x_mode;
  10010     /* Delete operation don't require freeze */
  10011     if ((0 == (flags & (BCM_L2_REPLACE_DELETE|BCM_L2_REPLACE_AGE))) ||
  10012         mode != L2MODE_FIFO || _is_soc_tr3_l2_mem_cache_enabled(unit)) {
  10013         BCM_IF_ERROR_RETURN(bcm_esw_l2_addr_freeze(unit));
  10014     }
  10015     rv = _bcm_tr3_l2_replace_by_hw(unit, &rep_st);
  10016 
  10017     if (SOC_SUCCESS(rv) && (rep_st.flags & BCM_L2_REPLACE_MATCH_STATIC)) {
  10018         /* update the entries in mem cache with the bulk op results */
  10019         rv = _soc_tr3_l2_sync_mem_cache(unit, &rep_st);
  10020     }
  10021 
  10022     if ((0 == (flags & (BCM_L2_REPLACE_DELETE|BCM_L2_REPLACE_AGE))) ||
  10023         mode != L2MODE_FIFO || _is_soc_tr3_l2_mem_cache_enabled(unit)) {
  10024         BCM_IF_ERROR_RETURN(bcm_esw_l2_addr_thaw(unit));
  10025     }
  10026 
  10027     return rv;
  10028 }
  10029 
  10030 /*
  10031  * Function:
  10032  *      bcm_tr3_l2_replace
  10033  * Purpose:
  10034  *      Replace L2 entries matching given criterions
  10035  * Parameters:
  10036  *      unit - (IN) Unit number.
  10037  *      flags - (IN) <UNDEF>
  10038  *      match_addr - (IN) <UNDEF>
  10039  *      new_module - (IN) <UNDEF>
  10040  *      new_port - (IN) <UNDEF>
  10041  *      new_trunk - (IN) <UNDEF>
  10042  * Returns:
  10043  *      BCM_E_xxx
  10044  * Notes:
  10045  */
  10046 int
  10047 bcm_tr3_l2_replace(int unit, uint32 flags, bcm_l2_addr_t *match_addr,
  10048                    bcm_module_t new_module, bcm_port_t new_port,
  10049                    bcm_trunk_t new_trunk)
  10050 {
  10051     BCM_TR3_L2_INIT(unit);
  10052 
  10053     if (!flags) {
  10054         return BCM_E_PARAM;
  10055     }
  10056     if ((flags & (BCM_L2_REPLACE_DELETE|BCM_L2_REPLACE_AGE)) &&
  10057         (flags & BCM_L2_REPLACE_NEW_TRUNK)) {
  10058         return BCM_E_PARAM;
  10059     }
  10060 
  10061     if ((flags & BCM_L2_REPLACE_DELETE) && (flags & BCM_L2_REPLACE_MATCH_MAC) &&
  10062         ((flags & BCM_L2_REPLACE_MATCH_UC) || (flags & BCM_L2_REPLACE_MATCH_MC))) {
  10063         return BCM_E_PARAM;
  10064     }
  10065 
  10066     /* matching L2 address allowed to be NULL together with */
  10067     /* BCM_L2_REPLACE_DELETE/BCM_L2_REPLACE_AGE flag indicating to delete/age all entries. */
  10068     if (NULL == match_addr) {
  10069         if (!(flags & (BCM_L2_REPLACE_DELETE|BCM_L2_REPLACE_AGE))) {
  10070             return BCM_E_PARAM;
  10071         }
  10072         flags &= ~(BCM_L2_REPLACE_MATCH_VLAN | BCM_L2_REPLACE_MATCH_MAC |
  10073                    BCM_L2_REPLACE_MATCH_DEST);
  10074 
  10075         if (flags & BCM_L2_REPLACE_VLAN_AND_VPN_TYPE) {
  10076             /* coverity[var_deref_model] */
  10077             BCM_IF_ERROR_RETURN
  10078                 (_bcm_tr3_l2_replace(unit, flags, match_addr, new_module,
  10079                               new_port, new_trunk));
  10080             flags ^= BCM_L2_REPLACE_VPN_TYPE;
  10081         }
  10082     }
  10083 
  10084     /*
  10085      * COVERITY
  10086      *
  10087      * Coverity complains that the NULL pointer match_addr is dereferenced
  10088      * in the below call.  But it is only dereferenced for one of the
  10089      * three flags that are explicitly removed above.
  10090      */ 
  10091     /*    coverity[var_deref_model : FALSE]    */
  10092     return _bcm_tr3_l2_replace(unit, flags, match_addr, new_module, new_port,
  10093                                new_trunk);
  10094 }
  10095 
  10096 /*
  10097  * Function:
  10098  *      _bcm_tr3_l2_addr_delete_mcast_by_hw
  10099  * Purpose:
  10100  *      Delete all L2 multicast entries by hardware bulk operation.
  10101  * Parameters:
  10102  *      unit - (IN) Unit number.
  10103  * Returns:
  10104  *      BCM_E_xxx
  10105  * Notes:
  10106  */
  10107 STATIC int
  10108 _bcm_tr3_l2_addr_delete_mcast_by_hw(int unit)
  10109 {
  10110     bcm_mac_t mac_mask;
  10111     uint32 rval;
  10112     l2_bulk_entry_t l2_bulk;
  10113     l2_entry_1_entry_t l2_entry_1;
  10114     l2_entry_2_entry_t l2_entry_2;
  10115     ext_l2_entry_1_entry_t ext_l2_entry_1;
  10116     ext_l2_entry_2_entry_t ext_l2_entry_2;
  10117     int field_len;
  10118 
  10119     sal_memset(&mac_mask, 0, sizeof(mac_mask));
  10120     mac_mask[0] = 1; /* bit 40 */
  10121 
  10122     /* ************************ */
  10123     /* First work on L2_ENTRY_1 */
  10124     /* ************************ */
  10125 
  10126     /* Set match mask */
  10127     sal_memset(&l2_entry_1, 0, sizeof(l2_entry_1));
  10128     soc_mem_field32_set(unit, L2_ENTRY_1m, &l2_entry_1, VALIDf, 1);
  10129     soc_mem_field32_set(unit, L2_ENTRY_1m, &l2_entry_1, WIDEf, 1);
  10130     field_len = soc_mem_field_length(unit, L2_ENTRY_1m, KEY_TYPEf);
  10131     soc_mem_field32_set(unit, L2_ENTRY_1m, &l2_entry_1, KEY_TYPEf,
  10132                         (1 << field_len) - 1);
  10133     soc_mem_mac_addr_set(unit, L2_ENTRY_1m, &l2_entry_1, L2__MAC_ADDRf,
  10134             mac_mask);
  10135 
  10136     sal_memset(&l2_bulk, 0, sizeof(l2_bulk));
  10137     sal_memcpy(&l2_bulk, &l2_entry_1, sizeof(l2_entry_1));
  10138     SOC_IF_ERROR_RETURN(WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 1, &l2_bulk));
  10139 
  10140     /* Set match data */
  10141     /* VALIDf is already set to 1 */
  10142     soc_mem_field32_set(unit, L2_ENTRY_1m, &l2_entry_1, WIDEf, 0);
  10143     soc_mem_field32_set(unit, L2_ENTRY_1m, &l2_entry_1, KEY_TYPEf, 
  10144                         SOC_MEM_KEY_L2_ENTRY_1_L2_BRIDGE);
  10145     /* Bit 40 of L2__MAC_ADDRf is already set to 1 */ 
  10146     sal_memcpy(&l2_bulk, &l2_entry_1, sizeof(l2_entry_1));
  10147     SOC_IF_ERROR_RETURN(WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 0, &l2_bulk));
  10148 
  10149     /* Set bulk control */
  10150     rval = 0;
  10151     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, L2_MOD_FIFO_RECORDf, 0);
  10152     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ACTIONf, 1);
  10153     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, BURST_ENTRIESf, 
  10154                       _SOC_TR3_L2_BULK_BURST_MAX);
  10155     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ENTRY_WIDTHf, 0);
  10156     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, NUM_ENTRIESf, 
  10157                       soc_mem_index_count(unit, L2_ENTRY_1m));
  10158     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, EXTERNAL_L2_ENTRYf, 0);
  10159     SOC_IF_ERROR_RETURN(WRITE_L2_BULK_CONTROLr(unit, rval));
  10160     SOC_IF_ERROR_RETURN(soc_tr3_l2_port_age(unit, L2_BULK_CONTROLr, INVALIDr));
  10161 
  10162     /* *********************** */
  10163     /* Then work on L2_ENTRY_2 */
  10164     /* *********************** */
  10165 
  10166     /* Set match mask */
  10167     sal_memset(&l2_entry_2, 0, sizeof(l2_entry_2));
  10168     soc_mem_field32_set(unit, L2_ENTRY_2m, &l2_entry_2, VALID_0f, 1);
  10169     soc_mem_field32_set(unit, L2_ENTRY_2m, &l2_entry_2, VALID_1f, 1);
  10170     soc_mem_field32_set(unit, L2_ENTRY_2m, &l2_entry_2, WIDE_0f, 1);
  10171     soc_mem_field32_set(unit, L2_ENTRY_2m, &l2_entry_2, WIDE_1f, 1);
  10172     field_len = soc_mem_field_length(unit, L2_ENTRY_2m, KEY_TYPE_0f);
  10173     soc_mem_field32_set(unit, L2_ENTRY_2m, &l2_entry_2, KEY_TYPE_0f,
  10174                         (1 << field_len) - 1);
  10175     soc_mem_field32_set(unit, L2_ENTRY_2m, &l2_entry_2, KEY_TYPE_1f,
  10176                         (1 << field_len) - 1);
  10177     soc_mem_mac_addr_set(unit, L2_ENTRY_2m, &l2_entry_2, L2__MAC_ADDRf,
  10178             mac_mask);
  10179 
  10180     sal_memset(&l2_bulk, 0, sizeof(l2_bulk));
  10181     sal_memcpy(&l2_bulk, &l2_entry_2, sizeof(l2_entry_2));
  10182     SOC_IF_ERROR_RETURN(WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 1, &l2_bulk));
  10183 
  10184     /* Set match data */
  10185     /* VALID_0f and VALID_1f are already set to 1 */
  10186     /* WIDE_0f and WIDE_1f are already set to 1 */
  10187     soc_mem_field32_set(unit, L2_ENTRY_2m, &l2_entry_2, KEY_TYPE_0f, 
  10188                             SOC_MEM_KEY_L2_ENTRY_2_L2_BRIDGE);
  10189     soc_mem_field32_set(unit, L2_ENTRY_2m, &l2_entry_2, KEY_TYPE_1f, 
  10190                             SOC_MEM_KEY_L2_ENTRY_2_L2_BRIDGE);
  10191     /* Bit 40 of L2__MAC_ADDRf is already set to 1 */ 
  10192     sal_memcpy(&l2_bulk, &l2_entry_2, sizeof(l2_entry_2));
  10193     SOC_IF_ERROR_RETURN(WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 0, &l2_bulk));
  10194 
  10195     /* Set bulk control */
  10196     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ENTRY_WIDTHf, 1);
  10197     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, NUM_ENTRIESf, 
  10198                       soc_mem_index_count(unit, L2_ENTRY_2m));
  10199     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, EXTERNAL_L2_ENTRYf, 0);
  10200     SOC_IF_ERROR_RETURN(WRITE_L2_BULK_CONTROLr(unit, rval));
  10201     SOC_IF_ERROR_RETURN(soc_tr3_l2_port_age(unit, L2_BULK_CONTROLr, INVALIDr));
  10202     
  10203     /* *************************** */
  10204     /* Next work on EXT_L2_ENTRY_1 */
  10205     /* *************************** */
  10206 
  10207     if (!soc_feature(unit, soc_feature_esm_support)) {
  10208         return BCM_E_NONE;
  10209     }
  10210 
  10211     /* Set match mask */
  10212     sal_memset(&ext_l2_entry_1, 0, sizeof(ext_l2_entry_1));
  10213     soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &ext_l2_entry_1, FREEf, 1); 
  10214     field_len = soc_mem_field_length(unit, EXT_L2_ENTRY_1m, KEY_TYPEf);
  10215     soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &ext_l2_entry_1, KEY_TYPEf, 
  10216                         (1 << field_len) - 1);
  10217     soc_mem_mac_addr_set(unit, EXT_L2_ENTRY_1m, &ext_l2_entry_1, MAC_ADDRf,
  10218             mac_mask);
  10219 
  10220     sal_memset(&l2_bulk, 0, sizeof(l2_bulk));
  10221     sal_memcpy(&l2_bulk, &ext_l2_entry_1, sizeof(ext_l2_entry_1));
  10222     SOC_IF_ERROR_RETURN(WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 1, &l2_bulk));
  10223 
  10224     /* Set match data */
  10225     soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &ext_l2_entry_1, FREEf, 0);
  10226     soc_mem_field32_set(unit, EXT_L2_ENTRY_1m, &ext_l2_entry_1, KEY_TYPEf, 
  10227                             SOC_MEM_KEY_EXT_L2_ENTRY_1_L2_BRIDGE);
  10228     /* Bit 40 of MAC_ADDRf is already set to 1 */ 
  10229     sal_memcpy(&l2_bulk, &ext_l2_entry_1, sizeof(ext_l2_entry_1));
  10230     SOC_IF_ERROR_RETURN(WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 0, &l2_bulk));
  10231 
  10232     /* Set bulk control */
  10233     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ENTRY_WIDTHf, 0);
  10234     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, NUM_ENTRIESf, 
  10235                       SOC_MEM_TR3_EXT_L2_MAX_ENTRIES);
  10236     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, EXTERNAL_L2_ENTRYf, 1);
  10237     SOC_IF_ERROR_RETURN(WRITE_L2_BULK_CONTROLr(unit, rval));
  10238     SOC_IF_ERROR_RETURN(soc_tr3_l2_port_age(unit, L2_BULK_CONTROLr, INVALIDr));
  10239     SOC_IF_ERROR_RETURN(WRITE_ETU_EXT_L2_BULK_INFOr(unit, 0));
  10240     /* Issue dummy op */
  10241     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ACTIONf, 0);
  10242     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ENTRY_WIDTHf, 0);
  10243     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, NUM_ENTRIESf, 1);
  10244     SOC_IF_ERROR_RETURN(WRITE_L2_BULK_CONTROLr(unit, rval));
  10245     SOC_IF_ERROR_RETURN(soc_tr3_l2_port_age(unit, L2_BULK_CONTROLr, INVALIDr));
  10246     SOC_IF_ERROR_RETURN(WRITE_ETU_EXT_L2_BULK_INFOr(unit, 0));
  10247     
  10248     /* ****************************** */
  10249     /* Finally work on EXT_L2_ENTRY_2 */
  10250     /* ****************************** */
  10251 
  10252     /* Set match mask */
  10253     sal_memset(&ext_l2_entry_2, 0, sizeof(ext_l2_entry_2));
  10254     soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &ext_l2_entry_2, FREEf, 1); 
  10255     field_len = soc_mem_field_length(unit, EXT_L2_ENTRY_2m, KEY_TYPEf);
  10256     soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &ext_l2_entry_2, KEY_TYPEf, 
  10257                         (1 << field_len) - 1);
  10258     soc_mem_mac_addr_set(unit, EXT_L2_ENTRY_2m, &ext_l2_entry_2, MAC_ADDRf,
  10259             mac_mask);
  10260 
  10261     sal_memset(&l2_bulk, 0, sizeof(l2_bulk));
  10262     sal_memcpy(&l2_bulk, &ext_l2_entry_2, sizeof(ext_l2_entry_2));
  10263     SOC_IF_ERROR_RETURN(WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 1, &l2_bulk));
  10264 
  10265     /* Set match data */
  10266     soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &ext_l2_entry_2, FREEf, 0);
  10267     soc_mem_field32_set(unit, EXT_L2_ENTRY_2m, &ext_l2_entry_2, KEY_TYPEf, 
  10268                             SOC_MEM_KEY_EXT_L2_ENTRY_2_L2_BRIDGE);
  10269     /* Bit 40 of MAC_ADDRf is already set to 1 */ 
  10270     sal_memcpy(&l2_bulk, &ext_l2_entry_2, sizeof(ext_l2_entry_2));
  10271     SOC_IF_ERROR_RETURN(WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 0, &l2_bulk));
  10272 
  10273     /* Set bulk control */
  10274     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ACTIONf, 1);
  10275     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ENTRY_WIDTHf, 1);
  10276     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, NUM_ENTRIESf, 
  10277                       SOC_MEM_TR3_EXT_L2_MAX_ENTRIES);
  10278     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, EXTERNAL_L2_ENTRYf, 1);
  10279     SOC_IF_ERROR_RETURN(WRITE_L2_BULK_CONTROLr(unit, rval));
  10280     SOC_IF_ERROR_RETURN(soc_tr3_l2_port_age(unit, L2_BULK_CONTROLr, INVALIDr));
  10281     SOC_IF_ERROR_RETURN(WRITE_ETU_EXT_L2_BULK_INFOr(unit, 0));
  10282     /* Issue dummy op */
  10283     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ACTIONf, 0);
  10284     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ENTRY_WIDTHf, 0);
  10285     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, NUM_ENTRIESf, 1);
  10286     SOC_IF_ERROR_RETURN(WRITE_L2_BULK_CONTROLr(unit, rval));
  10287     SOC_IF_ERROR_RETURN(soc_tr3_l2_port_age(unit, L2_BULK_CONTROLr, INVALIDr));
  10288     SOC_IF_ERROR_RETURN(WRITE_ETU_EXT_L2_BULK_INFOr(unit, 0));
  10289     
  10290     return BCM_E_NONE;
  10291 }
  10292 
  10293 /*
  10294  * Function:
  10295  *      _bcm_tr3_l2_addr_delete_mcast_by_sw
  10296  * Purpose:
  10297  *      Delete all L2 multicast entries by traversing all L2 tables.
  10298  * Parameters:
  10299  *      unit - (IN) Unit number.
  10300  * Returns:
  10301  *      BCM_E_xxx
  10302  * Notes:
  10303  */
  10304 STATIC int
  10305 _bcm_tr3_l2_addr_delete_mcast_by_sw(int unit)
  10306 {
  10307     int             rv = BCM_E_NONE;
  10308     int             buf_size, chunksize;
  10309     uint32          *l2_tbl_chnk;
  10310     soc_mem_t       mem;
  10311     int             chnk_idx, chnk_idx_max, mem_idx_max;
  10312     int             modified;
  10313     int             chnk_end, ent_idx;
  10314     uint32          *l2_entry;
  10315     int             key_type;
  10316     bcm_mac_t       mac_addr;
  10317 
  10318     chunksize = soc_property_get(unit, spn_L2DELETE_CHUNKS,
  10319             L2_MEM_CHUNKS_DEFAULT);
  10320     buf_size = 4 * SOC_MAX_MEM_FIELD_WORDS * chunksize;
  10321     l2_tbl_chnk = soc_cm_salloc(unit, buf_size, "l2 mcast delete");
  10322     if (NULL == l2_tbl_chnk) {
  10323         return BCM_E_MEMORY;
  10324     }
  10325 
  10326     /* First work on L2_ENTRY_1 */
  10327 
  10328     mem = L2_ENTRY_1m;
  10329     mem_idx_max = soc_mem_index_max(unit, mem);
  10330     for (chnk_idx = soc_mem_index_min(unit, mem); 
  10331          chnk_idx <= mem_idx_max; chnk_idx += chunksize) {
  10332 
  10333         sal_memset((void *)l2_tbl_chnk, 0, buf_size);
  10334         chnk_idx_max = ((chnk_idx + chunksize) <= mem_idx_max) ? 
  10335             (chnk_idx + chunksize - 1) : mem_idx_max;
  10336         rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY,
  10337                 chnk_idx, chnk_idx_max, l2_tbl_chnk);
  10338         if (BCM_FAILURE(rv)) {
  10339             break;
  10340         }
  10341 
  10342         modified = FALSE;
  10343         chnk_end = (chnk_idx_max - chnk_idx);
  10344         for (ent_idx = 0 ; ent_idx <= chnk_end; ent_idx++) {
  10345             l2_entry = soc_mem_table_idx_to_pointer(unit, mem, uint32 *, 
  10346                     l2_tbl_chnk, ent_idx);
  10347 
  10348             if (!soc_mem_field32_get(unit, mem, l2_entry, VALIDf)) {
  10349                 continue;
  10350             }
  10351 
  10352             key_type = soc_mem_field32_get(unit, mem, l2_entry,
  10353                     KEY_TYPEf);
  10354             if (SOC_MEM_KEY_L2_ENTRY_1_L2_BRIDGE != key_type) {
  10355                 continue;
  10356             }
  10357 
  10358             soc_mem_mac_addr_get(unit, mem, l2_entry, L2__MAC_ADDRf, mac_addr);
  10359             if (!BCM_MAC_IS_MCAST(mac_addr)) {
  10360                 continue;
  10361             }
  10362 
  10363             sal_memcpy(l2_entry, soc_mem_entry_null(unit, mem),
  10364                     sizeof(l2_entry_1_entry_t));
  10365             modified = TRUE;
  10366         }
  10367 
  10368         if (modified) {
  10369             rv = soc_mem_write_range(unit, mem, MEM_BLOCK_ALL,
  10370                     chnk_idx, chnk_idx_max, l2_tbl_chnk);
  10371             if (BCM_FAILURE(rv)) {
  10372                 break;
  10373             }
  10374         }
  10375     }
  10376 
  10377     if (BCM_FAILURE(rv)) {
  10378         soc_cm_sfree(unit, l2_tbl_chnk);
  10379         return rv;  
  10380     }
  10381 
  10382     /* Then work on L2_ENTRY_2 */
  10383 
  10384     mem = L2_ENTRY_2m;
  10385     mem_idx_max = soc_mem_index_max(unit, mem);
  10386     for (chnk_idx = soc_mem_index_min(unit, mem); 
  10387             chnk_idx <= mem_idx_max; 
  10388             chnk_idx += chunksize) {
  10389 
  10390         sal_memset((void *)l2_tbl_chnk, 0, buf_size);
  10391         chnk_idx_max = ((chnk_idx + chunksize) <= mem_idx_max) ? 
  10392             (chnk_idx + chunksize - 1) : mem_idx_max;
  10393         rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY,
  10394                 chnk_idx, chnk_idx_max, l2_tbl_chnk);
  10395         if (BCM_FAILURE(rv)) {
  10396             break;
  10397         }
  10398 
  10399         modified = FALSE;
  10400         chnk_end = (chnk_idx_max - chnk_idx);
  10401         for (ent_idx = 0 ; ent_idx <= chnk_end; ent_idx++) {
  10402             l2_entry = soc_mem_table_idx_to_pointer(unit, mem, uint32 *, 
  10403                     l2_tbl_chnk, ent_idx);
  10404 
  10405             if (!soc_mem_field32_get(unit, mem, l2_entry, VALID_0f)) {
  10406                 continue;
  10407             }
  10408             if (!soc_mem_field32_get(unit, mem, l2_entry, VALID_1f)) {
  10409                 continue;
  10410             }
  10411 
  10412             key_type = soc_mem_field32_get(unit, mem, l2_entry,
  10413                     KEY_TYPE_0f);
  10414             if (SOC_MEM_KEY_L2_ENTRY_2_L2_BRIDGE != key_type) {
  10415                 continue;
  10416             }
  10417 
  10418             soc_mem_mac_addr_get(unit, mem, l2_entry, L2__MAC_ADDRf, mac_addr);
  10419             if (!BCM_MAC_IS_MCAST(mac_addr)) {
  10420                 continue;
  10421             }
  10422 
  10423             sal_memcpy(l2_entry, soc_mem_entry_null(unit, mem),
  10424                     sizeof(l2_entry_2_entry_t));
  10425             modified = TRUE;
  10426         }
  10427 
  10428         if (modified) {
  10429             rv = soc_mem_write_range(unit, mem, MEM_BLOCK_ALL,
  10430                     chnk_idx, chnk_idx_max, l2_tbl_chnk);
  10431             if (BCM_FAILURE(rv)) {
  10432                 break;
  10433             }
  10434         }
  10435     }
  10436 
  10437     if (BCM_FAILURE(rv)) {
  10438         soc_cm_sfree(unit, l2_tbl_chnk);
  10439         return rv;  
  10440     }
  10441 
  10442     /* Next work on EXT_L2_ENTRY_1 */
  10443 
  10444     if (!soc_feature(unit, soc_feature_esm_support)) {
  10445         return BCM_E_NONE;
  10446     }
  10447 
  10448     mem = EXT_L2_ENTRY_1m;
  10449     mem_idx_max = soc_mem_index_max(unit, mem);
  10450     for (chnk_idx = soc_mem_index_min(unit, mem); 
  10451             chnk_idx <= mem_idx_max; 
  10452             chnk_idx += chunksize) {
  10453 
  10454         sal_memset((void *)l2_tbl_chnk, 0, buf_size);
  10455         chnk_idx_max = ((chnk_idx + chunksize) <= mem_idx_max) ? 
  10456             (chnk_idx + chunksize - 1) : mem_idx_max;
  10457         rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY,
  10458                 chnk_idx, chnk_idx_max, l2_tbl_chnk);
  10459         if (BCM_FAILURE(rv)) {
  10460             break;
  10461         }
  10462 
  10463         modified = FALSE;
  10464         chnk_end = (chnk_idx_max - chnk_idx);
  10465         for (ent_idx = 0 ; ent_idx <= chnk_end; ent_idx++) {
  10466             l2_entry = soc_mem_table_idx_to_pointer(unit, mem, uint32 *, 
  10467                     l2_tbl_chnk, ent_idx);
  10468 
  10469             if (soc_mem_field32_get(unit, mem, l2_entry, FREEf)) {
  10470                 continue;
  10471             }
  10472 
  10473             key_type = soc_mem_field32_get(unit, mem, l2_entry,
  10474                     KEY_TYPEf);
  10475             if (SOC_MEM_KEY_EXT_L2_ENTRY_1_L2_BRIDGE != key_type) {
  10476                 continue;
  10477             }
  10478 
  10479             soc_mem_mac_addr_get(unit, mem, l2_entry, MAC_ADDRf, mac_addr);
  10480             if (!BCM_MAC_IS_MCAST(mac_addr)) {
  10481                 continue;
  10482             }
  10483 
  10484             sal_memcpy(l2_entry, soc_mem_entry_null(unit, mem),
  10485                     sizeof(ext_l2_entry_1_entry_t));
  10486             modified = TRUE;
  10487         }
  10488 
  10489         if (modified) {
  10490             rv = soc_mem_write_range(unit, mem, MEM_BLOCK_ALL,
  10491                     chnk_idx, chnk_idx_max, l2_tbl_chnk);
  10492             if (BCM_FAILURE(rv)) {
  10493                 break;
  10494             }
  10495         }
  10496     }
  10497 
  10498     if (BCM_FAILURE(rv)) {
  10499         soc_cm_sfree(unit, l2_tbl_chnk);
  10500         return rv;  
  10501     }
  10502 
  10503     /* Finally work on EXT_L2_ENTRY_2 */
  10504 
  10505     mem = EXT_L2_ENTRY_2m;
  10506     mem_idx_max = soc_mem_index_max(unit, mem);
  10507     for (chnk_idx = soc_mem_index_min(unit, mem); 
  10508             chnk_idx <= mem_idx_max; 
  10509             chnk_idx += chunksize) {
  10510 
  10511         sal_memset((void *)l2_tbl_chnk, 0, buf_size);
  10512         chnk_idx_max = ((chnk_idx + chunksize) <= mem_idx_max) ? 
  10513             (chnk_idx + chunksize - 1) : mem_idx_max;
  10514         rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY,
  10515                 chnk_idx, chnk_idx_max, l2_tbl_chnk);
  10516         if (BCM_FAILURE(rv)) {
  10517             break;
  10518         }
  10519 
  10520         modified = FALSE;
  10521         chnk_end = (chnk_idx_max - chnk_idx);
  10522         for (ent_idx = 0 ; ent_idx <= chnk_end; ent_idx++) {
  10523             l2_entry = soc_mem_table_idx_to_pointer(unit, mem, uint32 *, 
  10524                     l2_tbl_chnk, ent_idx);
  10525 
  10526             if (soc_mem_field32_get(unit, mem, l2_entry, FREEf)) {
  10527                 continue;
  10528             }
  10529 
  10530             key_type = soc_mem_field32_get(unit, mem, l2_entry,
  10531                     KEY_TYPEf);
  10532             if (SOC_MEM_KEY_EXT_L2_ENTRY_2_L2_BRIDGE != key_type) {
  10533                 continue;
  10534             }
  10535 
  10536             soc_mem_mac_addr_get(unit, mem, l2_entry, MAC_ADDRf, mac_addr);
  10537             if (!BCM_MAC_IS_MCAST(mac_addr)) {
  10538                 continue;
  10539             }
  10540 
  10541             sal_memcpy(l2_entry, soc_mem_entry_null(unit, mem),
  10542                     sizeof(ext_l2_entry_2_entry_t));
  10543             modified = TRUE;
  10544         }
  10545 
  10546         if (modified) {
  10547             rv = soc_mem_write_range(unit, mem, MEM_BLOCK_ALL,
  10548                     chnk_idx, chnk_idx_max, l2_tbl_chnk);
  10549             if (BCM_FAILURE(rv)) {
  10550                 break;
  10551             }
  10552         }
  10553     }
  10554 
  10555     soc_cm_sfree(unit, l2_tbl_chnk);
  10556     return rv;        
  10557 }
  10558 
  10559 /*
  10560  * Function:
  10561  *      bcm_tr3_l2_addr_delete_mcast
  10562  * Purpose:
  10563  *      Delete all L2 multicast entries.
  10564  * Parameters:
  10565  *      unit - (IN) Unit number.
  10566  *      bulk - (IN) Hardware bulk delete indication.
  10567  * Returns:
  10568  *      BCM_E_xxx
  10569  * Notes:
  10570  */
  10571 int
  10572 bcm_tr3_l2_addr_delete_mcast(int unit, int bulk)
  10573 {
  10574     int rv, seconds, enabled;
  10575 
  10576     SOC_IF_ERROR_RETURN
  10577         (SOC_FUNCTIONS(unit)->soc_age_timer_get(unit, &seconds, &enabled));
  10578     if (enabled) {
  10579         SOC_IF_ERROR_RETURN(soc_tr3_l2_bulk_age_stop(unit));
  10580     }
  10581     _BCM_ALL_L2X_MEM_LOCK(unit);
  10582 
  10583     if (bulk) {
  10584         rv = _bcm_tr3_l2_addr_delete_mcast_by_hw(unit);
  10585     } else {
  10586         rv = _bcm_tr3_l2_addr_delete_mcast_by_sw(unit);
  10587     }
  10588 
  10589     _BCM_ALL_L2X_MEM_UNLOCK(unit);
  10590     if(enabled) {
  10591         SOC_IF_ERROR_RETURN(soc_tr3_l2_bulk_age_start(unit, seconds));
  10592     }
  10593     return rv;
  10594 }
  10595 
  10596 /*
  10597  * Function:
  10598  *      bcm_tr3_cross_connect_add
  10599  * Purpose:
  10600  *      Add a VLAN cross connect entry
  10601  * Parameters:
  10602  *      unit       - Device unit number
  10603  *      outer_vlan - Outer vlan ID
  10604  *      inner_vlan - Inner vlan ID
  10605  *      port_1     - First port in the cross-connect
  10606  *      port_2     - Second port in the cross-connect
  10607  * Returns:
  10608  *      BCM_E_NONE - Success.
  10609  *      BCM_E_XXX
  10610  */
  10611 int 
  10612 bcm_tr3_l2_cross_connect_add(int unit, bcm_vlan_t outer_vlan, 
  10613                             bcm_vlan_t inner_vlan, bcm_gport_t port_1, 
  10614                             bcm_gport_t port_2)
  10615 {
  10616     _bcm_tr3_l2_entries_t l2_entries, l2_entries_lookup;
  10617     int rv, gport_id;
  10618     bcm_port_t port_out;
  10619     bcm_module_t mod_out;
  10620     bcm_trunk_t trunk_id;
  10621 
  10622     BCM_TR3_L2_INIT(unit);
  10623 
  10624     sal_memset(&l2_entries, 0, sizeof (l2_entries));
  10625     l2_entries.entry_flags = _BCM_TR3_L2_SELECT_L2_ENTRY_1;
  10626     if ((outer_vlan < BCM_VLAN_DEFAULT) || (outer_vlan > BCM_VLAN_MAX)) {
  10627         return BCM_E_PARAM;
  10628     } else if (inner_vlan == BCM_VLAN_INVALID) {
  10629         /* Single cross-connect (use only outer_vid) */
  10630         soc_L2_ENTRY_1m_field32_set(unit, &(l2_entries.l2_entry_1), 
  10631                                     KEY_TYPEf, 
  10632                                     SOC_MEM_KEY_L2_ENTRY_1_VLAN_SINGLE_CROSS_CONNECT);
  10633     } else {
  10634         if ((inner_vlan < BCM_VLAN_DEFAULT) || (inner_vlan > BCM_VLAN_MAX)) {
  10635             return BCM_E_PARAM;
  10636         }
  10637         /* Double cross-connect (use both outer_vid and inner_vid) */
  10638         soc_L2_ENTRY_1m_field32_set(unit, &(l2_entries.l2_entry_1), 
  10639                                     KEY_TYPEf, 
  10640                                     SOC_MEM_KEY_L2_ENTRY_1_VLAN_DOUBLE_CROSS_CONNECT);
  10641         soc_L2_ENTRY_1m_field32_set(unit, &(l2_entries.l2_entry_1), VLAN__IVIDf, inner_vlan);
  10642     }
  10643     soc_L2_ENTRY_1m_field32_set(unit, &(l2_entries.l2_entry_1), STATIC_BITf, 1);
  10644     soc_L2_ENTRY_1m_field32_set(unit, &(l2_entries.l2_entry_1), VALIDf, 1);
  10645     soc_L2_ENTRY_1m_field32_set(unit, &(l2_entries.l2_entry_1), VLAN__OVIDf, outer_vlan);
  10646 
  10647     /* See if the entry already exists */
  10648     sal_memset(&l2_entries_lookup, 0, sizeof (l2_entries_lookup));
  10649     l2_entries.entry_flags = _BCM_TR3_L2_SELECT_L2_ENTRY_1;
  10650     rv = _bcm_tr3_l2_entries_lookup(unit, &l2_entries, &l2_entries_lookup);
  10651     if ((rv < 0) && (rv != BCM_E_NOT_FOUND)) {
  10652          return rv;
  10653     } 
  10654 
  10655     /* Resolve first port */
  10656     BCM_IF_ERROR_RETURN
  10657         (_bcm_esw_gport_resolve(unit, port_1, &mod_out, &port_out, &trunk_id,
  10658                                 &gport_id));
  10659     if (BCM_GPORT_IS_TRUNK(port_1)) {
  10660         soc_L2_ENTRY_1m_field32_set(unit, 
  10661                                     &(l2_entries.l2_entry_1), 
  10662                                     VLAN__DEST_TYPE_0f, 1);
  10663         soc_L2_ENTRY_1m_field32_set(unit, 
  10664                                     &(l2_entries.l2_entry_1), 
  10665                                     VLAN__TGID_0f, trunk_id);
  10666     } else if (BCM_GPORT_IS_SUBPORT_GROUP(port_1)
  10667                || BCM_GPORT_IS_VLAN_PORT(port_1)) {
  10668         soc_L2_ENTRY_1m_field32_set(unit, 
  10669                                     &(l2_entries.l2_entry_1), 
  10670                                     VLAN__DEST_TYPE_0f, 0x2);
  10671         soc_L2_ENTRY_1m_field32_set(unit, 
  10672                                     &(l2_entries.l2_entry_1), 
  10673                                     VLAN__DESTINATION_0f, gport_id);
  10674     } else {
  10675         if ((mod_out == -1) ||(port_out == -1)) {
  10676             return BCM_E_PORT;
  10677         }
  10678         soc_L2_ENTRY_1m_field32_set(unit, 
  10679                                     &(l2_entries.l2_entry_1), 
  10680                                     VLAN__DEST_TYPE_0f, 0);
  10681         soc_L2_ENTRY_1m_field32_set(unit, 
  10682                                     &(l2_entries.l2_entry_1), 
  10683                                     VLAN__MODULE_ID_0f, mod_out);
  10684         soc_L2_ENTRY_1m_field32_set(unit, 
  10685                                     &(l2_entries.l2_entry_1), 
  10686                                     VLAN__PORT_NUM_0f, port_out);
  10687     }
  10688 
  10689     /* Resolve second port */
  10690     BCM_IF_ERROR_RETURN 
  10691         (_bcm_esw_gport_resolve(unit, port_2, &mod_out, &port_out, &trunk_id,
  10692                                 &gport_id));
  10693     if (BCM_GPORT_IS_TRUNK(port_2)) {
  10694         soc_L2_ENTRY_1m_field32_set(unit, 
  10695                                     &(l2_entries.l2_entry_1), 
  10696                                     VLAN__DEST_TYPE_1f, 1);
  10697         soc_L2_ENTRY_1m_field32_set(unit, 
  10698                                     &(l2_entries.l2_entry_1), 
  10699                                     VLAN__TGID_1f, trunk_id);
  10700     } else if (BCM_GPORT_IS_SUBPORT_GROUP(port_2)
  10701                || BCM_GPORT_IS_VLAN_PORT(port_2)) {
  10702         soc_L2_ENTRY_1m_field32_set(unit, 
  10703                                     &(l2_entries.l2_entry_1), 
  10704                                     VLAN__DEST_TYPE_1f, 0x2);
  10705         soc_L2_ENTRY_1m_field32_set(unit, 
  10706                                     &(l2_entries.l2_entry_1), 
  10707                                     VLAN__DESTINATION_1f, gport_id);
  10708     } else {
  10709         if ((mod_out == -1) ||(port_out == -1)) {
  10710             return BCM_E_PORT;
  10711         }
  10712         soc_L2_ENTRY_1m_field32_set(unit, 
  10713                                     &(l2_entries.l2_entry_1), 
  10714                                     VLAN__DEST_TYPE_1f, 0);
  10715         soc_L2_ENTRY_1m_field32_set(unit, 
  10716                                     &(l2_entries.l2_entry_1), 
  10717                                     VLAN__MODULE_ID_1f, mod_out);
  10718         soc_L2_ENTRY_1m_field32_set(unit, 
  10719                                     &(l2_entries.l2_entry_1), 
  10720                                     VLAN__PORT_NUM_1f, port_out);
  10721     }
  10722 
  10723     rv = BCM_E_FULL;
  10724     rv = soc_mem_insert_return_old(unit, L2_ENTRY_1m, MEM_BLOCK_ANY, 
  10725                                        (void *)&(l2_entries.l2_entry_1),
  10726                                        (void *)&(l2_entries.l2_entry_1));
  10727     if (rv == BCM_E_FULL) {
  10728         rv = _bcm_tr3_l2_hash_dynamic_replace(unit, &l2_entries);
  10729     } 
  10730     if (BCM_SUCCESS(rv)) {
  10731         if (soc_feature(unit, soc_feature_ppa_bypass)) {
  10732             SOC_CONTROL(unit)->l2x_ppa_bypass = TRUE;
  10733         }
  10734     }
  10735 
  10736     return rv;
  10737 }
  10738 
  10739 /*
  10740  * Function:
  10741  *      bcm_tr3_l2_cross_connect_delete
  10742  * Purpose:
  10743  *      Delete a VLAN cross connect entry
  10744  * Parameters:
  10745  *      unit       - Device unit number
  10746  *      outer_vlan - Outer vlan ID
  10747  *      inner_vlan - Inner vlan ID
  10748  * Returns:
  10749  *      BCM_E_NONE - Success.
  10750  *      BCM_E_XXX
  10751  */
  10752 int 
  10753 bcm_tr3_l2_cross_connect_delete(int unit, bcm_vlan_t outer_vlan, 
  10754                                bcm_vlan_t inner_vlan)
  10755 {
  10756     _bcm_tr3_l2_entries_t l2_entries, l2_entries_lookup;
  10757     int mb_index;
  10758     int rv;
  10759 
  10760     BCM_TR3_L2_INIT(unit);
  10761 
  10762     sal_memset(&l2_entries, 0, sizeof (l2_entries));
  10763     l2_entries.entry_flags = _BCM_TR3_L2_SELECT_L2_ENTRY_1;
  10764     if ((outer_vlan < BCM_VLAN_DEFAULT) || (outer_vlan > BCM_VLAN_MAX)) {
  10765         return BCM_E_PARAM;
  10766     } else if (inner_vlan == BCM_VLAN_INVALID) {
  10767         /* Single cross-connect (use only outer_vid) */
  10768         soc_L2_ENTRY_1m_field32_set(unit, &(l2_entries.l2_entry_1), 
  10769                                     KEY_TYPEf, 
  10770                                     SOC_MEM_KEY_L2_ENTRY_1_VLAN_SINGLE_CROSS_CONNECT);
  10771     } else {
  10772         if ((inner_vlan < BCM_VLAN_DEFAULT) || (inner_vlan > BCM_VLAN_MAX)) {
  10773             return BCM_E_PARAM;
  10774         }
  10775         /* Double cross-connect (use both outer_vid and inner_vid) */
  10776         soc_L2_ENTRY_1m_field32_set(unit, &(l2_entries.l2_entry_1), 
  10777                                     KEY_TYPEf, 
  10778                                     SOC_MEM_KEY_L2_ENTRY_1_VLAN_DOUBLE_CROSS_CONNECT);
  10779 
  10780         soc_L2_ENTRY_1m_field32_set(unit, &(l2_entries.l2_entry_1), VLAN__IVIDf, inner_vlan);
  10781     }
  10782 
  10783     soc_L2_ENTRY_1m_field32_set(unit, &(l2_entries.l2_entry_1), STATIC_BITf, 1);
  10784     soc_L2_ENTRY_1m_field32_set(unit, &(l2_entries.l2_entry_1), VALIDf, 1);
  10785     soc_L2_ENTRY_1m_field32_set(unit, &(l2_entries.l2_entry_1), VLAN__OVIDf, outer_vlan);
  10786 
  10787     _BCM_ALL_L2X_MEM_LOCK(unit);
  10788     rv = _bcm_tr3_l2_entries_lookup(unit, (void *)&l2_entries,
  10789                                     (void *)&l2_entries_lookup);
  10790 
  10791     if (BCM_E_NONE != rv) {
  10792         _BCM_ALL_L2X_MEM_UNLOCK(unit);
  10793         return rv;
  10794     }
  10795 
  10796     if (!SOC_L2X_GROUP_ENABLE_GET(unit)) {
  10797         mb_index = _bcm_tr3_l2hw_entries_field32_get(unit, &l2_entries_lookup,
  10798                             _BCM_TR3_L2_MEMACC_MAC_BLOCK_INDEX);
  10799         _bcm_tr3_mac_block_delete(unit, mb_index);
  10800     }
  10801 
  10802     rv = _bcm_tr3_l2_entries_delete(unit, &l2_entries_lookup);
  10803     _BCM_ALL_L2X_MEM_UNLOCK(unit);
  10804 
  10805     return rv;
  10806 }
  10807 
  10808 /*
  10809  * Function:
  10810  *      bcm_tr3_l2_cross_connect_delete_all
  10811  * Purpose:
  10812  *      Delete all VLAN cross connect entries
  10813  * Parameters:
  10814  *      unit       - Device unit number
  10815  * Returns:
  10816  *      BCM_E_NONE - Success.
  10817  *      BCM_E_XXX
  10818  */
  10819 int
  10820 bcm_tr3_l2_cross_connect_delete_all(int unit)
  10821 {
  10822     int index_min, index_max, index, mem_max;
  10823     l2_entry_1_entry_t *l2_entry_1;
  10824     int rv = BCM_E_NONE;
  10825     int *buffer = NULL;
  10826     int mem_size, idx, chnk_end;
  10827     int chunksize, modified;
  10828     soc_mem_t mem = L2_ENTRY_1m;
  10829 
  10830     chunksize = soc_property_get(unit, spn_L2DELETE_CHUNKS,
  10831                                  L2_MEM_CHUNKS_DEFAULT);
  10832     index_min = soc_mem_index_min(unit, mem);
  10833     mem_max = soc_mem_index_max(unit, mem);
  10834     mem_size =  chunksize * sizeof(l2_entry_only_entry_t);
  10835     
  10836     buffer = soc_cm_salloc(unit, mem_size, "L2_ENTRY_1_delete");
  10837     if (NULL == buffer) {
  10838         return SOC_E_MEMORY;
  10839     }
  10840 
  10841     soc_mem_lock(unit, L2_ENTRY_1m);
  10842     for (idx = index_min; idx <= mem_max; idx += chunksize) {
  10843         index_max = idx + chunksize - 1;
  10844         if ( index_max > mem_max) {
  10845             index_max = mem_max;
  10846         }
  10847         if ((rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ALL,
  10848                                      idx, index_max, buffer)) < 0 ) {
  10849             soc_cm_sfree(unit, buffer);
  10850             soc_mem_unlock(unit, L2_ENTRY_1m);
  10851             return rv;
  10852         }
  10853         modified = 0;
  10854         chnk_end = index_max - idx;
  10855         for (index = 0; index <= chnk_end; index++) {
  10856             l2_entry_1 =
  10857                 soc_mem_table_idx_to_pointer(unit, mem, l2_entry_1_entry_t *,
  10858                                              buffer, index);
  10859             if (soc_L2_ENTRY_1m_field32_get(unit, l2_entry_1, VALIDf) &&
  10860                 ((soc_L2_ENTRY_1m_field32_get(unit, l2_entry_1, KEY_TYPEf) ==
  10861                                   SOC_MEM_KEY_L2_ENTRY_1_VLAN_SINGLE_CROSS_CONNECT) ||
  10862                  (soc_L2_ENTRY_1m_field32_get(unit, l2_entry_1, KEY_TYPEf) ==
  10863                                   SOC_MEM_KEY_L2_ENTRY_1_VLAN_DOUBLE_CROSS_CONNECT))) {
  10864                 sal_memcpy(l2_entry_1, soc_mem_entry_null(unit, mem),
  10865                            sizeof(l2_entry_1_entry_t));
  10866                 modified = 1;
  10867             }
  10868         }
  10869         if (modified) {
  10870             if ((rv = soc_mem_write_range(unit, mem, MEM_BLOCK_ALL,
  10871                                          idx, index_max, buffer)) < 0) {
  10872                 soc_cm_sfree(unit, buffer);
  10873                 soc_mem_unlock(unit, L2_ENTRY_1m);
  10874                 return rv;
  10875             }
  10876         }
  10877     }
  10878 
  10879     if (SOC_CONTROL(unit)->arlShadow != NULL) {
  10880         sal_mutex_take(SOC_CONTROL(unit)->arlShadowMutex, sal_mutex_FOREVER);
  10881         (void) shr_avl_delete_all(SOC_CONTROL(unit)->arlShadow);
  10882         sal_mutex_give(SOC_CONTROL(unit)->arlShadowMutex);
  10883     }
  10884     soc_cm_sfree(unit, buffer);
  10885     soc_mem_unlock(unit, L2_ENTRY_1m);
  10886     
  10887     return rv;
  10888 }
  10889 
  10890 /*
  10891  * Function:
  10892  *      bcm_tr3_l2_cross_connect_traverse
  10893  * Purpose:
  10894  *      Walks through the valid cross connect entries and calls
  10895  *      the user supplied callback function for each entry.
  10896  * Parameters:
  10897  *      unit       - (IN) bcm device.
  10898  *      trav_fn    - (IN) Callback function.
  10899  *      user_data  - (IN) User data to be passed to callback function.
  10900  * Returns:
  10901  *      BCM_E_NONE - Success.
  10902  *      BCM_E_XXX
  10903  */
  10904 int
  10905 bcm_tr3_l2_cross_connect_traverse(int unit,
  10906                                  bcm_vlan_cross_connect_traverse_cb cb,
  10907                                  void *user_data)
  10908 {
  10909     int index_min, index_max, index, mem_max;
  10910     l2_entry_1_entry_t *l2_entry_1;
  10911     int rv = SOC_E_NONE;
  10912     int *buffer = NULL;
  10913     int mem_size, idx, chunksize, chnk_end;
  10914     bcm_gport_t port_1 = BCM_GPORT_INVALID, port_2 = BCM_GPORT_INVALID;
  10915     bcm_vlan_t outer_vlan, inner_vlan;
  10916     bcm_port_t port_in, port_out;
  10917     bcm_module_t mod_in, mod_out;
  10918     soc_mem_t mem = L2_ENTRY_1m;
  10919 
  10920     chunksize = soc_property_get(unit, spn_L2DELETE_CHUNKS,
  10921                                  L2_MEM_CHUNKS_DEFAULT);
  10922     index_min = soc_mem_index_min(unit, mem);
  10923     mem_max = soc_mem_index_max(unit, mem);
  10924     mem_size =  chunksize * sizeof(l2_entry_1_entry_t);
  10925     
  10926     buffer = soc_cm_salloc(unit, mem_size, "cross connect traverse");
  10927     if (NULL == buffer) {
  10928         return SOC_E_MEMORY;
  10929     }
  10930     sal_memset((void *)buffer, 0, mem_size);
  10931     
  10932     soc_mem_lock(unit, L2_ENTRY_1m);
  10933     for (idx = index_min; idx <= mem_max; idx += chunksize) {
  10934         index_max = idx + chunksize - 1;
  10935         if ( index_max > mem_max) {
  10936             index_max = mem_max;
  10937         }
  10938         if ((rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ALL,
  10939                                      idx, index_max, buffer)) < 0 ) {
  10940             soc_cm_sfree(unit, buffer);
  10941             soc_mem_unlock(unit, L2_ENTRY_1m);
  10942             return rv;
  10943         }
  10944         chnk_end = index_max - idx;
  10945         for (index = 0; index <= chnk_end ; index++) {
  10946             l2_entry_1 = 
  10947                 soc_mem_table_idx_to_pointer(unit, mem,
  10948                                              l2_entry_1_entry_t *, buffer, index);
  10949             if (soc_L2_ENTRY_1m_field32_get(unit, l2_entry_1, VALIDf)) {
  10950                 if (soc_L2_ENTRY_1m_field32_get(unit, l2_entry_1, KEY_TYPEf) ==
  10951                                      SOC_MEM_KEY_L2_ENTRY_1_VLAN_DOUBLE_CROSS_CONNECT) {
  10952                     /* Double cross-connect entry */
  10953                     inner_vlan = soc_L2_ENTRY_1m_field32_get(unit, l2_entry_1, VLAN__IVIDf);
  10954                 } else if (soc_L2_ENTRY_1m_field32_get(unit, l2_entry_1, KEY_TYPEf) ==
  10955                                      SOC_MEM_KEY_L2_ENTRY_1_VLAN_SINGLE_CROSS_CONNECT) {
  10956                     /* Single cross-connect entry */
  10957                     inner_vlan = BCM_VLAN_INVALID;
  10958                 } else {
  10959                     /* Not a cross-connect entry, ignore */
  10960                     continue;
  10961                 }
  10962                 outer_vlan = soc_L2_ENTRY_1m_field32_get(unit, l2_entry_1, VLAN__OVIDf);
  10963 
  10964                 /* Get first port params */
  10965                 if (soc_L2_ENTRY_1m_field32_get(unit, l2_entry_1, VLAN__DEST_TYPE_0f) == 2) {
  10966                     int vpg;
  10967                     vpg = soc_L2_ENTRY_1m_field32_get(unit, l2_entry_1, VLAN__DESTINATION_0f);
  10968                     BCM_GPORT_SUBPORT_GROUP_SET(port_1, vpg);
  10969                 } else if (soc_L2_ENTRY_1m_field32_get(unit, l2_entry_1, VLAN__DEST_TYPE_0f) == 1) {
  10970                     BCM_GPORT_TRUNK_SET(port_1, 
  10971                         soc_L2_ENTRY_1m_field32_get(unit, l2_entry_1, VLAN__TGID_0f));
  10972                 } else if (soc_L2_ENTRY_1m_field32_get(unit, l2_entry_1, VLAN__DEST_TYPE_0f) == 0) {
  10973                     port_in = soc_L2_ENTRY_1m_field32_get(unit, l2_entry_1, VLAN__PORT_NUM_0f);
  10974                     mod_in = soc_L2_ENTRY_1m_field32_get(unit, l2_entry_1, VLAN__MODULE_ID_0f);
  10975                     rv = _bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET,
  10976                                                  mod_in, port_in, &mod_out, &port_out);
  10977                     if (BCM_FAILURE(rv)) {
  10978                         soc_cm_sfree(unit, buffer);
  10979                         soc_mem_unlock(unit, L2_ENTRY_1m);
  10980                         return rv;
  10981                     }
  10982                     BCM_GPORT_MODPORT_SET(port_1, mod_out, port_out);
  10983                 }
  10984 
  10985                 /* Get second port params */
  10986                 if (soc_L2_ENTRY_1m_field32_get(unit, l2_entry_1, VLAN__DEST_TYPE_1f) == 2) {
  10987                     int vpg;
  10988                     vpg = soc_L2_ENTRY_1m_field32_get(unit, l2_entry_1, VLAN__DESTINATION_1f);
  10989                     BCM_GPORT_SUBPORT_GROUP_SET(port_2, vpg);
  10990                 } else if (soc_L2_ENTRY_1m_field32_get(unit, l2_entry_1, VLAN__DEST_TYPE_1f) == 1) {
  10991                     BCM_GPORT_TRUNK_SET(port_2, soc_L2_ENTRY_1m_field32_get(unit, l2_entry_1, VLAN__TGID_1f));
  10992                 } else if (soc_L2_ENTRY_1m_field32_get(unit, l2_entry_1, VLAN__DEST_TYPE_1f) == 0) {
  10993                     port_in = soc_L2_ENTRY_1m_field32_get(unit, l2_entry_1, VLAN__PORT_NUM_1f);
  10994                     mod_in = soc_L2_ENTRY_1m_field32_get(unit, l2_entry_1, VLAN__MODULE_ID_1f);
  10995                     BCM_IF_ERROR_RETURN
  10996                         (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET,
  10997                                                 mod_in, port_in, &mod_out, &port_out));
  10998                     BCM_GPORT_MODPORT_SET(port_2, mod_out, port_out);
  10999                 }
  11000 
  11001                 /* Call application call-back */
  11002                 rv = cb(unit, outer_vlan, inner_vlan, port_1, port_2, user_data);
  11003 #ifdef BCM_CB_ABORT_ON_ERR
  11004                 if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) {
  11005                     soc_cm_sfree(unit, buffer);
  11006                     soc_mem_unlock(unit, L2_ENTRY_1m);
  11007                     return rv;
  11008                 }
  11009 #endif
  11010             }
  11011         }
  11012     }
  11013     soc_cm_sfree(unit, buffer);
  11014     soc_mem_unlock(unit, L2_ENTRY_1m);
  11015 
  11016     return BCM_E_NONE;
  11017 }
  11018 
  11019 int
  11020 bcm_tr3_failover_ring_config_set(int unit, bcm_failover_ring_t *failover_ring)
  11021 {    
  11022     int match_type = -1, i, rv, gport_id;
  11023     uint32 map_size, rval;
  11024     SHR_BITDCL *vlan_map = NULL, *vpn_map = NULL;
  11025     bcm_module_t mod_out;
  11026     bcm_port_t port_out;
  11027     bcm_trunk_t trunk_id;
  11028     /*
  11029     * match_type = -1 means forced_flooding/learn_disabling based on physical 
  11030     *              port or VP
  11031     * match_type = 0 means forced_flooding/learn_disabling based on VLAN or 
  11032     *              port + VLAN
  11033     * match_type = 1 means forced_flooding/learn_disabling based on VPN or 
  11034     *              VP + VPN
  11035     */
  11036     if (!failover_ring) {
  11037         return BCM_E_PARAM;
  11038     }
  11039     /*
  11040     * If only one of the ports(port0 or port1) are valid, then we have to write 
  11041     * that port value into both FLOOD_LEARN_MATCH_PORT_Ar and 
  11042     * FLOOD_LEARN_MATCH_PORT_Br due to hardware behavior.
  11043     */
  11044     if ((failover_ring->port0 != BCM_GPORT_INVALID) && 
  11045         (failover_ring->port1 == BCM_GPORT_INVALID)) {
  11046         failover_ring->port1 = failover_ring->port0;   
  11047     }
  11048     if ((failover_ring->port1 != BCM_GPORT_INVALID) && 
  11049         (failover_ring->port0 == BCM_GPORT_INVALID)) {
  11050         failover_ring->port0 = failover_ring->port1;   
  11051     }
  11052     /* Configure h/w tables and memory */
  11053     if (failover_ring->flags & 
  11054         (BCM_FAILOVER_LOOKUP_DISABLE | BCM_FAILOVER_LEARN_DISABLE)) {
  11055         if(failover_ring->port0 != BCM_GPORT_INVALID) {
  11056            BCM_IF_ERROR_RETURN
  11057                (_bcm_esw_gport_resolve(unit, failover_ring->port0, &mod_out, 
  11058                                        &port_out, &trunk_id, &gport_id));
  11059            SOC_IF_ERROR_RETURN(READ_FLOOD_LEARN_MATCH_PORT_Ar(unit, &rval));
  11060            if (-1 != gport_id) {
  11061                soc_reg_field_set(unit, FLOOD_LEARN_MATCH_PORT_Ar, &rval,
  11062                                  DESTINATIONf, gport_id);
  11063                soc_reg_field_set(unit, FLOOD_LEARN_MATCH_PORT_Ar, &rval,
  11064                                  DEST_TYPEf, 2);
  11065            } else if (BCM_TRUNK_INVALID != trunk_id) {
  11066                soc_reg_field_set(unit, FLOOD_LEARN_MATCH_PORT_Ar, &rval, 
  11067                                  DESTINATIONf, trunk_id);
  11068                soc_reg_field_set(unit, FLOOD_LEARN_MATCH_PORT_Ar, &rval,
  11069                                  DEST_TYPEf, 1);
  11070            } else if (!(-1 == port_out || -1 == mod_out)) {
  11071                soc_reg_field_set(unit, FLOOD_LEARN_MATCH_PORT_Ar, &rval, 
  11072                                  PORT_NUMf, port_out);
  11073                soc_reg_field_set(unit, FLOOD_LEARN_MATCH_PORT_Ar, &rval, 
  11074                                  MODULE_IDf, mod_out);
  11075                soc_reg_field_set(unit, FLOOD_LEARN_MATCH_PORT_Ar, &rval,
  11076                                  DEST_TYPEf, 0);
  11077            } 
  11078            SOC_IF_ERROR_RETURN(WRITE_FLOOD_LEARN_MATCH_PORT_Ar(unit, rval));
  11079         }
  11080         if (failover_ring->port1 != BCM_GPORT_INVALID) {
  11081             BCM_IF_ERROR_RETURN
  11082                 (_bcm_esw_gport_resolve(unit, failover_ring->port1, &mod_out, 
  11083                                         &port_out, &trunk_id, &gport_id));
  11084             SOC_IF_ERROR_RETURN(READ_FLOOD_LEARN_MATCH_PORT_Br(unit, &rval));
  11085             if (-1 != gport_id) {
  11086                 soc_reg_field_set(unit, FLOOD_LEARN_MATCH_PORT_Br, &rval,
  11087                                   DESTINATIONf, gport_id);
  11088                 soc_reg_field_set(unit, FLOOD_LEARN_MATCH_PORT_Br, &rval,
  11089                                   DEST_TYPEf, 2);
  11090             } else if (BCM_TRUNK_INVALID != trunk_id) {
  11091                 soc_reg_field_set(unit, FLOOD_LEARN_MATCH_PORT_Br, &rval, 
  11092                                   DESTINATIONf, trunk_id);
  11093                 soc_reg_field_set(unit, FLOOD_LEARN_MATCH_PORT_Br, &rval,
  11094                                   DEST_TYPEf, 1);
  11095             } else if (!(-1 == port_out || -1 == mod_out)) {
  11096                 soc_reg_field_set(unit, FLOOD_LEARN_MATCH_PORT_Br, &rval, 
  11097                                   PORT_NUMf, port_out);
  11098                 soc_reg_field_set(unit, FLOOD_LEARN_MATCH_PORT_Br, &rval, 
  11099                                   MODULE_IDf, mod_out);
  11100                 soc_reg_field_set(unit, FLOOD_LEARN_MATCH_PORT_Br, &rval,
  11101                                   DEST_TYPEf, 0);
  11102             }
  11103             SOC_IF_ERROR_RETURN(WRITE_FLOOD_LEARN_MATCH_PORT_Br(unit, rval));
  11104         }
  11105         /* 
  11106         * KT2 and TR3 have hardware restriction that forced_flooding / 
  11107         * learn_disabling can be set only for all VPNs and not for set  
  11108         * of VPNs. Hence, vpn_vector will be used only for future  
  11109         * devices which overcome this hardware restriction.
  11110         */
  11111         if (failover_ring->flags & BCM_FAILOVER_VPN_TYPE) {
  11112 #if defined(BCM_KATANA2_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
  11113             if (SOC_IS_KATANA2(unit) || SOC_IS_TRIUMPH3(unit)) {
  11114                 match_type = 1;
  11115             } else
  11116 #endif	
  11117             {
  11118                 map_size = SHR_BITALLOCSIZE(BCM_VPN_MAX+1);
  11119                 vpn_map = soc_cm_salloc(unit, map_size, "Failover ring vpn map");
  11120                 if (NULL == vpn_map) {
  11121                     return (SOC_E_MEMORY);
  11122                 }
  11123                 sal_memset(vpn_map, 0, map_size);
  11124                 for (i = BCM_VPN_MIN; i < BCM_VPN_MAX; i++) {
  11125                      if (BCM_VPN_VEC_GET(failover_ring->vpn_vector, i)) {
  11126                          SHR_BITSET(vpn_map, i);
  11127                          match_type = 1;  
  11128                      }
  11129                 }
  11130                 if (match_type == 1) {
  11131                     if ((rv = soc_mem_write_range(unit, FLOOD_LEARN_MATCH_VLANS_PORT_Am,
  11132                                                   MEM_BLOCK_ALL, 0, soc_mem_index_max( 
  11133                                                   unit, FLOOD_LEARN_MATCH_VLANS_PORT_Am), 
  11134                                                   vpn_map)) < 0) {
  11135                         soc_cm_sfree(unit, vpn_map);
  11136                         return rv;
  11137                     }
  11138                     if ((rv = soc_mem_write_range(unit, FLOOD_LEARN_MATCH_VLANS_PORT_Bm,
  11139                                                   MEM_BLOCK_ALL, 0, soc_mem_index_max( 
  11140                                                   unit, FLOOD_LEARN_MATCH_VLANS_PORT_Bm), 
  11141                                                   vpn_map)) < 0) {
  11142                         soc_cm_sfree(unit, vpn_map);
  11143                         return rv;
  11144                     }
  11145                 }    
  11146                 soc_cm_sfree(unit, vpn_map);
  11147             }
  11148             if (match_type == 1) {
  11149                 /*
  11150                 * As we are writing vlan_vector/vpn_vector into both 
  11151                 * FLOOD_LEARN_MATCH_VLANS_PORT_Am and 
  11152                 * FLOOD_LEARN_MATCH_VLANS_PORT_Bm, we have to set key_type into 
  11153                 * both FLOOD_LEARN_KEY_TYPE_PORT_Ar and 
  11154                 * FLOOD_LEARN_KEY_TYPE_PORT_Br. 
  11155                 */
  11156                 SOC_IF_ERROR_RETURN(READ_FLOOD_LEARN_KEY_TYPE_PORT_Ar(unit, 
  11157                                     &rval));
  11158 #ifdef BCM_KATANA2_SUPPORT        
  11159                 if (SOC_IS_KATANA2(unit)) {
  11160                     soc_reg_field_set(unit, FLOOD_LEARN_KEY_TYPE_PORT_Ar, &rval, 
  11161                                       KEY_TYPEf, KT2_L2_HASH_KEY_TYPE_VFI);
  11162                 }
  11163 #endif  
  11164                 if (SOC_IS_TRIUMPH3(unit)) {
  11165                     soc_reg_field_set(unit, FLOOD_LEARN_KEY_TYPE_PORT_Ar, &rval, 
  11166                                       KEY_TYPEf, SOC_MEM_KEY_L2_ENTRY_1_L2_VFI);
  11167                 }
  11168                 SOC_IF_ERROR_RETURN(WRITE_FLOOD_LEARN_KEY_TYPE_PORT_Ar(unit, 
  11169                                     rval));
  11170            
  11171                 SOC_IF_ERROR_RETURN(READ_FLOOD_LEARN_KEY_TYPE_PORT_Br(unit, 
  11172                                     &rval));
  11173 #ifdef BCM_KATANA2_SUPPORT        
  11174                 if (SOC_IS_KATANA2(unit)) {
  11175                     soc_reg_field_set(unit, FLOOD_LEARN_KEY_TYPE_PORT_Br, &rval,
  11176                                       KEY_TYPEf, KT2_L2_HASH_KEY_TYPE_VFI);
  11177                 }
  11178 #endif
  11179                 if (SOC_IS_TRIUMPH3(unit)) {
  11180                     soc_reg_field_set(unit, FLOOD_LEARN_KEY_TYPE_PORT_Br, &rval,
  11181                                       KEY_TYPEf, SOC_MEM_KEY_L2_ENTRY_1_L2_VFI);
  11182                 }
  11183                 SOC_IF_ERROR_RETURN(WRITE_FLOOD_LEARN_KEY_TYPE_PORT_Br(unit, 
  11184                                     rval));
  11185             }
  11186         } else {
  11187             map_size = SHR_BITALLOCSIZE(BCM_VLAN_MAX+1);
  11188             vlan_map = soc_cm_salloc(unit, map_size, "Failover ring vlan map");
  11189             if (NULL == vlan_map) {
  11190                 return (SOC_E_MEMORY);
  11191             }
  11192             sal_memset(vlan_map, 0, map_size);
  11193             for (i = BCM_VLAN_MIN; i < BCM_VLAN_MAX; i++) {
  11194                  if (BCM_VLAN_VEC_GET(failover_ring->vlan_vector, i)) {
  11195                      SHR_BITSET(vlan_map, i);
  11196                      match_type = 0;
  11197                  }
  11198             }
  11199             if ((rv = soc_mem_write_range(unit, FLOOD_LEARN_MATCH_VLANS_PORT_Am,
  11200                                           MEM_BLOCK_ALL, 0, soc_mem_index_max( 
  11201                                           unit, FLOOD_LEARN_MATCH_VLANS_PORT_Am), 
  11202                                           vlan_map)) < 0) {
  11203                  soc_cm_sfree(unit, vlan_map);
  11204                  return rv;
  11205             }
  11206             if ((rv = soc_mem_write_range(unit, FLOOD_LEARN_MATCH_VLANS_PORT_Bm,
  11207                                           MEM_BLOCK_ALL, 0, soc_mem_index_max(
  11208                                           unit, FLOOD_LEARN_MATCH_VLANS_PORT_Bm), 
  11209                                           vlan_map)) < 0) {
  11210                  soc_cm_sfree(unit, vlan_map);
  11211                  return rv;
  11212             }
  11213             soc_cm_sfree(unit, vlan_map);
  11214         }
  11215 
  11216         SOC_IF_ERROR_RETURN(READ_FLOOD_LEARN_CONTROLr(unit, &rval));
  11217         if (failover_ring->flags & BCM_FAILOVER_LOOKUP_DISABLE) {
  11218             soc_reg_field_set(unit, FLOOD_LEARN_CONTROLr, &rval, FLOOD_FORCEf, 
  11219                               1);
  11220         }
  11221         if (failover_ring->flags & BCM_FAILOVER_LEARN_DISABLE) {
  11222             soc_reg_field_set(unit, FLOOD_LEARN_CONTROLr, &rval, LEARN_DISABLEf, 
  11223                               1);
  11224         }
  11225         if (match_type != -1) {
  11226             soc_reg_field_set(unit, FLOOD_LEARN_CONTROLr, &rval, 
  11227                               MATCH_KEY_TYPE_PORT_Af, 1);
  11228             soc_reg_field_set(unit, FLOOD_LEARN_CONTROLr, &rval, 
  11229                               MATCH_KEY_TYPE_PORT_Bf, 1);
  11230         }
  11231         if ((failover_ring->port0 != BCM_GPORT_INVALID) || 
  11232             (failover_ring->port1 != BCM_GPORT_INVALID)) {
  11233             /*
  11234             * In KT2 and TR3, as we do forced_flooding/learn_disabling for all 
  11235             * VPNs irrespective of VPs, we would not set MATCH_PORT_Af and 
  11236             * MATCH_PORT_Bf if match_type is 1.
  11237             */
  11238 #if defined(BCM_KATANA2_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
  11239             if ((SOC_IS_KATANA2(unit) || SOC_IS_TRIUMPH3(unit)) && 
  11240                 (match_type != 1))
  11241 #endif				
  11242             {             
  11243                  soc_reg_field_set(unit, FLOOD_LEARN_CONTROLr, &rval, 
  11244                                    MATCH_PORT_Af, 1);
  11245                  soc_reg_field_set(unit, FLOOD_LEARN_CONTROLr, &rval, 
  11246                                    MATCH_PORT_Bf, 1);
  11247             }
  11248         }
  11249         if (match_type != -1) {
  11250             /*
  11251             * In KT2 and TR3, as we would not consider vpn_vector due to
  11252             * hardware restriction, we won't set MATCH_VLANS_PORT_Af and
  11253             * MATCH_VLANS_PORT_Bf if match_type is 1.
  11254             */
  11255 #if defined(BCM_KATANA2_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
  11256             if ((SOC_IS_KATANA2(unit) || SOC_IS_TRIUMPH3(unit)) && 
  11257                 (match_type != 1))  
  11258 #endif		
  11259             {	
  11260                  soc_reg_field_set(unit, FLOOD_LEARN_CONTROLr, &rval, 
  11261                                    MATCH_VLANS_PORT_Af, 1);
  11262                  soc_reg_field_set(unit, FLOOD_LEARN_CONTROLr, &rval, 
  11263                                    MATCH_VLANS_PORT_Bf, 1);
  11264             }
  11265         }			
  11266         SOC_IF_ERROR_RETURN(WRITE_FLOOD_LEARN_CONTROLr(unit, rval));
  11267     } else if (failover_ring->flags & BCM_FAILOVER_CLEAR) {
  11268         rval = 0;
  11269         SOC_IF_ERROR_RETURN(WRITE_FLOOD_LEARN_CONTROLr(unit, rval));
  11270         SOC_IF_ERROR_RETURN(WRITE_FLOOD_LEARN_MATCH_PORT_Ar(unit, rval));
  11271         SOC_IF_ERROR_RETURN(WRITE_FLOOD_LEARN_MATCH_PORT_Br(unit, rval));
  11272         SOC_IF_ERROR_RETURN(WRITE_FLOOD_LEARN_KEY_TYPE_PORT_Ar(unit, rval));
  11273         SOC_IF_ERROR_RETURN(WRITE_FLOOD_LEARN_KEY_TYPE_PORT_Br(unit, rval));
  11274         SOC_IF_ERROR_RETURN
  11275             (soc_mem_clear(unit, FLOOD_LEARN_MATCH_VLANS_PORT_Am, COPYNO_ALL, 
  11276                            0));
  11277         SOC_IF_ERROR_RETURN
  11278             (soc_mem_clear(unit, FLOOD_LEARN_MATCH_VLANS_PORT_Bm, COPYNO_ALL, 
  11279                            0));
  11280     }
  11281     return BCM_E_NONE;
  11282 }
  11283 
  11284 int
  11285 bcm_tr3_failover_ring_config_get(int unit, bcm_failover_ring_t *failover_ring)
  11286 {
  11287     int i, rv, vp, dest_type = -1;
  11288     uint8 no_clear = 0;
  11289     _bcm_gport_dest_t dest;
  11290     SHR_BITDCL *vlan_map = NULL, *vpn_map = NULL;
  11291     uint32 map_size, rval, is_vfi;
  11292 
  11293     COMPILER_REFERENCE(vp);
  11294  
  11295     if (!failover_ring) {
  11296         return BCM_E_PARAM;
  11297     }
  11298     bcm_failover_ring_t_init(failover_ring);
  11299     SOC_IF_ERROR_RETURN(READ_FLOOD_LEARN_KEY_TYPE_PORT_Ar(unit, &rval));
  11300     is_vfi = soc_reg_field_get(unit, FLOOD_LEARN_KEY_TYPE_PORT_Ar, rval, 
  11301                                KEY_TYPEf);
  11302     /*
  11303     * is_vfi = zero means KEY_TYPE is VLAN
  11304     * is_vfi = non-zero value means KEY_TYPE is VFI
  11305     */
  11306     if (is_vfi) {
  11307 #if defined(BCM_KATANA2_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
  11308         if (!(SOC_IS_KATANA2(unit) || SOC_IS_TRIUMPH3(unit)))
  11309 #endif
  11310         {
  11311             /* 
  11312             * KT2 && TR3 have hardware restriction that forced_flooding / 
  11313             * learn_disabling can be set only for all VPNs and not for set of 
  11314             * VPNs. Hence, vpn_vector will be used only for future devices  
  11315             * which overcome this hardware restriction.
  11316             */
  11317             /* Construct vpn vector */
  11318             map_size = SHR_BITALLOCSIZE(BCM_VPN_MAX+1);
  11319             vpn_map = soc_cm_salloc(unit, map_size, "Failover ring vpn map");
  11320             if (NULL == vpn_map) {
  11321                 return (SOC_E_MEMORY);
  11322             }
  11323             sal_memset(vpn_map, 0, map_size);
  11324             if ((rv = soc_mem_read_range(unit, FLOOD_LEARN_MATCH_VLANS_PORT_Am,
  11325                                          MEM_BLOCK_ALL, 0, soc_mem_index_max(unit, 
  11326                                          FLOOD_LEARN_MATCH_VLANS_PORT_Am), 
  11327                                          vpn_map)) < 0) {
  11328                 soc_cm_sfree(unit, vpn_map);
  11329                 return rv;
  11330             }
  11331             for (i = BCM_VPN_MIN; i < BCM_VPN_MAX; i++) {
  11332                 if (BCM_VPN_VEC_GET(vpn_map, i)) {
  11333                     SHR_BITSET(failover_ring->vpn_vector, i);
  11334                 }
  11335             }
  11336             soc_cm_sfree(unit, vpn_map);
  11337         }	
  11338     } else {
  11339         /* Construct vlan vector */
  11340         map_size = SHR_BITALLOCSIZE(BCM_VLAN_MAX+1);
  11341         vlan_map = soc_cm_salloc(unit, map_size, "Failover ring vlan map");
  11342         if (NULL == vlan_map) {
  11343             return (SOC_E_MEMORY);
  11344         }
  11345         sal_memset(vlan_map, 0, map_size);
  11346         if ((rv = soc_mem_read_range(unit, FLOOD_LEARN_MATCH_VLANS_PORT_Am,
  11347                                      MEM_BLOCK_ALL, 0, soc_mem_index_max(unit, 
  11348                                      FLOOD_LEARN_MATCH_VLANS_PORT_Am), 
  11349                                      vlan_map)) < 0) {
  11350             soc_cm_sfree(unit, vlan_map);
  11351             return rv;
  11352         }
  11353         for (i = BCM_VLAN_MIN; i < BCM_VLAN_MAX; i++) {
  11354             if (BCM_VLAN_VEC_GET(vlan_map, i)) {
  11355                 SHR_BITSET(failover_ring->vlan_vector, i);
  11356             }
  11357         }
  11358         soc_cm_sfree(unit, vlan_map);
  11359     }
  11360     /* Construct flags */    
  11361     SOC_IF_ERROR_RETURN(READ_FLOOD_LEARN_CONTROLr(unit, &rval));
  11362     if (soc_reg_field_get(unit, FLOOD_LEARN_CONTROLr, rval, FLOOD_FORCEf)) {
  11363         failover_ring->flags |= BCM_FAILOVER_LOOKUP_DISABLE;
  11364         no_clear++;
  11365     }
  11366     if (soc_reg_field_get(unit, FLOOD_LEARN_CONTROLr, rval, LEARN_DISABLEf)) {
  11367         failover_ring->flags |= BCM_FAILOVER_LEARN_DISABLE;
  11368         no_clear++;
  11369     }
  11370     if (is_vfi) {
  11371         failover_ring->flags |= BCM_FAILOVER_VPN_TYPE;
  11372     }
  11373     if (no_clear == 0) {
  11374         failover_ring->flags |= BCM_FAILOVER_CLEAR;
  11375     }
  11376     /* Construct gport info */
  11377     _bcm_gport_dest_t_init(&dest);
  11378     SOC_IF_ERROR_RETURN(READ_FLOOD_LEARN_MATCH_PORT_Ar(unit, &rval));
  11379     if (rval) {
  11380         dest_type = soc_reg_field_get(unit, FLOOD_LEARN_MATCH_PORT_Ar, rval, 
  11381                                       DEST_TYPEf);
  11382     } else {
  11383         dest_type = -1;
  11384     }    
  11385     if (dest_type == 0) {
  11386         dest.port = soc_reg_field_get(unit, FLOOD_LEARN_MATCH_PORT_Ar, rval, 
  11387                                       PORT_NUMf);
  11388         dest.modid = soc_reg_field_get(unit, FLOOD_LEARN_MATCH_PORT_Ar, rval, 
  11389                                        MODULE_IDf);
  11390         dest.gport_type = _SHR_GPORT_TYPE_MODPORT;
  11391     } else if (dest_type == 1) {
  11392         dest.tgid = soc_reg_field_get(unit, FLOOD_LEARN_MATCH_PORT_Ar, rval, 
  11393                                       DESTINATIONf);
  11394         dest.gport_type = _SHR_GPORT_TYPE_TRUNK;
  11395     } else if (dest_type == 2) {
  11396         vp = soc_reg_field_get(unit, FLOOD_LEARN_MATCH_PORT_Ar, rval, 
  11397                                DESTINATIONf);
  11398 #if defined(INCLUDE_L3)    
  11399         if ((rv = _bcm_vp_gport_dest_fill(unit, vp, &dest)) < 0) {
  11400             return rv;
  11401         }  
  11402 #endif        
  11403     }
  11404     if (dest_type != -1) {
  11405         BCM_IF_ERROR_RETURN
  11406             (_bcm_esw_gport_construct(unit, &dest, &failover_ring->port0));
  11407     }        
  11408     _bcm_gport_dest_t_init(&dest);
  11409     SOC_IF_ERROR_RETURN(READ_FLOOD_LEARN_MATCH_PORT_Br(unit, &rval));
  11410     if (rval) {
  11411         dest_type = soc_reg_field_get(unit, FLOOD_LEARN_MATCH_PORT_Br, rval, 
  11412                                       DEST_TYPEf);
  11413     } else {
  11414         dest_type = -1;
  11415     }    
  11416     if (dest_type == 0) {
  11417         dest.port = soc_reg_field_get(unit, FLOOD_LEARN_MATCH_PORT_Br, rval, 
  11418                                       PORT_NUMf);
  11419         dest.modid = soc_reg_field_get(unit, FLOOD_LEARN_MATCH_PORT_Br, rval, 
  11420                                        MODULE_IDf);
  11421         dest.gport_type = _SHR_GPORT_TYPE_MODPORT;
  11422     } else if (dest_type == 1) {
  11423         dest.tgid = soc_reg_field_get(unit, FLOOD_LEARN_MATCH_PORT_Br, rval, 
  11424                                       DESTINATIONf);
  11425         dest.gport_type = _SHR_GPORT_TYPE_TRUNK;
  11426     } else if (dest_type == 2) {
  11427         vp = soc_reg_field_get(unit, FLOOD_LEARN_MATCH_PORT_Br, rval, 
  11428                                DESTINATIONf);
  11429 #if defined(INCLUDE_L3)    
  11430         if ((rv = _bcm_vp_gport_dest_fill(unit, vp, &dest)) < 0) {
  11431             return rv;
  11432         } 
  11433 #endif
  11434     }
  11435     if (dest_type != -1) {
  11436         BCM_IF_ERROR_RETURN
  11437             (_bcm_esw_gport_construct(unit, &dest, &failover_ring->port1));
  11438     }        
  11439     return BCM_E_NONE;
  11440 }
  11441 
  11442 int
  11443 _bcm_tr3_l2_ring_replace(int unit, bcm_l2_ring_t *l2_ring)
  11444 {
  11445     int match_type = -1, rv = BCM_E_NONE, gport_id, vp_type = 0;
  11446     uint32 map_size, i, rval;
  11447     SHR_BITDCL *vlan_map = NULL, *vpn_map = NULL;
  11448     bcm_module_t mod_out;
  11449     bcm_port_t port_out;
  11450     bcm_trunk_t trunk_id;
  11451     uint32 r_flags = 0;
  11452 
  11453     /*
  11454     * match_type = -1 means flushing based on physical port or VP
  11455     * match_type = 0 means flushing based on VLAN or port + VLAN
  11456     * match_type = 1 means flushing based on VPN or VP + VPN
  11457     */
  11458     if (!l2_ring) {
  11459         return BCM_E_PARAM;
  11460     }
  11461 
  11462     /* Flag Validation Check */
  11463     if (((l2_ring->flags & BCM_L2_REPLACE_DYNAMIC) &&
  11464          (l2_ring->flags & BCM_L2_REPLACE_MATCH_STATIC)) ||
  11465         ((l2_ring->flags & BCM_L2_REPLACE_MATCH_UC) &&
  11466          (l2_ring->flags & BCM_L2_REPLACE_MATCH_MC))) {
  11467         return BCM_E_PARAM;
  11468     }
  11469 
  11470     /*
  11471     * If only one of the ports(port0 or port1) are valid, then we have to write 
  11472     * that port value into both L2_BULK_MATCH_PORT_Ar and 
  11473     * L2_BULK_MATCH_PORT_Br due to hardware behavior.
  11474     */
  11475     if ((l2_ring->port0 != BCM_GPORT_INVALID) && 
  11476         (l2_ring->port1 == BCM_GPORT_INVALID)) {
  11477         l2_ring->port1 = l2_ring->port0;   
  11478     }
  11479     if ((l2_ring->port1 != BCM_GPORT_INVALID) && 
  11480         (l2_ring->port0 == BCM_GPORT_INVALID)) {
  11481         l2_ring->port0 = l2_ring->port1;   
  11482     }
  11483 
  11484     /* Get replace flags */
  11485     r_flags = l2_ring->flags;
  11486 
  11487     /* Configure h/w tables and memory */
  11488     if (l2_ring->flags & BCM_L2_REPLACE_PROTECTION_RING) {
  11489         if (l2_ring->port0 != BCM_GPORT_INVALID) {
  11490             BCM_IF_ERROR_RETURN
  11491                 (_bcm_esw_gport_resolve(unit, l2_ring->port0, &mod_out, 
  11492                                         &port_out, &trunk_id, &gport_id));
  11493             SOC_IF_ERROR_RETURN(READ_L2_BULK_MATCH_PORT_Ar(unit, &rval));
  11494             if (-1 != gport_id) {
  11495                 vp_type = 1;
  11496                 soc_reg_field_set(unit, L2_BULK_MATCH_PORT_Ar, &rval,
  11497                                   DESTINATIONf, gport_id);
  11498                 soc_reg_field_set(unit, L2_BULK_MATCH_PORT_Ar, &rval,
  11499                                   DEST_TYPEf, 2);
  11500             } else if (BCM_TRUNK_INVALID != trunk_id) {
  11501                 soc_reg_field_set(unit, L2_BULK_MATCH_PORT_Ar, &rval, 
  11502                                   DESTINATIONf, trunk_id);
  11503                 soc_reg_field_set(unit, L2_BULK_MATCH_PORT_Ar, &rval,
  11504                                   DEST_TYPEf, 1);
  11505             } else if (!(-1 == port_out || -1 == mod_out)) {
  11506                 soc_reg_field_set(unit, L2_BULK_MATCH_PORT_Ar, &rval, 
  11507                                   PORT_NUMf, port_out);
  11508                 soc_reg_field_set(unit, L2_BULK_MATCH_PORT_Ar, &rval, 
  11509                                   MODULE_IDf, mod_out);
  11510                 soc_reg_field_set(unit, L2_BULK_MATCH_PORT_Ar, &rval,
  11511                                   DEST_TYPEf, 0);
  11512             } 
  11513             SOC_IF_ERROR_RETURN(WRITE_L2_BULK_MATCH_PORT_Ar(unit, rval));
  11514         }
  11515         if (l2_ring->port1 != BCM_GPORT_INVALID) {
  11516             BCM_IF_ERROR_RETURN
  11517                 (_bcm_esw_gport_resolve(unit, l2_ring->port1, &mod_out, 
  11518                                         &port_out, &trunk_id, &gport_id));
  11519             SOC_IF_ERROR_RETURN(READ_L2_BULK_MATCH_PORT_Br(unit, &rval));
  11520             if (-1 != gport_id) {
  11521                 vp_type = 1;
  11522                 soc_reg_field_set(unit, L2_BULK_MATCH_PORT_Br, &rval,
  11523                                   DESTINATIONf, gport_id);
  11524                 soc_reg_field_set(unit, L2_BULK_MATCH_PORT_Br, &rval,
  11525                                   DEST_TYPEf, 2);
  11526             } else if (BCM_TRUNK_INVALID != trunk_id) {
  11527                 soc_reg_field_set(unit, L2_BULK_MATCH_PORT_Br, &rval, 
  11528                                   DESTINATIONf, trunk_id);
  11529                 soc_reg_field_set(unit, L2_BULK_MATCH_PORT_Br, &rval,
  11530                                   DEST_TYPEf, 1);
  11531             } else if (!(-1 == port_out || -1 == mod_out)) {
  11532                 soc_reg_field_set(unit, L2_BULK_MATCH_PORT_Br, &rval, 
  11533                                   PORT_NUMf, port_out);
  11534                 soc_reg_field_set(unit, L2_BULK_MATCH_PORT_Br, &rval, 
  11535                                   MODULE_IDf, mod_out);
  11536                 soc_reg_field_set(unit, L2_BULK_MATCH_PORT_Br, &rval,
  11537                                   DEST_TYPEf, 0);
  11538             }
  11539             SOC_IF_ERROR_RETURN(WRITE_L2_BULK_MATCH_PORT_Br(unit, rval));
  11540         }
  11541         if (l2_ring->flags & BCM_L2_REPLACE_VPN_TYPE) {
  11542             map_size = SHR_BITALLOCSIZE(BCM_VPN_MAX+1);
  11543             vpn_map = soc_cm_salloc(unit, map_size, "Failover ring vpn map");
  11544             if (NULL == vpn_map) {
  11545                 return (SOC_E_MEMORY);
  11546             }
  11547             sal_memset(vpn_map, 0, map_size);
  11548             for (i = BCM_VPN_MIN; i < BCM_VPN_MAX; i++) {
  11549                  if (BCM_VPN_VEC_GET(l2_ring->vpn_vector, i)) {
  11550                      SHR_BITSET(vpn_map, i);
  11551                      match_type = 1;  
  11552                  }
  11553             }
  11554             if (match_type == 1) {
  11555                 if ((rv = soc_mem_write_range(unit, L2_BULK_MATCH_VLANS_PORT_Am,
  11556                                               MEM_BLOCK_ALL, 0, soc_mem_index_max( 
  11557                                               unit, L2_BULK_MATCH_VLANS_PORT_Am), 
  11558                                               vpn_map)) < 0) {
  11559                     soc_cm_sfree(unit, vpn_map);
  11560                     return rv;
  11561                 }
  11562                 if ((rv = soc_mem_write_range(unit, L2_BULK_MATCH_VLANS_PORT_Bm,
  11563                                               MEM_BLOCK_ALL, 0, soc_mem_index_max( 
  11564                                               unit, L2_BULK_MATCH_VLANS_PORT_Bm), 
  11565                                               vpn_map)) < 0) {
  11566                     soc_cm_sfree(unit, vpn_map);
  11567                     return rv;
  11568                 }
  11569                 /*
  11570                 * As we are writing vlan_vector/vpn_vector into both 
  11571                 * L2_BULK_MATCH_VLANS_PORT_Am and 
  11572                 * L2_BULK_MATCH_VLANS_PORT_Bm, we have to set key_type into 
  11573                 * both L2_BULK_KEY_TYPE_PORT_Ar and 
  11574                 * L2_BULK_KEY_TYPE_PORT_Br. 
  11575                 */
  11576                 SOC_IF_ERROR_RETURN(READ_L2_BULK_KEY_TYPE_PORT_Ar(unit, &rval));
  11577 #ifdef BCM_KATANA2_SUPPORT        
  11578                 if (SOC_IS_KATANA2(unit)) {
  11579                     soc_reg_field_set(unit, L2_BULK_KEY_TYPE_PORT_Ar, &rval, 
  11580                                       KEY_TYPEf, KT2_L2_HASH_KEY_TYPE_VFI);
  11581                 }
  11582 #endif  
  11583                 if (SOC_IS_TRIUMPH3(unit)) {
  11584                     soc_reg_field_set(unit, L2_BULK_KEY_TYPE_PORT_Ar, &rval, 
  11585                                       KEY_TYPEf, SOC_MEM_KEY_L2_ENTRY_1_L2_VFI);
  11586                 }
  11587                 SOC_IF_ERROR_RETURN(WRITE_L2_BULK_KEY_TYPE_PORT_Ar(unit, rval));
  11588            
  11589                 SOC_IF_ERROR_RETURN(READ_L2_BULK_KEY_TYPE_PORT_Br(unit, &rval));
  11590 #ifdef BCM_KATANA2_SUPPORT        
  11591                 if (SOC_IS_KATANA2(unit)) {
  11592                     soc_reg_field_set(unit, L2_BULK_KEY_TYPE_PORT_Br, &rval,
  11593                                       KEY_TYPEf, KT2_L2_HASH_KEY_TYPE_VFI);
  11594                 }
  11595 #endif
  11596                 if (SOC_IS_TRIUMPH3(unit)) {
  11597                     soc_reg_field_set(unit, L2_BULK_KEY_TYPE_PORT_Br, &rval,
  11598                                       KEY_TYPEf, SOC_MEM_KEY_L2_ENTRY_1_L2_VFI);
  11599                 }
  11600                 SOC_IF_ERROR_RETURN(WRITE_L2_BULK_KEY_TYPE_PORT_Br(unit, rval));
  11601             }
  11602             soc_cm_sfree(unit, vpn_map);
  11603         } else {
  11604             vp_type = 0;
  11605             map_size = SHR_BITALLOCSIZE(BCM_VLAN_MAX+1);
  11606             vlan_map = soc_cm_salloc(unit, map_size, "Failover ring vlan map");
  11607             if (NULL == vlan_map) {
  11608                 return (SOC_E_MEMORY);
  11609             }
  11610             sal_memset(vlan_map, 0, map_size);
  11611             for (i = BCM_VLAN_MIN; i < BCM_VLAN_MAX; i++) {
  11612                  if (BCM_VLAN_VEC_GET(l2_ring->vlan_vector, i)) {
  11613                      SHR_BITSET(vlan_map, i);
  11614                      match_type = 0;
  11615                  }
  11616             }
  11617             if ((rv = soc_mem_write_range(unit, L2_BULK_MATCH_VLANS_PORT_Am,
  11618                                           MEM_BLOCK_ALL, 0, soc_mem_index_max( 
  11619                                           unit, L2_BULK_MATCH_VLANS_PORT_Am), 
  11620                                           vlan_map)) < 0) {
  11621                  soc_cm_sfree(unit, vlan_map);
  11622                  return rv;
  11623             }
  11624             if ((rv = soc_mem_write_range(unit, L2_BULK_MATCH_VLANS_PORT_Bm,
  11625                                           MEM_BLOCK_ALL, 0, soc_mem_index_max(
  11626                                           unit, L2_BULK_MATCH_VLANS_PORT_Bm), 
  11627                                           vlan_map)) < 0) {
  11628                  soc_cm_sfree(unit, vlan_map);
  11629                  return rv;
  11630             }
  11631 
  11632             /*
  11633             * As we are writing vlan_vector/vpn_vector into both
  11634             * L2_BULK_MATCH_VLANS_PORT_Am and
  11635             * L2_BULK_MATCH_VLANS_PORT_Bm, we have to set key_type into
  11636             * both L2_BULK_KEY_TYPE_PORT_Ar and
  11637             * L2_BULK_KEY_TYPE_PORT_Br.
  11638             */
  11639             SOC_IF_ERROR_RETURN(READ_L2_BULK_KEY_TYPE_PORT_Ar(unit, &rval));
  11640 #ifdef BCM_KATANA2_SUPPORT
  11641             if (SOC_IS_KATANA2(unit)) {
  11642                 soc_reg_field_set(unit, L2_BULK_KEY_TYPE_PORT_Ar, &rval,
  11643                                   KEY_TYPEf, KT2_L2_HASH_KEY_TYPE_BRIDGE);
  11644             }
  11645 #endif
  11646             if (SOC_IS_TRIUMPH3(unit)) {
  11647                 soc_reg_field_set(unit, L2_BULK_KEY_TYPE_PORT_Ar, &rval,
  11648                                   KEY_TYPEf, SOC_MEM_KEY_L2_ENTRY_1_L2_BRIDGE);
  11649             }
  11650             SOC_IF_ERROR_RETURN(WRITE_L2_BULK_KEY_TYPE_PORT_Ar(unit, rval));
  11651 
  11652             SOC_IF_ERROR_RETURN(READ_L2_BULK_KEY_TYPE_PORT_Br(unit, &rval));
  11653 #ifdef BCM_KATANA2_SUPPORT
  11654             if (SOC_IS_KATANA2(unit)) {
  11655                 soc_reg_field_set(unit, L2_BULK_KEY_TYPE_PORT_Br, &rval,
  11656                                   KEY_TYPEf, KT2_L2_HASH_KEY_TYPE_BRIDGE);
  11657             }
  11658 #endif
  11659             if (SOC_IS_TRIUMPH3(unit)) {
  11660                 soc_reg_field_set(unit, L2_BULK_KEY_TYPE_PORT_Br, &rval,
  11661                                   KEY_TYPEf, SOC_MEM_KEY_L2_ENTRY_1_L2_BRIDGE);
  11662             }
  11663             SOC_IF_ERROR_RETURN(WRITE_L2_BULK_KEY_TYPE_PORT_Br(unit, rval));
  11664             soc_cm_sfree(unit, vlan_map);
  11665         }
  11666         SOC_IF_ERROR_RETURN(READ_AUX_L2_BULK_CONTROLr(unit, &rval));
  11667         if ((l2_ring->port0 != BCM_GPORT_INVALID) || 
  11668             (l2_ring->port1 != BCM_GPORT_INVALID)) {
  11669             soc_reg_field_set(unit, AUX_L2_BULK_CONTROLr, &rval, 
  11670                               MATCH_PORT_Af, 1);
  11671             soc_reg_field_set(unit, AUX_L2_BULK_CONTROLr, &rval, 
  11672                               MATCH_PORT_Bf, 1);
  11673         } 
  11674         if (match_type != -1) {
  11675             soc_reg_field_set(unit, AUX_L2_BULK_CONTROLr, &rval, 
  11676                               MATCH_VLANS_PORT_Af, 1);
  11677             soc_reg_field_set(unit, AUX_L2_BULK_CONTROLr, &rval, 
  11678                               MATCH_VLANS_PORT_Bf, 1);
  11679             soc_reg_field_set(unit, AUX_L2_BULK_CONTROLr, &rval, 
  11680                               MATCH_KEY_TYPE_PORT_Af, 1);
  11681             soc_reg_field_set(unit, AUX_L2_BULK_CONTROLr, &rval, 
  11682                               MATCH_KEY_TYPE_PORT_Bf, 1);
  11683         }
  11684         soc_reg_field_set(unit, AUX_L2_BULK_CONTROLr, &rval, BULK_OPS_ENABLEf, 
  11685                           1);
  11686         SOC_IF_ERROR_RETURN(WRITE_AUX_L2_BULK_CONTROLr(unit, rval));
  11687         /*
  11688         * match_type is set to 1 in case of flushing based on VP
  11689         */
  11690         if (vp_type) {  
  11691             match_type = 1;
  11692         }    
  11693 #ifdef BCM_KATANA2_SUPPORT        
  11694         if (SOC_IS_KATANA2(unit)) {
  11695             rv = _kt2_l2_delete_all_by_hw(unit, match_type, r_flags); 
  11696         } else 
  11697 #endif        
  11698         {    
  11699             rv = _tr3_l2_delete_all_by_hw(unit, match_type, r_flags);
  11700         }    
  11701         if (rv < 0) {
  11702             LOG_ERROR(BSL_LS_BCM_L2,
  11703                       (BSL_META_U(unit,
  11704                                   "Error deleting entries: %d\n"), rv));
  11705         }
  11706  	
  11707         /* Trunk port delete */
  11708         if ((BCM_GPORT_IS_TRUNK(l2_ring->port0))
  11709              || (BCM_GPORT_IS_TRUNK(l2_ring->port1))) {
  11710             SOC_IF_ERROR_RETURN(READ_L2_BULK_MATCH_PORT_Ar(unit, &rval));
  11711             if (soc_reg_field_get(unit, L2_BULK_MATCH_PORT_Ar,
  11712                                   rval, DEST_TYPEf) == 1) {
  11713                 soc_reg_field_set(unit, L2_BULK_MATCH_PORT_Ar,
  11714                                   &rval, MODULE_IDf, 0x80);
  11715             }
  11716             SOC_IF_ERROR_RETURN(WRITE_L2_BULK_MATCH_PORT_Ar(unit, rval));
  11717             
  11718             SOC_IF_ERROR_RETURN(READ_L2_BULK_MATCH_PORT_Br(unit, &rval));
  11719             if (soc_reg_field_get(unit, L2_BULK_MATCH_PORT_Br,
  11720                                   rval, DEST_TYPEf) == 1) {
  11721                 soc_reg_field_set(unit, L2_BULK_MATCH_PORT_Br,
  11722                                   &rval, MODULE_IDf, 0x80);
  11723             }
  11724             SOC_IF_ERROR_RETURN(WRITE_L2_BULK_MATCH_PORT_Br(unit, rval));
  11725 #ifdef BCM_KATANA2_SUPPORT            
  11726             if (SOC_IS_KATANA2(unit)) {
  11727                 rv = _kt2_l2_delete_all_by_hw(unit, match_type, r_flags);
  11728             } else
  11729 #endif      
  11730             {
  11731                 rv = _tr3_l2_delete_all_by_hw(unit, match_type, r_flags);
  11732             }    
  11733             if (rv < 0) {
  11734 	            LOG_ERROR(BSL_LS_BCM_L2,
  11735                           (BSL_META_U(unit,
  11736                                       "Error deleting entries: %d\n"), rv));
  11737             }
  11738         }
  11739         rval = 0;
  11740         SOC_IF_ERROR_RETURN(WRITE_AUX_L2_BULK_CONTROLr(unit, rval));    
  11741     }
  11742     return rv;
  11743 }
  11744 
  11745 int
  11746 bcm_tr3_l2_ring_replace(int unit, bcm_l2_ring_t *l2_ring)
  11747 {
  11748     int rv = BCM_E_NONE;
  11749     _BCM_ALL_L2X_MEM_LOCK(unit);
  11750     rv = _bcm_tr3_l2_ring_replace(unit, l2_ring);
  11751     _BCM_ALL_L2X_MEM_UNLOCK(unit);
  11752     return rv;
  11753 }
  11754 
  11755 /*
  11756  * Function:
  11757  *      bcm_tr3_bfd_l2_hash_dynamic_replace
  11758  * Purpose:
  11759  *      Replace dynamic L2 entries in a dual hash.
  11760  * Parameters:
  11761  *      unit - Unit number
  11762  *      l2x_entry - Entry to insert instead of dynamic entry.
  11763  * Returns:
  11764  *      BCM_E_NONE              Success
  11765  *      BCM_E_XXX               Error
  11766  */
  11767 
  11768 int bcm_tr3_bfd_l2_hash_dynamic_replace(int unit, void *l2x_entry)
  11769 {
  11770     _bcm_tr3_l2_entries_t l2_entry; 
  11771     
  11772     sal_memset(&l2_entry, 0, sizeof(_bcm_tr3_l2_entries_t)); 
  11773     sal_memcpy(&l2_entry.l2_entry_1, l2x_entry, sizeof(l2_entry_1_entry_t)); 
  11774     l2_entry.entry_flags |= _BCM_TR3_L2_SELECT_L2_ENTRY_1; 
  11775     
  11776     return _bcm_tr3_l2_hash_dynamic_replace(unit, &l2_entry); 
  11777 }
  11778 
  11779 #endif /* BCM_TRIUMPH3_SUPPORT */