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


      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:     Triumph L2 function implementations
      9  */
     10 
     11 #include <shared/bsl.h>
     12 
     13 #include <soc/defs.h>
     14 #if defined(BCM_TRX_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/triumph.h>
     28 #ifdef BCM_TRIDENT2_SUPPORT
     29 #include <soc/trident2.h>
     30 #endif /* BCM_TRIDENT2_SUPPORT */
     31 #ifdef BCM_TOMAHAWK_SUPPORT
     32 #include <soc/tomahawk.h>
     33 #endif /* BCM_TOMAHAWK_SUPPORT */
     34 #if defined(BCM_APACHE_SUPPORT)
     35 #include <soc/apache.h>
     36 #endif /* BCM_APACHE_SUPPORT */
     37 #if defined(BCM_MONTEREY_SUPPORT)
     38 #include <soc/monterey.h>
     39 #endif /* BCM_MONTEREY_SUPPORT */
     40 
     41 #include <bcm/l2.h>
     42 #include <bcm/error.h>
     43 
     44 #include <bcm_int/esw/mbcm.h>
     45 #include <bcm_int/esw/l2.h>
     46 #include <bcm_int/esw/firebolt.h>
     47 #include <bcm_int/esw/trx.h>
     48 #include <bcm_int/esw/triumph.h>
     49 #include <bcm_int/esw/mpls.h>
     50 #include <bcm_int/esw/mim.h>
     51 #include <bcm_int/esw/stack.h>
     52 #include <bcm_int/esw/trunk.h>
     53 #include <bcm_int/common/multicast.h>
     54 #include <bcm_int/esw/multicast.h>
     55 #include <bcm_int/esw/virtual.h>
     56 #include <bcm_int/esw_dispatch.h>
     57 #include <bcm_int/esw/trident.h>
     58 #include <bcm_int/esw/switch.h>
     59 #if defined(BCM_TRIUMPH3_SUPPORT)
     60 #include <bcm_int/esw/triumph3.h>
     61 #endif /* BCM_TRIUMPH3_SUPPORT */
     62 #if defined(BCM_TRIDENT2_SUPPORT)
     63 #include <bcm_int/esw/trident2.h>
     64 #endif /* BCM_TRIDENT2_SUPPORT */
     65 #if defined(BCM_GREYHOUND2_SUPPORT)
     66 #include <bcm_int/esw/greyhound2.h>
     67 #endif /* BCM_GREYHOUND2_SUPPORT */
     68 #if defined(BCM_SABER2_SUPPORT)
     69 #include <soc/saber2.h>
     70 #endif /* BCM_SABER2_SUPPORT */
     71 #if defined(BCM_METROLITE_SUPPORT)
     72 #include <soc/metrolite.h>
     73 #endif /* BCM_METROLITE_SUPPORT */
     74 #if defined (BCM_HGPROXY_COE_SUPPORT)
     75 #include <bcm_int/esw/subport.h>
     76 #endif /* BCM_HGPROXY_COE_SUPPORT */
     77 #if defined(BCM_TSN_SUPPORT)
     78 #include <bcm_int/esw/tsn.h>
     79 #endif /* BCM_TSN_SUPPORT */
     80 #if defined(BCM_KATANA2_SUPPORT)
     81 #include <bcm_int/esw/katana2.h>
     82 #define _BCM_PORT_MAC_MAX  170
     83 #endif /* BCM_KATANA2_SUPPORT */
     84 #if defined(BCM_GLOBAL_METER_SUPPORT)
     85 #include <bcm_int/esw/policer.h>
     86 #endif /* BCM_GLOBAL_METER_SUPPORT */
     87 
     88 #if defined(BCM_TOMAHAWK3_SUPPORT)
     89 #include <bcm_int/esw/tomahawk3.h>
     90 #endif /* BCM_TOMAHAWK3_SUPPORT  */
     91 
     92 #if defined(BCM_KATANA2_SUPPORT) || defined(BCM_TRIDENT2PLUS_SUPPORT)
     93 #include <bcm_int/esw/subport.h>
     94 #define _BCM_OLP_MAC_MAX   16
     95 
     96 #ifdef BCM_TRIDENT3_SUPPORT
     97 #include <soc/format.h>
     98 #include <soc/esw/flow_db.h>
     99 #include <soc/trident3.h>
    100 #include <bcm_int/esw/trident3.h>
    101 #include <bcm_int/esw/flow.h>
    102 #endif /* BCM_TRIDENT3_SUPPORT */
    103 
    104 #ifdef BCM_HELIX5_SUPPORT
    105 #include <soc/helix5.h>
    106 #endif /* BCM_HELIX5_SUPPORT  */
    107 
    108 #define _BCM_XGS_MAC_MAX   1
    109 
    110 #define DGLP_MODULE_ID_MASK                   0x7f80
    111 #define DGLP_PORT_NO_MASK                     0x7f
    112 #define DGLP_MODULE_ID_SHIFT_BITS             7
    113 #define DGLP_LAG_ID_INDICATOR_SHIFT_BITS      15
    114 #define MAC_MASK_HIGH                         0xffff
    115 #define MAC_MASK_LOW                          0xffffffff
    116 #define OLP_MAC_MASK                          0x1f
    117 #define OLP_LOWEST_MAC                        0
    118 #define OLP_HIGHEST_MAC                       1
    119 #define OLP_MAX_MAC_DIFF                      16
    120 #define OLP_ACTION_ADD                        1
    121 #define OLP_ACTION_UPDATE                     2
    122 #define OLP_ACTION_DELETE                     3
    123 #endif /* BCM_KATANA2_SUPPORT OR TD2+*/
    124 
    125 #if defined(BCM_TRIUMPH_SUPPORT) /* BCM_TRIUMPH_SUPPORT */
    126 
    127 #define GPORT_TYPE(_gport) (((_gport) >> _SHR_GPORT_TYPE_SHIFT) & _SHR_GPORT_TYPE_MASK)
    128 
    129 #define _BCM_L2_STATION_OVERLAY(_station_) \
    130         ((soc_feature(unit, soc_feature_riot) && \
    131         !(_station_->flags & BCM_L2_STATION_UNDERLAY)))
    132 
    133 #define _BCM_L2_STATION_ID_OVERLAY(_sid_) \
    134         ((soc_feature(unit, soc_feature_riot) && \
    135          (_sid_ >= _BCM_L2_STATION_ID_2_BASE)))
    136 
    137 /* To differentiate between overlay and underlay tcams */
    138 #define _BCM_L2_STATION_ENTRY_UNDERLAY (0)
    139 #define _BCM_L2_STATION_ENTRY_OVERLAY  (1)
    140 #define _BCM_L2_STATION_ENTRY_LEGACY   _BCM_L2_STATION_ENTRY_UNDERLAY
    141 
    142 
    143 #define _BCM_L2_STATION_ID_INVALID (-1)
    144 #define _BCM_L2_STATION_ID_BASE (1)
    145 #define _BCM_L2_STATION_ID_MAX  (0x1000000)
    146 #define _BCM_L2_STATION_ID_2_BASE (0x2000001)
    147 #define _BCM_L2_STATION_ID_2_MAX  (0x3000000)
    148 
    149 #define _BCM_L2_STATION_ENTRY_INSTALLED      (1 << 0)
    150 
    151 #define _BCM_L2_STATION_ENTRY_PRIO_NO_CHANGE (1 << 1)
    152 
    153 #define _BCM_L2_STATION_ENTRY_TYPE_NON_TCAM  (1 << 2)
    154 
    155 #if defined(BCM_KATANA2_SUPPORT) || defined(BCM_TRIDENT2PLUS_SUPPORT)
    156 
    157 #define _BCM_L2_STATION_ENTRY_TYPE_OAM_MAC  (1 << 3)
    158 
    159 #define _BCM_L2_STATION_ENTRY_TYPE_OLP_MAC  (1 << 4)
    160 
    161 #define _BCM_L2_STATION_ENTRY_TYPE_XGS_MAC  (1 << 5)
    162 
    163 #endif /* BCM_KATANA2_SUPPORT OR TD2+ */
    164 
    165 #define _BCM_L2_STATION_TERM_FLAGS_MASK    (BCM_L2_STATION_IPV4       \
    166                                             | BCM_L2_STATION_IPV6     \
    167                                             | BCM_L2_STATION_ARP_RARP \
    168                                             | BCM_L2_STATION_MPLS     \
    169                                             | BCM_L2_STATION_MIM      \
    170                                             | BCM_L2_STATION_TRILL    \
    171                                             | BCM_L2_STATION_FCOE     \
    172                                             | BCM_L2_STATION_OAM)
    173 
    174 #define _BCM_GH2_L2_STATION_FLAGS_MASK    (BCM_L2_STATION_IPV4   \
    175                                             | BCM_L2_STATION_IPV6     \
    176                                             | BCM_L2_STATION_ARP_RARP \
    177                                             | BCM_L2_STATION_OAM \
    178                                             | BCM_L2_STATION_COPY_TO_CPU \
    179                                             | BCM_L2_STATION_DISCARD \
    180                                             | BCM_L2_STATION_WITH_ID \
    181                                             | BCM_L2_STATION_REPLACE)
    182 
    183 /*
    184  * Macro:
    185  *     ParamMax
    186  * Purpose:
    187  *     Determine maximum value that can be stored in the field.
    188  */
    189 #define ParamMax(_unit_, _mem_, _field_)                                      \
    190             ((soc_mem_field_length((_unit_), (_mem_) , (_field_)) < 32) ?     \
    191             ((1 << soc_mem_field_length((_unit_), (_mem_), (_field_))) - 1) : \
    192             (0xFFFFFFFFUL))                             
    193 /*
    194  * Macro:
    195  *     ParamCheck
    196  * Purpose:
    197  *     Check if value can fit in the field and return error if it exceeds
    198  *     the range. 
    199  */
    200 #define ParamCheck(_unit_, _mem_, _field_, _value_)                          \
    201         do {                                                                 \
    202             if (0 == ((uint32)(_value_) <=                                   \
    203                 (uint32)ParamMax((_unit_), (_mem_), (_field_)))) {           \
    204                     LOG_ERROR(BSL_LS_BCM_L2, \
    205                               (BSL_META("L2(unit %d) Error: _value_ %d > %d (max)" \
    206                                " mem (%d) field (%d).\n"), _unit_, (_value_),    \
    207                                (uint32)ParamMax((_unit_), (_mem_), (_field_)),  \
    208                                (_mem_), (_field_)));                            \
    209                     return (BCM_E_PARAM);                                    \
    210             }                                                                \
    211         } while(0)
    212 
    213 /*
    214  * Macro:
    215  *     SC_LOCK
    216  * Purpose:
    217  *     Lock take the Field control mutex
    218  */
    219 #define SC_LOCK(control) \
    220             sal_mutex_take((control)->sc_lock, sal_mutex_FOREVER)
    221 
    222 /*
    223  * Macro:
    224  *     FP_UNLOCK
    225  * Purpose:
    226  *     Lock take the Field control mutex
    227  */
    228 #define SC_UNLOCK(control) \
    229             sal_mutex_give((control)->sc_lock);
    230 
    231 STATIC _bcm_l2_station_control_t *_station_control[BCM_MAX_NUM_UNITS] = {NULL};
    232 int prio_with_no_free_entries = FALSE;
    233 
    234 #endif /* !BCM_TRIUMPH_SUPPORT */
    235 #define DEFAULT_L2DELETE_CHUNKS		64	/* 16k entries / 64 = 256 */
    236 
    237 typedef struct _bcm_mac_block_info_s {
    238     bcm_pbmp_t mb_pbmp;
    239     int ref_count;
    240 } _bcm_mac_block_info_t;
    241 
    242 static _bcm_mac_block_info_t *_mbi_entries[BCM_MAX_NUM_UNITS];
    243 static int _mbi_num[BCM_MAX_NUM_UNITS];
    244 
    245 #if defined(BCM_SCORPION_SUPPORT) && defined(INCLUDE_L3)
    246 extern int16 * _sc_subport_group_index[BCM_MAX_NUM_UNITS];
    247 #define _SC_SUBPORT_NUM_PORT  (4096)
    248 #define _SC_SUBPORT_NUM_GROUP (4096/8)
    249 #define _SC_SUBPORT_VPG_FIND(unit, vp, grp) \
    250     do { \
    251          int ix; \
    252          grp = -1; \
    253          for (ix = 0; ix < _SC_SUBPORT_NUM_GROUP; ix++) { \
    254               if (_sc_subport_group_index[unit][ix] == vp) { \
    255                   grp = ix * 8; \
    256                   break;  \
    257               } \
    258          } \
    259        } while ((0))
    260 #endif /* BCM_SCORPION_SUPPORT && INCLUDE_L3 */
    261 #ifdef PLISIM
    262 #ifdef BCM_KATANA_SUPPORT
    263 extern void _bcm_kt_enable_port_age_simulation(uint32 flags, _bcm_l2_replace_t *rep_st);
    264 #endif
    265 #endif
    266 
    267 #if defined(BCM_TRIUMPH_SUPPORT)
    268 
    269 #define L2_MYSTA_PROFILE_DEFAULT  0
    270 STATIC soc_profile_mem_t *l2_mysta_profile[BCM_MAX_NUM_UNITS][2];
    271 
    272 /*
    273  * Function:
    274  *     _bcm_l2_station_tcam_mem_get
    275  * Purpose:
    276  *     Get device specific station TCAM memory name.
    277  * Parameters:
    278  *     unit      - (IN) BCM device number
    279  *     overlay   - (IN) Overlay termination indication.
    280  *     tcam_mem  - (OUT) Station TCAM memory name.
    281  * Retruns:
    282  *     BCM_E_XXX
    283  */
    284 STATIC int
    285 _bcm_l2_station_tcam_mem_get(int unit, int overlay, soc_mem_t *tcam_mem)
    286 {
    287     if (NULL == tcam_mem) {
    288         return (BCM_E_PARAM);
    289     }
    290 
    291 #ifdef BCM_RIOT_SUPPORT
    292     /* Tcam memory for overlay termination */
    293     if (overlay == _BCM_L2_STATION_ENTRY_OVERLAY) {
    294         if (soc_feature(unit, soc_feature_my_station_2)) {
    295             *tcam_mem = MY_STATION_TCAM_2m;
    296             return (BCM_E_NONE);
    297         } else {
    298             return (BCM_E_UNAVAIL);
    299         }
    300     }
    301 #endif /* BCM_RIOT_SUPPORT */
    302     if (SOC_IS_ENDURO(unit) || SOC_IS_TRIUMPH(unit)
    303         || SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit)
    304         || SOC_IS_VALKYRIE(unit) || SOC_IS_VALKYRIE2(unit)
    305         || SOC_IS_HURRICANE(unit) || SOC_IS_HURRICANE2(unit)) {
    306         
    307         *tcam_mem = MPLS_STATION_TCAMm;
    308 
    309     } else if (SOC_IS_KATANAX(unit) || SOC_IS_TRIDENT(unit)
    310                || SOC_IS_TD2_TT2(unit) || SOC_IS_TRIUMPH3(unit)
    311                || soc_feature(unit, soc_feature_gh2_my_station)) {
    312 
    313         *tcam_mem = MY_STATION_TCAMm;
    314 
    315     } else {
    316 
    317         *tcam_mem = INVALIDm;
    318 
    319         return (BCM_E_UNAVAIL);
    320     }
    321 
    322     return (BCM_E_NONE);
    323 }
    324 
    325 /*
    326  * Function:
    327  *     _bcm_l2_station_control_deinit
    328  * Purpose:
    329  *     Uninitialize device station control information.
    330  * Parameters:
    331  *     unit  - (IN) BCM device number
    332  * Retruns:
    333  *     BCM_E_XXX
    334  */
    335 int
    336 _bcm_tr_l2_station_control_deinit(int unit)
    337 {
    338     _bcm_l2_station_control_t  *sc; /* Station control structure pointer. */
    339 
    340     sc = _station_control[unit];
    341     if (NULL == sc) {
    342         return (BCM_E_NONE);
    343     }
    344 
    345     BCM_IF_ERROR_RETURN
    346         (bcm_tr_l2_station_delete_all(unit));
    347 
    348     if (NULL != sc->entry_arr) {
    349         sal_free(sc->entry_arr);
    350         sc->entry_arr = NULL;
    351     }
    352 
    353 
    354     if (NULL != sc->entry_arr_2) {
    355         sal_free(sc->entry_arr_2);
    356         sc->entry_arr_2 = NULL;
    357     }
    358 
    359 
    360     if (NULL != sc->sc_lock) {
    361         sal_mutex_destroy(sc->sc_lock);
    362     }
    363 
    364     _station_control[unit] = NULL;
    365 
    366     sal_free(sc);
    367 
    368     return (BCM_E_NONE);
    369 
    370 }
    371 
    372 /*
    373  * Function:
    374  *     _bcm_l2_station_control_init
    375  * Purpose:
    376  *     Initialize device station control information.
    377  * Parameters:
    378  *     unit  - (IN) BCM device number
    379  * Retruns:
    380  *     BCM_E_XXX
    381  */
    382 int
    383 _bcm_tr_l2_station_control_init(int unit)
    384 {
    385     int                        rv;          /* Operation return status.     */
    386     _bcm_l2_station_control_t  *sc = NULL;  /* Station control structure.   */
    387     soc_mem_t                  tcam_mem;    /* TCAM memory name.            */
    388     uint32                     mem_size;    /* Size of entry buffer.        */
    389     int                        max_entries; /* Max no. of entries in table. */
    390     int                        i;           /* Temporary iterator variable. */
    391 
    392     /* Deinit if control has already been initialized. */
    393     if (NULL != _station_control[unit]) {
    394         rv = _bcm_tr_l2_station_control_deinit(unit);
    395         if (BCM_FAILURE(rv)) {
    396             return (rv);
    397         }
    398     }
    399 
    400     /* Allocate the station control memory for this unit. */
    401     sc = (_bcm_l2_station_control_t *) sal_alloc
    402             (sizeof(_bcm_l2_station_control_t), "L2 station control");
    403     if (NULL == sc) {
    404         return (BCM_E_MEMORY);
    405     }
    406 
    407     sal_memset(sc, 0, sizeof(_bcm_l2_station_control_t));
    408 
    409     rv = _bcm_l2_station_tcam_mem_get(unit, 0, &tcam_mem);
    410     if (BCM_FAILURE(rv)) {
    411         sal_free(sc);
    412         return (rv);
    413     }
    414 
    415     sc->last_allocated_sid = (_BCM_L2_STATION_ID_BASE - 1);
    416 
    417     max_entries = soc_mem_index_count(unit, tcam_mem);
    418 
    419     sc->entries_total = max_entries;
    420 
    421     sc->entries_free = max_entries;
    422 
    423 #ifdef BCM_METROLITE_SUPPORT
    424     if (SOC_IS_METROLITE(unit)) {
    425         sc->port_entries_total = ML_PORT_MAC_MAX;
    426 
    427         sc->port_entries_free = ML_PORT_MAC_MAX;
    428 
    429         sc->olp_entries_total = _BCM_OLP_MAC_MAX;
    430 
    431         sc->olp_entries_free = _BCM_OLP_MAC_MAX;
    432     } else
    433 #endif
    434 #ifdef BCM_SABER2_SUPPORT
    435     if (SOC_IS_SABER2(unit)) {
    436         sc->port_entries_total =SB2_PORT_MAC_MAX;
    437 
    438         sc->port_entries_free =SB2_PORT_MAC_MAX;
    439 
    440         sc->olp_entries_total = _BCM_OLP_MAC_MAX; 
    441 
    442         sc->olp_entries_free = _BCM_OLP_MAC_MAX; 
    443     } else
    444 #endif
    445 #ifdef BCM_KATANA2_SUPPORT
    446     if (SOC_IS_KATANA2(unit)) {
    447 
    448         sc->port_entries_total =_BCM_PORT_MAC_MAX;
    449 
    450         sc->port_entries_free =_BCM_PORT_MAC_MAX;
    451     }
    452 #endif
    453 #if defined(BCM_KATANA2_SUPPORT) || defined(BCM_TRIDENT2PLUS_SUPPORT)
    454     if (SOC_IS_KATANA2(unit) || soc_feature(unit, soc_feature_fp_based_oam)) {
    455         sc->olp_entries_total = _BCM_OLP_MAC_MAX; 
    456         sc->olp_entries_free = _BCM_OLP_MAC_MAX; 
    457     }
    458 #endif
    459 
    460     sc->entry_count = 0;
    461 #ifdef BCM_KATANA2_SUPPORT
    462     if (SOC_IS_KATANA2(unit)) {
    463         max_entries = sc->entries_total + sc->port_entries_total +
    464                       sc->olp_entries_total + 1;
    465     }
    466 #endif
    467 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
    468     if (soc_feature(unit, soc_feature_fp_based_oam)) {
    469         max_entries = sc->entries_total + sc->olp_entries_total + 1;
    470     }
    471 #endif
    472     mem_size = (max_entries * sizeof(_bcm_l2_station_entry_t *));
    473 
    474     sc->entry_arr = (_bcm_l2_station_entry_t **)
    475                         sal_alloc(mem_size, "L2 station entry pointers");
    476     if (NULL == sc->entry_arr) {
    477         sal_free(sc);
    478         sc = NULL;
    479         return (BCM_E_MEMORY);
    480     }
    481 
    482     for (i = 0; i < max_entries; i++) {
    483         sc->entry_arr[i] = NULL;
    484     }
    485 
    486 #ifdef BCM_RIOT_SUPPORT
    487     if (soc_feature(unit, soc_feature_riot)) {
    488         rv = _bcm_l2_station_tcam_mem_get(unit,
    489                  _BCM_L2_STATION_ENTRY_OVERLAY, &tcam_mem);
    490         if (BCM_FAILURE(rv)) {
    491             sal_free(sc);
    492             sc = NULL;
    493             return (rv);
    494         }
    495 
    496         sc->last_allocated_sid_2 = (_BCM_L2_STATION_ID_2_BASE - 1);
    497         max_entries = soc_mem_index_count(unit, tcam_mem);
    498         if (max_entries > 0) {
    499         sc->entries_total_2 = max_entries;
    500         sc->entries_free_2 = max_entries;
    501 
    502         mem_size = (max_entries * sizeof(_bcm_l2_station_entry_t *));
    503 
    504         sc->entry_arr_2 = (_bcm_l2_station_entry_t **)
    505                             sal_alloc(mem_size, "L2 station entry pointers");
    506         if (NULL == sc->entry_arr_2) {
    507             sal_free(sc);
    508             sc = NULL;
    509             return (BCM_E_MEMORY);
    510         }
    511 
    512         for (i = 0; i < max_entries; i++) {
    513             sc->entry_arr_2[i] = NULL;
    514         }
    515         }
    516 
    517     }
    518 #endif /* BCM_RIOT_SUPPORT */
    519 
    520     sc->sc_lock = sal_mutex_create("L2 station control.lock");
    521     if (NULL == sc->sc_lock) {
    522         sal_free(sc->entry_arr);
    523         sc->entry_arr = NULL;
    524         if (soc_feature(unit, soc_feature_riot)) {
    525             sal_free(sc->entry_arr_2);
    526             sc->entry_arr_2 = NULL;
    527         }
    528         sal_free(sc);
    529         sc = NULL;
    530         return (BCM_E_MEMORY);
    531     }
    532 
    533     _station_control[unit] = sc;
    534 
    535     return (BCM_E_NONE);
    536 }
    537 
    538 /*
    539  * Function:
    540  *     _bcm_l2_station_control_get
    541  * Purpose:
    542  *     Get device station control structure pointer.
    543  * Parameters:
    544  *     unit  - (IN) BCM device number
    545  *     sc    - (OUT) Device station structure pointer. 
    546  * Retruns:
    547  *     BCM_E_XXX
    548  */
    549 int
    550 _bcm_l2_station_control_get(int unit, _bcm_l2_station_control_t **sc)
    551 {
    552 
    553 #if defined(BCM_TOMAHAWK3_SUPPORT)
    554     if (SOC_IS_TOMAHAWK3(unit)) {
    555         return _bcm_th3_l2_station_control_get(unit, sc);
    556     }
    557 #endif /* BCM_TOMAHAWK3_SUPPORT  */
    558 
    559     /* Input parameter check. */
    560     if (NULL == sc) {
    561         return (BCM_E_PARAM);
    562     }
    563 
    564     if (NULL == _station_control[unit]) {
    565         return (BCM_E_INIT);
    566     }
    567 
    568     *sc = _station_control[unit];
    569 
    570     return (BCM_E_NONE);
    571 }
    572 
    573 /*
    574  * Function:
    575  *     _bcm_l2_station_entry_get
    576  * Purpose:
    577  *     Get station entry details by performing
    578  *     lookup using station ID.
    579  * Parameters:
    580  *     unit  - (IN) BCM device number
    581  *     sid   - (IN) Station ID.
    582  *     ent_p - (OUT) Station look up result.
    583  * Retruns:
    584  *     BCM_E_XXX
    585  */
    586 STATIC int
    587 _bcm_l2_station_entry_get(int unit,
    588                           int sid,
    589                           _bcm_l2_station_entry_t **ent_p)
    590 {
    591     _bcm_l2_station_control_t *sc;   /* Station control structure pointer. */
    592     _bcm_l2_station_entry_t **entry_arr;
    593     int                       index; /* Entry index.                       */
    594     int                       count;
    595 
    596 #if defined(BCM_TOMAHAWK3_SUPPORT)
    597     if (SOC_IS_TOMAHAWK3(unit)) {
    598         return _bcm_th3_l2_station_entry_get(unit, sid, ent_p);
    599     }
    600 #endif /* BCM_TOMAHAWK3_SUPPORT  */
    601 
    602     /* Input parameter check. */
    603     if (NULL == ent_p) {
    604         return (BCM_E_PARAM);
    605     }
    606 
    607     BCM_IF_ERROR_RETURN(_bcm_l2_station_control_get(unit, &sc));
    608 
    609 #ifdef BCM_RIOT_SUPPORT
    610     if (_BCM_L2_STATION_ID_OVERLAY(sid)) {
    611         count = sc->entries_total_2;
    612         entry_arr = (sc->entry_arr_2);
    613     } else
    614 #endif /* BCM_RIOT_SUPPORT */
    615     {
    616         count = sc->entries_total;
    617         entry_arr = (sc->entry_arr);
    618 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
    619         if (soc_feature(unit, soc_feature_fp_based_oam)) {
    620             count = sc->entries_total + sc->olp_entries_total + 1;
    621         }
    622 #endif
    623     }
    624 #ifdef BCM_KATANA2_SUPPORT
    625     if (SOC_IS_KATANA2(unit)) {
    626         count = sc->entries_total + sc->port_entries_total + 
    627                                           sc->olp_entries_total + 1;
    628     }
    629 #endif
    630 
    631     for (index = 0; index < count; index++) {
    632 
    633         if (NULL == entry_arr[index]) {
    634             continue;
    635         }
    636 
    637         if (sid == entry_arr[index]->sid) {
    638             *ent_p = entry_arr[index];
    639             LOG_DEBUG(BSL_LS_BCM_L2,
    640                       (BSL_META_U(unit,
    641                                   "L2(unit %d) Info: (SID=%d) - found (idx=%d).\n"),
    642                        unit, sid, index));
    643             return (BCM_E_NONE);
    644         }
    645     }
    646 
    647     LOG_DEBUG(BSL_LS_BCM_L2,
    648               (BSL_META_U(unit,
    649                           "L2(unit %d) Info: (SID=%d) - not found (idx=%d).\n"),
    650                unit, sid, index));
    651 
    652     /* L2 station entry with ID == sid not found. */
    653     return (BCM_E_NOT_FOUND);
    654 }
    655 
    656 int
    657 _bcm_l2_mysta_profile_detach(int unit)
    658 {
    659     int i, rv, t_count = 2;
    660     soc_mem_t mem[2] = {MY_STATION_PROFILE_1m, MY_STATION_PROFILE_2m};
    661 
    662     if (l2_mysta_profile[unit][1] == NULL) {
    663         t_count = 1;
    664     }
    665 
    666     for (i = 0; i < t_count; ++i) {
    667         if (SOC_MEM_IS_VALID(unit, mem[i])) {
    668             /* De-initialize the MY_STATION_PROFILE_1 table */
    669             rv = soc_profile_mem_destroy(unit, l2_mysta_profile[unit][i]);
    670             BCM_IF_ERROR_RETURN(rv);
    671 
    672             sal_free(l2_mysta_profile[unit][i]);
    673             l2_mysta_profile[unit][i] = NULL;
    674         }
    675     }
    676     return BCM_E_NONE;
    677 }
    678 
    679 int
    680 _bcm_l2_mysta_profile_init(int unit)
    681 {
    682     int i, idx, j, t_count = 2;
    683     my_station_tcam_entry_t mysta_entry;
    684     uint32 temp_index;
    685     soc_mem_t mem[2];
    686     int entry_words[2];
    687     void *entries[2];
    688     my_station_profile_1_entry_t mysta_profile_1;
    689     my_station_profile_2_entry_t mysta_profile_2;
    690     void *prof_entry;
    691     uint32 ent_sz;
    692     uint32 dest_type = 0;
    693     /* MY_STATION_PROFILE_2m is for MY_STATION_TCAM_2m, but we don't know if
    694      * they are in sync, so set table_count=1 */
    695     int table_count = 1;
    696     soc_mem_t tcam_mem[2] = {MY_STATION_TCAMm, MY_STATION_TCAM_2m};
    697 
    698     /* Create profile table cache (or re-init if it already exists) */
    699     mem[0] = MY_STATION_PROFILE_1m;
    700     mem[1] = MY_STATION_PROFILE_2m;
    701     ent_sz = sizeof(my_station_profile_1_entry_t);
    702     prof_entry = &mysta_profile_1;
    703 
    704     for(j = 0; j < t_count; ++j) {
    705         if (SOC_MEM_IS_VALID(unit, mem[j])) {
    706             if (j == 1) {
    707                 prof_entry = &mysta_profile_2;
    708                 ent_sz = sizeof(my_station_profile_2_entry_t);
    709             }
    710             /* Initialize the ING_VLAN_TAG_ACTION_PROFILE table */
    711 
    712             if (l2_mysta_profile[unit][j] == NULL) {
    713                 l2_mysta_profile[unit][j] = sal_alloc(sizeof(soc_profile_mem_t),
    714                                                      "L2 MYSTA Profile Mem");
    715                 if (l2_mysta_profile[unit][j] == NULL) {
    716                     return BCM_E_MEMORY;
    717                 }
    718                 soc_profile_mem_t_init(l2_mysta_profile[unit][j]);
    719             }
    720 
    721             /* Create profile table cache (or re-init if it already exists) */
    722             entry_words[0] = entry_words[1] = ent_sz / sizeof(uint32);
    723             SOC_IF_ERROR_RETURN(
    724                 soc_profile_mem_create(unit, &mem[j], entry_words, table_count,
    725                                    l2_mysta_profile[unit][j]));
    726 
    727             if (SOC_WARM_BOOT(unit)) {
    728                 /* Increment the ref count for all ports */
    729                 for (i = 0; i < soc_mem_index_count(unit, tcam_mem[j]); i++) {
    730                     if (j == 1) {
    731                         SOC_IF_ERROR_RETURN
    732                             (READ_MY_STATION_TCAM_2m(unit, MEM_BLOCK_ANY, i, &mysta_entry));
    733                     } else {
    734                         SOC_IF_ERROR_RETURN
    735                             (READ_MY_STATION_TCAMm(unit, MEM_BLOCK_ANY, i, &mysta_entry));
    736                     }
    737                     idx = soc_mem_field32_get(unit, tcam_mem[j],
    738                                               &mysta_entry, VALIDf);
    739                     if (idx == 0) {
    740                         continue;
    741                     }
    742                     idx = soc_mem_field32_dest_get(unit, tcam_mem[j],
    743                                 &mysta_entry, DESTINATIONf, &dest_type);
    744                     if (dest_type != SOC_MEM_FIF_DEST_MYSTA) {
    745                         continue;
    746                     }
    747 
    748                     SOC_PROFILE_MEM_REFERENCE(unit, l2_mysta_profile[unit][j], idx, 1);
    749                     SOC_PROFILE_MEM_ENTRIES_PER_SET(unit, l2_mysta_profile[unit][j], idx, 1);
    750                 }
    751 
    752                 /* One extra increment to preserve location
    753                  * ING_ACTION_PROFILE_DEFAULT */
    754                 SOC_PROFILE_MEM_REFERENCE(unit, l2_mysta_profile[unit][j],
    755                     L2_MYSTA_PROFILE_DEFAULT,
    756                     soc_mem_index_count(unit, tcam_mem[j]) + 1);
    757 
    758             } else {
    759                 /* Initialize the ING_ACTION_PROFILE_DEFAULT. For untagged and
    760                  * inner-tagged packets, always add an outer tag.
    761                  */
    762                 sal_memset(prof_entry, 0, ent_sz);
    763                 entries[0] = prof_entry;
    764                 entries[1] = prof_entry;
    765                 SOC_IF_ERROR_RETURN
    766                     (soc_profile_mem_add(unit, l2_mysta_profile[unit][j],
    767                                          (void *) &entries, 1, &temp_index));
    768 
    769                 /* Increment the ref count for MY_STATION_TCAM */
    770                 SOC_PROFILE_MEM_REFERENCE(unit, l2_mysta_profile[unit][j],
    771                     L2_MYSTA_PROFILE_DEFAULT,
    772                     soc_mem_index_count(unit, tcam_mem[j]));
    773              }
    774         }
    775     }
    776 
    777     return BCM_E_NONE;
    778 }
    779 
    780 void
    781 _bcm_l2_mysta_station_to_entry(int unit, bcm_l2_station_t *station, soc_mem_t mysp_mem, void *entry)
    782 {
    783     soc_mem_field32_set(unit, mysp_mem, entry, MIM_TERMINATION_ALLOWEDf,
    784                         ((station->flags & BCM_L2_STATION_MIM) ? 1 : 0));
    785     soc_mem_field32_set(unit, mysp_mem, entry, MPLS_TERMINATION_ALLOWEDf,
    786                         ((station->flags & BCM_L2_STATION_MPLS) ? 1 : 0));
    787     soc_mem_field32_set(unit, mysp_mem, entry, IPV4_TERMINATION_ALLOWEDf,
    788                         ((station->flags & BCM_L2_STATION_IPV4) ? 1 : 0));
    789     soc_mem_field32_set(unit, mysp_mem, entry, IPV6_TERMINATION_ALLOWEDf,
    790                         ((station->flags & BCM_L2_STATION_IPV6) ? 1 : 0));
    791     soc_mem_field32_set(unit, mysp_mem, entry, ARP_RARP_TERMINATION_ALLOWEDf,
    792                         ((station->flags & BCM_L2_STATION_ARP_RARP) ? 1 : 0));
    793     if (soc_mem_field_valid(unit, mysp_mem, TRILL_TERMINATION_ALLOWEDf)) {
    794         soc_mem_field32_set(unit, mysp_mem, entry, TRILL_TERMINATION_ALLOWEDf,
    795                             ((station->flags & BCM_L2_STATION_TRILL) ? 1 : 0));
    796     }
    797     if (soc_mem_field_valid(unit, mysp_mem, OAM_TERMINATION_ALLOWEDf)) {
    798         soc_mem_field32_set(unit, mysp_mem, entry, OAM_TERMINATION_ALLOWEDf,
    799                             ((station->flags & BCM_L2_STATION_OAM) ? 1 : 0));
    800     }
    801     soc_mem_field32_set(unit, mysp_mem, entry, FCOE_TERMINATION_ALLOWEDf,
    802                         ((station->flags & BCM_L2_STATION_FCOE) ? 1 : 0));
    803     soc_mem_field32_set(unit, mysp_mem, entry, IPV4_MULTICAST_TERMINATION_ALLOWEDf,
    804                         ((station->flags & BCM_L2_STATION_IPV4_MCAST) ? 1 : 0));
    805     soc_mem_field32_set(unit, mysp_mem, entry, IPV6_MULTICAST_TERMINATION_ALLOWEDf,
    806                         ((station->flags & BCM_L2_STATION_IPV6_MCAST) ? 1 : 0));
    807 }
    808 
    809 int
    810 _bcm_l2_mysta_profile_entry_add(int unit,
    811                                 void *entry,
    812                                 int mem_no,
    813                                 uint32 *mysta_prof_id)
    814 {
    815     void *entries[2];
    816     entries[0] = entry;
    817     entries[1] = entry;
    818 
    819     return (soc_profile_mem_add(unit, l2_mysta_profile[unit][mem_no],
    820                                 (void *) &entries, 1, mysta_prof_id));
    821 }
    822 
    823 void
    824 _bcm_l2_mysta_profile_entry_increment(int unit, int mem_no, uint32 mysta_prof_id)
    825 {
    826     SOC_PROFILE_MEM_REFERENCE(unit, l2_mysta_profile[unit][mem_no], mysta_prof_id, 1);
    827 }
    828 
    829 void
    830 _bcm_l2_mysta_entry_to_station(int unit, void *entry, soc_mem_t mem, bcm_l2_station_t *station)
    831 {
    832     uint32 val;
    833 
    834     val = soc_mem_field32_get(unit, mem, entry, MIM_TERMINATION_ALLOWEDf);
    835     station->flags |= val ? BCM_L2_STATION_MIM : 0;
    836 
    837     val = soc_mem_field32_get(unit, mem, entry, MPLS_TERMINATION_ALLOWEDf);
    838     station->flags |= val ? BCM_L2_STATION_MPLS : 0;
    839 
    840     val = soc_mem_field32_get(unit, mem, entry, IPV4_TERMINATION_ALLOWEDf);
    841     station->flags |= val ? BCM_L2_STATION_IPV4 : 0;
    842 
    843     val = soc_mem_field32_get(unit, mem, entry, IPV6_TERMINATION_ALLOWEDf);
    844     station->flags |= val ? BCM_L2_STATION_IPV6 : 0;
    845 
    846     val = soc_mem_field32_get(unit, mem, entry, ARP_RARP_TERMINATION_ALLOWEDf);
    847     station->flags |= val ? BCM_L2_STATION_ARP_RARP : 0;
    848 
    849     if (soc_mem_field_valid(unit, mem, TRILL_TERMINATION_ALLOWEDf)) {
    850         val = soc_mem_field32_get(unit, mem, entry, TRILL_TERMINATION_ALLOWEDf);
    851         station->flags |= val ? BCM_L2_STATION_TRILL : 0;
    852     }
    853 
    854     if (soc_mem_field_valid(unit, mem, OAM_TERMINATION_ALLOWEDf)) {
    855         val = soc_mem_field32_get(unit, mem, entry, OAM_TERMINATION_ALLOWEDf);
    856         station->flags |= val ? BCM_L2_STATION_OAM : 0;
    857     }
    858 
    859     val = soc_mem_field32_get(unit, mem, entry, FCOE_TERMINATION_ALLOWEDf);
    860     station->flags |= val ? BCM_L2_STATION_FCOE : 0;
    861 
    862     val = soc_mem_field32_get(unit, mem, entry, IPV4_MULTICAST_TERMINATION_ALLOWEDf);
    863     station->flags |= val ? BCM_L2_STATION_IPV4_MCAST : 0;
    864 
    865     val = soc_mem_field32_get(unit, mem, entry, IPV6_MULTICAST_TERMINATION_ALLOWEDf);
    866     station->flags |= val ? BCM_L2_STATION_IPV6_MCAST : 0;
    867 }
    868 
    869 int
    870 _bcm_l2_mysta_profile_entry_get(int unit,
    871                                 void *entry,
    872                                 int mem_no,
    873                                 uint32 mysta_prof_id)
    874 {
    875     int rv = 0;
    876     void *entries[2];
    877     entries[0] = entry;
    878     entries[1] = entry;
    879     rv = soc_profile_mem_get(unit, l2_mysta_profile[unit][mem_no],
    880                              mysta_prof_id, 1, entries);
    881     return rv;
    882 }
    883 
    884 /*
    885  * Function : _bcm_l2_mysta_profile_entry_delete
    886  *
    887  * Purpose  : remove an entry from MY_STATION_PROFILE_1 profile table
    888  */
    889 int
    890 _bcm_l2_mysta_profile_entry_delete(int unit, int mem_no, uint32 mysta_prof_id)
    891 {
    892     return soc_profile_mem_delete(unit, l2_mysta_profile[unit][mem_no], mysta_prof_id);
    893 }
    894 
    895 #endif
    896 
    897 typedef enum _bcm_tr_l2x_memacc_field_e {
    898     _BCM_TR_L2X_MEMACC_VALID_f,
    899     _BCM_TR_L2X_MEMACC_KEY_TYPE_f,
    900     _BCM_TR_L2X_MEMACC_MAC_ADDR_f,
    901     _BCM_TR_L2X_MEMACC_VFI_f,
    902     _BCM_TR_L2X_MEMACC_VLAN_ID_f,
    903     _BCM_TR_L2X_MEMACC_L2MC_PTR_f,
    904     _BCM_TR_L2X_MEMACC_VPG_TYPE_f,
    905     _BCM_TR_L2X_MEMACC_DEST_TYPE_f,
    906     _BCM_TR_L2X_MEMACC_TGID_f,
    907     _BCM_TR_L2X_MEMACC_REMOTE_TRUNK_f,
    908     _BCM_TR_L2X_MEMACC_PORT_NUM_f,
    909     _BCM_TR_L2X_MEMACC_MODULE_ID_f,
    910     _BCM_TR_L2X_MEMACC_CLASS_ID_f,
    911     _BCM_TR_L2X_MEMACC_MAC_BLOCK_INDEX_f,
    912     _BCM_TR_L2X_MEMACC_PRI_f,
    913     _BCM_TR_L2X_MEMACC_CPU_f,
    914     _BCM_TR_L2X_MEMACC_DST_DISCARD_f,
    915     _BCM_TR_L2X_MEMACC_SRC_DISCARD_f,
    916     _BCM_TR_L2X_MEMACC_SCP_f,
    917     _BCM_TR_L2X_MEMACC_STATIC_BIT_f,
    918     _BCM_TR_L2X_MEMACC_LIMIT_COUNTED_f,
    919     _BCM_TR_L2X_MEMACC_PENDING_f,
    920     _BCM_TR_L2X_MEMACC_HITDA_f,
    921     _BCM_TR_L2X_MEMACC_HITSA_f,
    922     _BCM_TR_L2X_MEMACC_LOCAL_SA_f,
    923     _BCM_TR_L2X_MEMACC_REMOTE_f,
    924     _BCM_TR_L2X_MEMACC_DESTINATION_f,
    925     _BCM_TR_L2X_MEMACC_T_f,
    926     _BCM_TR_L2X_MEMACC_L3_f,
    927     _BCM_TR_L2X_MEMACC_RPE_f,
    928     _BCM_TR_L2X_MEMACC_NUM
    929 } _bcm_tr_l2x_memacc_field_t;
    930 
    931 static soc_memacc_t *_bcm_tr_l2x_memacc[BCM_UNITS_MAX];
    932 static soc_field_t   _bcm_tr_l2x_fields[] = {
    933     VALIDf,
    934     KEY_TYPEf,
    935     MAC_ADDRf,
    936     VFIf,
    937     VLAN_IDf,
    938     L2MC_PTRf,
    939     VPG_TYPEf,
    940     DEST_TYPEf,
    941     TGIDf,
    942     REMOTE_TRUNKf,
    943     PORT_NUMf,
    944     MODULE_IDf,
    945     CLASS_IDf,
    946     MAC_BLOCK_INDEXf,
    947     PRIf,
    948     CPUf,
    949     DST_DISCARDf,
    950     SRC_DISCARDf,
    951     SCPf,
    952     STATIC_BITf,
    953     LIMIT_COUNTEDf,
    954     PENDINGf,
    955     HITDAf,
    956     HITSAf,
    957     LOCAL_SAf,
    958     REMOTEf,
    959     DESTINATIONf,
    960     Tf,
    961     L3f,
    962     RPEf,
    963 };
    964 
    965 #define _BCM_L2X_MEMACC_FIELD(_u_, _f_) \
    966             (&_bcm_tr_l2x_memacc[_u_][_BCM_TR_L2X_MEMACC_##_f_])
    967 
    968 #define _BCM_L2X_MEMACC_FIELD_VALID(_u_, _f_) \
    969             SOC_MEMACC_VALID(_BCM_L2X_MEMACC_FIELD(_u_, _f_))
    970 
    971 #define _BCM_L2X_MEMACC_FIELD32_GET(_u_, _entBuf_, _f_) \
    972             soc_memacc_field32_get(_BCM_L2X_MEMACC_FIELD(_u_, _f_), _entBuf_)
    973 
    974 #define _BCM_L2X_MEMACC_FIELD32_SET(_u_, _entBuf_, _f_, _v_) \
    975             soc_memacc_field32_set(_BCM_L2X_MEMACC_FIELD(_u_, _f_), _entBuf_, \
    976                                    _v_)
    977 
    978 #if defined(BCM_TRIDENT2_SUPPORT)
    979 
    980 typedef enum _bcm_td2_l2hit_mem_e {
    981     _BCM_TD2_L2HITDA_X,
    982     _BCM_TD2_L2HITDA_Y,
    983     _BCM_TD2_L2HITSA_X,
    984     _BCM_TD2_L2HITSA_Y,
    985     _BCM_TD2_L2HIT_MEM_NUM
    986 } _bcm_td2_l2hit_mem_t;
    987 
    988 typedef enum _bcm_td2_l2hit_field_e {
    989     _BCM_TD2_L2HITDA_HITDA_f_0,
    990     _BCM_TD2_L2HITDA_HITDA_f_1,
    991     _BCM_TD2_L2HITDA_HITDA_f_2,
    992     _BCM_TD2_L2HITDA_HITDA_f_3,
    993     _BCM_TD2_L2HITSA_HITSA_f_0,
    994     _BCM_TD2_L2HITSA_HITSA_f_1,
    995     _BCM_TD2_L2HITSA_HITSA_f_2,
    996     _BCM_TD2_L2HITSA_HITSA_f_3,
    997     _BCM_TD2_L2HITSA_LOCAL_SA_f_0,
    998     _BCM_TD2_L2HITSA_LOCAL_SA_f_1,
    999     _BCM_TD2_L2HITSA_LOCAL_SA_f_2,
   1000     _BCM_TD2_L2HITSA_LOCAL_SA_f_3,
   1001     _BCM_TD2_L2HIT_FIELD_NUM
   1002 } _bcm_td2_l2hit_field_t;
   1003 
   1004 
   1005 static soc_memacc_t *_td2_l2hit_memacc[BCM_UNITS_MAX][_BCM_TD2_L2HIT_MEM_NUM];
   1006 
   1007 #define _TD2_L2HIT_MEM(_u_, _m_, _p_) \
   1008             (_BCM_TD2_##_m_##_X + (_p_))
   1009 
   1010 #define _TD2_L2HIT_FIELD(_u_, _m_,_f_, _i_) \
   1011             (_BCM_TD2_##_m_##_##_f_##_0 + (_i_))
   1012 
   1013 #define _TD2_L2HIT_MEMACC_FIELD(_u_, _mem_, _fld_) \
   1014             (&_td2_l2hit_memacc[_u_][_mem_][_fld_])
   1015 
   1016 #define _TD2_L2HIT_MEMACC_FIELD32_GET(_u_, _mem_, _entBuf_, _fld_) \
   1017             soc_memacc_field32_get(_TD2_L2HIT_MEMACC_FIELD(_u_, _mem_, _fld_), \
   1018                                    _entBuf_)
   1019 
   1020 #endif /* BCM_TRIDENT2_SUPPORT */
   1021 
   1022 STATIC int
   1023 _bcm_tr_l2_memacc_init(int unit)
   1024 {
   1025     int rv, i;
   1026     int alloc_size;
   1027 
   1028     if (_bcm_tr_l2x_memacc[unit] != NULL) {
   1029         sal_free(_bcm_tr_l2x_memacc[unit]);
   1030     }
   1031     alloc_size = sizeof(soc_memacc_t) * _BCM_TR_L2X_MEMACC_NUM;
   1032     _bcm_tr_l2x_memacc[unit] = sal_alloc(alloc_size, "L2 memacc");
   1033     if (_bcm_tr_l2x_memacc[unit] == NULL) {
   1034         return BCM_E_MEMORY;
   1035     }
   1036     sal_memset(_bcm_tr_l2x_memacc[unit], 0, alloc_size);
   1037 
   1038     for (i = 0; i < _BCM_TR_L2X_MEMACC_NUM; i++) {
   1039         rv = soc_memacc_init(unit, L2Xm, _bcm_tr_l2x_fields[i], 
   1040                              &_bcm_tr_l2x_memacc[unit][i]);
   1041         if (BCM_FAILURE(rv)) {
   1042             SOC_MEMACC_INVALID_SET(&_bcm_tr_l2x_memacc[unit][i]);
   1043         }
   1044     }
   1045 
   1046 #if defined(BCM_TRIDENT2_SUPPORT)
   1047     if (SOC_IS_TRIDENT2(unit) || SOC_IS_TITAN2(unit)
   1048         || SOC_IS_TD2P_TT2P(unit)) {
   1049         int m, f;
   1050         static soc_mem_t   _bcm_td2_l2hit_mems[] = {
   1051             L2_HITDA_ONLY_Xm,
   1052             L2_HITDA_ONLY_Ym,
   1053             L2_HITSA_ONLY_Xm,
   1054             L2_HITSA_ONLY_Ym,
   1055         };
   1056         static soc_field_t   _bcm_td2_l2hit_fields[] = {
   1057             HITDA_0f, HITDA_1f, HITDA_2f, HITDA_3f,
   1058             HITSA_0f, HITSA_1f, HITSA_2f, HITSA_3f,
   1059             LOCAL_SA_0f, LOCAL_SA_1f, LOCAL_SA_2f, LOCAL_SA_3f,
   1060         };
   1061 
   1062         for (m = 0; m < _BCM_TD2_L2HIT_MEM_NUM; m++) {
   1063             if (_td2_l2hit_memacc[unit][m] != NULL) {
   1064                 sal_free(_td2_l2hit_memacc[unit][m]);
   1065             }
   1066             alloc_size = sizeof(soc_memacc_t) * _BCM_TD2_L2HIT_FIELD_NUM;
   1067             _td2_l2hit_memacc[unit][m] = sal_alloc(alloc_size, "L2hit memacc");
   1068             if (_td2_l2hit_memacc[unit][m] == NULL) {
   1069                 sal_free(_bcm_tr_l2x_memacc[unit]);
   1070                 _bcm_tr_l2x_memacc[unit] = NULL;
   1071                 return BCM_E_MEMORY;
   1072             }
   1073             
   1074             for (f = 0; f < _BCM_TD2_L2HIT_FIELD_NUM; f++) {
   1075                 rv = soc_memacc_init(unit, _bcm_td2_l2hit_mems[m], 
   1076                                      _bcm_td2_l2hit_fields[f], 
   1077                                      &_td2_l2hit_memacc[unit][m][f]);
   1078                 if (BCM_FAILURE(rv)) {
   1079                     SOC_MEMACC_INVALID_SET(&_td2_l2hit_memacc[unit][m][f]);
   1080                 }
   1081             }
   1082         }
   1083     }
   1084 #endif
   1085 
   1086     return BCM_E_NONE;
   1087 }
   1088 
   1089 STATIC int
   1090 _bcm_tr_l2_memacc_deinit(int unit)
   1091 {
   1092     if (_bcm_tr_l2x_memacc[unit] != NULL) {
   1093         sal_free(_bcm_tr_l2x_memacc[unit]);
   1094         _bcm_tr_l2x_memacc[unit] = NULL;
   1095     }
   1096 
   1097 #if defined(BCM_TRIDENT2_SUPPORT)
   1098     if (SOC_IS_TRIDENT2(unit) || SOC_IS_TITAN2(unit)
   1099         || SOC_IS_TD2P_TT2P(unit)) {
   1100         int m;
   1101         for (m = 0; m < _BCM_TD2_L2HIT_MEM_NUM; m++) {
   1102             if (_td2_l2hit_memacc[unit][m] != NULL) {
   1103                 sal_free(_td2_l2hit_memacc[unit][m]);
   1104                 _td2_l2hit_memacc[unit][m] = NULL;
   1105             }
   1106         }
   1107     }
   1108 #endif
   1109     
   1110     return BCM_E_NONE;
   1111 }
   1112 
   1113 /*
   1114  * Function:
   1115  *      _bcm_tr_l2_from_l2x
   1116  * Purpose:
   1117  *      Convert a Triumph L2X entry to an L2 API data structure
   1118  * Parameters:
   1119  *      unit        Unit number
   1120  *      l2addr      (OUT) L2 API data structure
   1121  *      l2x_entry   Triumph L2X entry
   1122  */
   1123 int
   1124 _bcm_tr_l2_from_l2x(int unit, bcm_l2_addr_t *l2addr, l2x_entry_t *l2x_entry)
   1125 {
   1126     int l2mc_index, mb_index, vfi, rval;
   1127 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   1128     int my_station_config = 0;
   1129 #endif
   1130     soc_memacc_t *memacc;
   1131 #if defined(INCLUDE_L3)
   1132     int vp = -1;
   1133 #endif /* INCLUDE_L3 */
   1134     int vfi_multicast = 0;
   1135 #if defined(BCM_GREYHOUND2_SUPPORT) && defined(INCLUDE_L3)
   1136     int dest_type_is_nhi = 0;
   1137     int ecmp = 0, nh_ecmp_index = 0;
   1138 #endif /* BCM_GREYHOUND2_SUPPORT && INCLUDE_L3 */
   1139 #if defined(BCM_TSN_SUPPORT)
   1140     uint32 hw_id = 0;
   1141     bcm_tsn_flow_t tsn_flow_id = 0;
   1142 #if defined(BCM_TSN_SR_SUPPORT)
   1143     bcm_tsn_sr_flow_t sr_flow_id = 0;
   1144     int mp_index = 0; /* TSN SR MAC Proxy profile index */
   1145     bcm_pbmp_t mp_pbmp;
   1146 #endif /* BCM_TSN_SR_SUPPORT */
   1147 #endif /* BCM_TSN_SUPPORT */
   1148     int vfi_fid_used = 0;
   1149 
   1150     sal_memset(l2addr, 0, sizeof(*l2addr));
   1151 
   1152 #ifdef BCM_TRIDENT3_SUPPORT
   1153     if (soc_feature(unit, soc_feature_flex_flow) &&
   1154        (soc_mem_field32_get(unit, L2Xm, l2x_entry, KEY_TYPEf) >=
   1155         TD3_L2_HASH_KEY_TYPE_COUNT)) {
   1156 
   1157         rval = _bcm_td3_flex_l2_from_l2x(unit, l2addr, l2x_entry, &mb_index);
   1158 
   1159         if (mb_index) {
   1160             BCM_PBMP_ASSIGN(l2addr->block_bitmap,
   1161                             _mbi_entries[unit][mb_index].mb_pbmp);
   1162         }
   1163         return rval;
   1164     }
   1165 #endif
   1166 
   1167 #if defined(BCM_GREYHOUND2_SUPPORT) && defined(INCLUDE_L3)
   1168     if (soc_feature(unit, soc_feature_vxlan_lite_riot)) {
   1169         if (_BCM_L2X_MEMACC_FIELD32_GET(unit, l2x_entry, KEY_TYPE_f) ==
   1170             GH2_L2_HASH_KEY_TYPE_VFI_MULTICAST) {
   1171             vfi_multicast = 1;
   1172         }
   1173     }
   1174 #endif /* BCM_GREYHOUND2_SUPPORT && INCLUDE_L3 */
   1175 
   1176     memacc = _BCM_L2X_MEMACC_FIELD(unit, MAC_ADDR_f);
   1177     soc_memacc_mac_addr_get(memacc, l2x_entry, l2addr->mac);
   1178 
   1179 #if defined(BCM_TRIDENT3_SUPPORT)
   1180     if (soc_feature(unit, soc_feature_pvlan_on_vfi)) {
   1181         int enable;
   1182 
   1183         BCM_IF_ERROR_RETURN(
   1184             bcm_esw_switch_control_get(unit, bcmSwitchSharedVlanEnable, &enable));
   1185         if (enable) {
   1186             vfi_fid_used = 1;
   1187         }
   1188     }
   1189 #endif
   1190 
   1191     if (((_BCM_L2X_MEMACC_FIELD32_GET(unit, l2x_entry, KEY_TYPE_f) ==
   1192         TR_L2_HASH_KEY_TYPE_VFI) || (vfi_multicast)) && !vfi_fid_used) {
   1193         vfi = _BCM_L2X_MEMACC_FIELD32_GET(unit, l2x_entry, VFI_f);
   1194         COMPILER_REFERENCE(vfi);
   1195         /* VPLS or MIM VPN */
   1196 #if defined(INCLUDE_L3)
   1197         if (_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeMpls)) {
   1198             _BCM_MPLS_VPN_SET(l2addr->vid, _BCM_MPLS_VPN_TYPE_VPLS, vfi);
   1199         } else if (_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeMim)) {
   1200             _BCM_MIM_VPN_SET(l2addr->vid, _BCM_MIM_VPN_TYPE_MIM, vfi);
   1201         } else  if (_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeL2Gre)) {
   1202 #if defined(BCM_TRIUMPH3_SUPPORT)
   1203                 if (soc_feature(unit, soc_feature_l2gre)) {
   1204                     BCM_IF_ERROR_RETURN
   1205                         (_bcm_tr3_l2gre_vpn_get(unit, vfi, &l2addr->vid));
   1206                 }
   1207 #endif
   1208         } else if (_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeVxlan)) {
   1209 #if defined(BCM_TRIDENT2_SUPPORT)
   1210                 if (soc_feature(unit, soc_feature_vxlan)) {
   1211                     BCM_IF_ERROR_RETURN(
   1212                       _bcm_td2_vxlan_vpn_get(unit, vfi, &l2addr->vid));
   1213                 }
   1214 #endif
   1215         } else if (_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeFlow)) {
   1216 #if defined(BCM_TRIDENT3_SUPPORT)
   1217                 if (soc_feature(unit, soc_feature_flex_flow)) {
   1218                     BCM_IF_ERROR_RETURN(
   1219                       bcmi_esw_flow_vpnid_get(unit, vfi, &l2addr->vid));
   1220                 }
   1221 #endif
   1222 #if defined(BCM_GREYHOUND2_SUPPORT)
   1223         } else if (soc_feature(unit, soc_feature_vxlan_lite)) {
   1224             if (bcmi_gh2_vxlan_vfi_used_get(unit, vfi)) {
   1225                 BCM_IF_ERROR_RETURN(
   1226                     bcmi_gh2_vxlan_vfi_to_vpn_get(unit, vfi, &l2addr->vid));
   1227                 /* Get DEST_TYPEf value for VFI view */
   1228                 dest_type_is_nhi = _BCM_L2X_MEMACC_FIELD32_GET(unit, l2x_entry,
   1229                                                                DEST_TYPE_f);
   1230             }
   1231 #endif /* BCM_GREYHOUND2_SUPPORT */
   1232         }
   1233 #endif /* INCLUDE_L3 */
   1234     } else {  
   1235         l2addr->vid = _BCM_L2X_MEMACC_FIELD32_GET(unit, l2x_entry, VLAN_ID_f); 
   1236     }
   1237 
   1238     if (BCM_MAC_IS_MCAST(l2addr->mac)) {
   1239 #if defined(BCM_MONTEREY_SUPPORT) && defined(INCLUDE_L3)
   1240         int dest_ipmc_index = 0;
   1241         dest_ipmc_index = _BCM_L2X_MEMACC_FIELD32_GET(unit, l2x_entry, DESTINATION_f);
   1242         if ((soc_feature(unit,soc_feature_roe) ||
   1243              soc_feature(unit,soc_feature_roe_custom)) &&
   1244             (_BCM_L2X_MEMACC_FIELD32_GET(unit, l2x_entry, DEST_TYPE_f) == 3)) {
   1245             l2addr->flags2 |= BCM_L2_FLAGS2_L3_MULTICAST;
   1246             _BCM_MULTICAST_GROUP_SET(l2addr->l3mc_group,
   1247                                      _BCM_MULTICAST_TYPE_L3,
   1248                                       dest_ipmc_index);
   1249         } else
   1250 #endif /* BCM_MONTEREY_SUPPORT && INCLUDE_L3 */
   1251         {
   1252         l2addr->flags |= BCM_L2_MCAST;
   1253         if (soc_feature(unit, soc_feature_generic_dest)) {
   1254             uint32 dest_type;
   1255             l2mc_index = soc_mem_field32_dest_get(unit, L2Xm, l2x_entry,
   1256                             DESTINATIONf, &dest_type);
   1257             if (dest_type != SOC_MEM_FIF_DEST_L2MC) {
   1258                 l2mc_index = 0;
   1259             }
   1260         } else {
   1261         l2mc_index = _BCM_L2X_MEMACC_FIELD32_GET(unit, l2x_entry, L2MC_PTR_f);
   1262         }
   1263         if (_BCM_L2X_MEMACC_FIELD_VALID(unit, VPG_TYPE_f) &&
   1264             _BCM_L2X_MEMACC_FIELD32_GET(unit, l2x_entry, VPG_TYPE_f)) {
   1265             if (_BCM_L2X_MEMACC_FIELD32_GET(unit, l2x_entry, KEY_TYPE_f) ==
   1266                                                TR_L2_HASH_KEY_TYPE_VFI) {
   1267                 vfi = _BCM_L2X_MEMACC_FIELD32_GET(unit, l2x_entry, VFI_f);
   1268                 /* VPLS, MIM, L2GRE, VXLAN multicast */
   1269 #if defined(INCLUDE_L3)
   1270                 if (_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeMpls)) {
   1271                     _BCM_MULTICAST_GROUP_SET(l2addr->l2mc_group,
   1272                             _BCM_MULTICAST_TYPE_VPLS, l2mc_index);
   1273                 } else if (_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeMim)) {
   1274                     _BCM_MULTICAST_GROUP_SET(l2addr->l2mc_group,
   1275                             _BCM_MULTICAST_TYPE_MIM, l2mc_index);
   1276                 } else  if (_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeVxlan)) {
   1277                     _BCM_MULTICAST_GROUP_SET(l2addr->l2mc_group,
   1278                             _BCM_MULTICAST_TYPE_VXLAN, l2mc_index);
   1279                 } else  if (_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeL2Gre)) {
   1280                     _BCM_MULTICAST_GROUP_SET(l2addr->l2mc_group,
   1281                             _BCM_MULTICAST_TYPE_L2GRE, l2mc_index);
   1282                 }
   1283 #endif
   1284             } else {
   1285 #if defined(INCLUDE_L3)
   1286                 int rv;
   1287                 rv = _bcm_tr_multicast_ipmc_group_type_get(unit,
   1288                             l2mc_index, &l2addr->l2mc_group);
   1289                 if (BCM_E_NOT_FOUND == rv) {
   1290                     /* Assume subport multicast */
   1291                     _BCM_MULTICAST_GROUP_SET(l2addr->l2mc_group,
   1292                             _BCM_MULTICAST_TYPE_SUBPORT, l2mc_index);
   1293                 } else if (BCM_FAILURE(rv)) {
   1294                     return rv;
   1295                 }
   1296 #endif
   1297             }
   1298 #if defined(BCM_GREYHOUND2_SUPPORT) && defined(INCLUDE_L3)
   1299         } else if (soc_feature(unit, soc_feature_vxlan_lite)) {
   1300             if ((dest_type_is_nhi == 0x4) || (dest_type_is_nhi == 0x5)) {
   1301                 if (dest_type_is_nhi == 0x5) {
   1302                     ecmp = 1; /* ECMP */
   1303                 } else {
   1304                     ecmp = 0; /* NHI */
   1305                 }
   1306 
   1307                 nh_ecmp_index = soc_L2Xm_field32_get(unit, l2x_entry,
   1308                                                      NHI_ECMPf);
   1309 
   1310                 BCM_IF_ERROR_RETURN(
   1311                     bcmi_gh2_vxlan_port_from_nh_ecmp_index(unit, ecmp,
   1312                                                            nh_ecmp_index,
   1313                                                            &vp));
   1314                 BCM_GPORT_VXLAN_PORT_ID_SET(l2addr->port, vp);
   1315             } else if (dest_type_is_nhi == 0x3) {
   1316                 _BCM_MULTICAST_GROUP_SET(l2addr->l2mc_group,
   1317                                          _BCM_MULTICAST_TYPE_VXLAN,
   1318                                          l2mc_index);
   1319             } else {
   1320                 l2addr->l2mc_group = l2mc_index;
   1321                 /* Translate l2mc index */
   1322                 BCM_IF_ERROR_RETURN(
   1323                     bcm_esw_switch_control_get(unit, bcmSwitchL2McIdxRetType,
   1324                                                &rval));
   1325                 if (rval) {
   1326                    _BCM_MULTICAST_GROUP_SET(l2addr->l2mc_group,
   1327                                             _BCM_MULTICAST_TYPE_L2,
   1328                                             l2addr->l2mc_group);
   1329                 }
   1330             }
   1331 #endif /* BCM_GREYHOUND2_SUPPORT && INCLUDE_L3 */
   1332         } else {
   1333             l2addr->l2mc_group = l2mc_index;
   1334             /* Translate l2mc index */
   1335             BCM_IF_ERROR_RETURN(
   1336                 bcm_esw_switch_control_get(unit, bcmSwitchL2McIdxRetType, &rval));
   1337             if (rval) {
   1338                _BCM_MULTICAST_GROUP_SET(l2addr->l2mc_group, _BCM_MULTICAST_TYPE_L2,
   1339                                                                     l2addr->l2mc_group);
   1340             }
   1341         }
   1342         }
   1343     } else {
   1344         _bcm_gport_dest_t       dest;
   1345         int                     dest_type_is_trunk = 0;
   1346         int                     isGport = 0;
   1347 #if defined(INCLUDE_L3)
   1348         int                     dest_type_is_dvp = 0;
   1349         uint32 dest_type = SOC_MEM_FIF_DEST_INVALID;
   1350 #endif
   1351         uint32 dest_value = 0;
   1352 #if defined(BCM_MONTEREY_SUPPORT) && defined(INCLUDE_L3)
   1353         int                     dest_type_is_roe_nhi = 0;
   1354         uint32                  dest_nhi = 0;
   1355         int                     nh_roe_idx = -1;
   1356 #endif /* BCM_MONTEREY_SUPPORT && INCLUDE_L3 */
   1357 
   1358         _bcm_gport_dest_t_init(&dest);
   1359 #if defined(INCLUDE_L3)
   1360         if (soc_feature(unit, soc_feature_generic_dest)) {
   1361             dest_value = soc_mem_field32_dest_get(unit, L2Xm, l2x_entry, 
   1362                             DESTINATIONf, &dest_type);
   1363             if (dest_type == SOC_MEM_FIF_DEST_DVP) {
   1364                 dest_type_is_dvp = 1;
   1365             } else if (dest_type == SOC_MEM_FIF_DEST_LAG) {
   1366                 dest_type_is_trunk = 1;
   1367             }
   1368         } else
   1369 #endif /* INCLUDE_L3 */
   1370         {
   1371 #if defined(INCLUDE_L3)
   1372             if (_BCM_L2X_MEMACC_FIELD32_GET(unit, l2x_entry,
   1373                                             DEST_TYPE_f) == 2) {
   1374                 dest_type_is_dvp = 1;
   1375             }
   1376 #endif /* INCLUDE_L3 */
   1377 
   1378             dest_type_is_trunk =
   1379                 _BCM_L2X_MEMACC_FIELD32_GET(unit, l2x_entry, T_f);
   1380 #if defined(BCM_MONTEREY_SUPPORT) && defined(INCLUDE_L3)
   1381             if (_BCM_L2X_MEMACC_FIELD32_GET(unit, l2x_entry, DEST_TYPE_f) == 1) {
   1382                 dest_nhi = _BCM_L2X_MEMACC_FIELD32_GET(unit, l2x_entry, DESTINATION_f);
   1383                 if ((dest_nhi & _BCM_L2_DEST_TYPE_MASK) == _BCM_L2_DEST_TYPE_NHI) {
   1384                     dest_type_is_roe_nhi = 1;
   1385                     dest_type_is_trunk = 0;
   1386                 }
   1387             }
   1388 #endif
   1389         }
   1390 
   1391 #if defined(INCLUDE_L3)
   1392         if (dest_type_is_dvp) {
   1393             if (soc_feature(unit, soc_feature_generic_dest)) {
   1394                 vp = dest_value;
   1395             } else {
   1396             vp = _BCM_L2X_MEMACC_FIELD32_GET(unit, l2x_entry, DESTINATION_f);
   1397             }
   1398             if (_BCM_L2X_MEMACC_FIELD32_GET(unit, l2x_entry, KEY_TYPE_f) ==
   1399                     TR_L2_HASH_KEY_TYPE_VFI) {
   1400                 /* MPLS/MiM virtual port unicast */
   1401                 if (_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) {
   1402                     dest.mpls_id = vp;
   1403                     dest.gport_type = _SHR_GPORT_TYPE_MPLS_PORT;
   1404                     isGport=1;
   1405                 } else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeMim)) {
   1406                     dest.mim_id = vp;
   1407                     dest.gport_type = _SHR_GPORT_TYPE_MIM_PORT;
   1408                     isGport=1;
   1409                 } else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeVxlan)) {
   1410                     dest.vxlan_id  = vp;
   1411                     dest.gport_type = _SHR_GPORT_TYPE_VXLAN_PORT;
   1412                     isGport=1;
   1413                 } else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeL2Gre)) {
   1414                     dest.l2gre_id  = vp;
   1415                     dest.gport_type = _SHR_GPORT_TYPE_L2GRE_PORT;
   1416                     isGport=1;
   1417                 } else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeFlow)) {
   1418                     dest.flow_id  = vp;
   1419                     dest.gport_type = _SHR_GPORT_TYPE_FLOW_PORT;
   1420                     isGport=1;
   1421                 } else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeVpLag)) {
   1422                     l2addr->flags |= BCM_L2_TRUNK_MEMBER;
   1423                     BCM_IF_ERROR_RETURN(_bcm_esw_trunk_vp_lag_vp_to_tid(unit,
   1424                                 vp, &l2addr->tgid));
   1425                     dest.tgid = l2addr->tgid;
   1426                     dest.gport_type = _SHR_GPORT_TYPE_TRUNK;
   1427                     BCM_IF_ERROR_RETURN(bcm_esw_switch_control_get(unit,
   1428                                 bcmSwitchUseGport, &isGport));
   1429                 } else {
   1430                     /* L2 entries with Stale VPN */
   1431                     dest.gport_type = BCM_GPORT_INVALID;
   1432                     isGport=0;
   1433                 }
   1434             } else {
   1435                 /* Subport/WLAN unicast */
   1436 #if defined(BCM_SCORPION_SUPPORT) && defined(INCLUDE_L3)
   1437                 if (SOC_IS_SC_CQ(unit)) {
   1438                     /* Scorpion uses index to L3_NEXT_HOP as VPG */
   1439                     int grp;
   1440 
   1441                     _SC_SUBPORT_VPG_FIND(unit, vp, grp);
   1442                     if ((vp = grp) == -1) {
   1443                         LOG_ERROR(BSL_LS_BCM_L2,
   1444                                   (BSL_META_U(unit,
   1445                                               "Can not find entry for VPG\n")));
   1446                     }
   1447                     dest.subport_id = vp;
   1448                     dest.gport_type = _SHR_GPORT_TYPE_SUBPORT_GROUP;
   1449                     isGport=1;
   1450                 } else
   1451 #endif /* BCM_SCORPION_SUPPORT && INCLUDE_L3 */
   1452                 {
   1453                     if (_bcm_vp_used_get(unit, vp, _bcmVpTypeSubport)) {
   1454                         dest.subport_id = vp;
   1455                         dest.gport_type = _SHR_GPORT_TYPE_SUBPORT_GROUP;
   1456                         isGport=1;
   1457                     } else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeWlan)) {
   1458                         dest.wlan_id = vp;
   1459                         dest.gport_type = _SHR_GPORT_TYPE_WLAN_PORT;
   1460                         isGport=1;
   1461                     } else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeVlan)) {
   1462                         dest.vlan_vp_id = vp;
   1463                         dest.gport_type = _SHR_GPORT_TYPE_VLAN_PORT;
   1464                         isGport=1;
   1465                     } else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeNiv)) {
   1466                         dest.niv_id = vp;
   1467                         dest.gport_type = _SHR_GPORT_TYPE_NIV_PORT;
   1468                         isGport=1;
   1469                     } else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeTrill)) {
   1470                         dest.trill_id  = vp;
   1471                         dest.gport_type = _SHR_GPORT_TYPE_TRILL_PORT;
   1472                         isGport=1;
   1473                     } else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeExtender)) {
   1474                         dest.extender_id = vp;
   1475                         dest.gport_type = _SHR_GPORT_TYPE_EXTENDER_PORT;
   1476                         isGport=1;
   1477                     } else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeVpLag)) {
   1478                         l2addr->flags |= BCM_L2_TRUNK_MEMBER;
   1479                         BCM_IF_ERROR_RETURN(_bcm_esw_trunk_vp_lag_vp_to_tid(unit,
   1480                                     vp, &l2addr->tgid));
   1481                         dest.tgid = l2addr->tgid;
   1482                         dest.gport_type = _SHR_GPORT_TYPE_TRUNK;
   1483                         BCM_IF_ERROR_RETURN(bcm_esw_switch_control_get(unit,
   1484                                     bcmSwitchUseGport, &isGport));
   1485                     } else {
   1486                         /* L2 entries with Stale Gport */
   1487                         dest.gport_type = BCM_GPORT_INVALID;
   1488                         isGport=0;
   1489                     }
   1490                 }
   1491             }
   1492         } else
   1493 #if defined(BCM_GREYHOUND2_SUPPORT)
   1494         if (((dest_type_is_nhi == 0x4) || (dest_type_is_nhi == 0x5)) &&
   1495             (soc_feature(unit, soc_feature_vxlan_lite))) {
   1496             if (dest_type_is_nhi == 0x5) {
   1497                 ecmp = 1; /* ECMP */
   1498             } else {
   1499                 ecmp = 0; /* NHI */
   1500             }
   1501 
   1502             nh_ecmp_index = soc_L2Xm_field32_get(unit, l2x_entry, NHI_ECMPf);
   1503 
   1504             BCM_IF_ERROR_RETURN(
   1505                 bcmi_gh2_vxlan_port_from_nh_ecmp_index(unit, ecmp,
   1506                                                        nh_ecmp_index, &vp));
   1507             dest.vxlan_id = vp;
   1508             dest.gport_type = _SHR_GPORT_TYPE_VXLAN_PORT;
   1509             isGport = 1;
   1510         } else
   1511 #endif /* BCM_GREYHOUND2_SUPPORT */
   1512 #if defined(BCM_MONTEREY_SUPPORT) && defined(INCLUDE_L3)
   1513         if (dest_type_is_roe_nhi) {
   1514             l2addr->flags2 |= BCM_L2_FLAGS2_ROE_NHI;
   1515             nh_roe_idx = (dest_nhi & (~_BCM_L2_DEST_TYPE_MASK));
   1516             l2addr->egress_if = BCM_XGS3_EGRESS_IDX_MIN(unit) + nh_roe_idx;
   1517         } else
   1518 #endif /* BCM_MONTEREY_SUPPORT && INCLUDE_L3 */
   1519 #endif /* INCLUDE_L3 */
   1520         if (dest_type_is_trunk) {
   1521             /* Trunk group */
   1522             int psc = 0; /* psc is dummy, not used */
   1523             l2addr->flags |= BCM_L2_TRUNK_MEMBER;
   1524             if (soc_feature(unit, soc_feature_generic_dest)) {
   1525                 l2addr->tgid = dest_value & SOC_MEM_FIF_DGPP_TGID_MASK;
   1526             } else {
   1527             l2addr->tgid = _BCM_L2X_MEMACC_FIELD32_GET(unit, l2x_entry, TGID_f);
   1528             if (_BCM_L2X_MEMACC_FIELD32_GET(unit, l2x_entry, REMOTE_TRUNK_f)) {
   1529                 l2addr->flags |= BCM_L2_REMOTE_TRUNK;
   1530             }
   1531             }
   1532 
   1533             bcm_esw_trunk_psc_get(unit, l2addr->tgid, &psc);
   1534             dest.tgid = l2addr->tgid;
   1535             dest.gport_type = _SHR_GPORT_TYPE_TRUNK;
   1536             BCM_IF_ERROR_RETURN(
   1537                 bcm_esw_switch_control_get(unit, bcmSwitchUseGport, &isGport));
   1538 #if defined(BCM_TSN_SR_SUPPORT)
   1539         } else if (soc_feature(unit, soc_feature_tsn_sr) &&
   1540             soc_L2Xm_field32_get(unit, l2x_entry, SR_DUPLICATE_FORWARDINGf)) {
   1541             /*
   1542              * Indicates that the destination is a
   1543              * Seamless Redundancy Duplicate port and Unicast packets must be
   1544              * forwarded as Multicast (DEST_TYPE=L2MC)
   1545              */
   1546             l2addr->flags |= BCM_L2_MCAST;
   1547             l2mc_index = _BCM_L2X_MEMACC_FIELD32_GET(unit,
   1548                                                      l2x_entry, L2MC_PTR_f);
   1549 
   1550             l2addr->l2mc_group = l2mc_index;
   1551             /* Translate l2mc index */
   1552             BCM_IF_ERROR_RETURN(
   1553                 bcm_esw_switch_control_get(unit,
   1554                                            bcmSwitchL2McIdxRetType, &rval));
   1555             if (rval) {
   1556                 _BCM_MULTICAST_GROUP_SET(l2addr->l2mc_group,
   1557                                          _BCM_MULTICAST_TYPE_L2,
   1558                                          l2addr->l2mc_group);
   1559             }
   1560 #endif /* BCM_TSN_SR_SUPPORT */
   1561         } else {
   1562             bcm_module_t    mod_in, mod_out;
   1563             bcm_port_t      port_in, port_out;
   1564 
   1565             if (soc_feature(unit, soc_feature_generic_dest)) {
   1566                 port_in = dest_value & SOC_MEM_FIF_DGPP_PORT_MASK;
   1567                 mod_in = (dest_value & SOC_MEM_FIF_DGPP_MOD_ID_MASK) >>
   1568                             SOC_MEM_FIF_DGPP_MOD_ID_SHIFT_BITS;
   1569             } else {
   1570             port_in = _BCM_L2X_MEMACC_FIELD32_GET(unit, l2x_entry, PORT_NUM_f);
   1571             mod_in  = _BCM_L2X_MEMACC_FIELD32_GET(unit, l2x_entry, MODULE_ID_f);
   1572             }
   1573             BCM_IF_ERROR_RETURN
   1574                 (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET,
   1575                                         mod_in, port_in, &mod_out, &port_out));
   1576             l2addr->modid = mod_out;
   1577             l2addr->port = port_out;
   1578             dest.port = l2addr->port;
   1579             dest.modid = l2addr->modid;
   1580             dest.gport_type = _SHR_GPORT_TYPE_MODPORT;
   1581             BCM_IF_ERROR_RETURN(
   1582                 bcm_esw_switch_control_get(unit, bcmSwitchUseGport, &isGport));
   1583         }
   1584 
   1585         if (isGport) {
   1586             BCM_IF_ERROR_RETURN(
   1587                 _bcm_esw_gport_construct(unit, &dest, &(l2addr->port)));
   1588         }
   1589     }
   1590 
   1591     if (_BCM_L2X_MEMACC_FIELD_VALID(unit, L3_f)) {
   1592         if (_BCM_L2X_MEMACC_FIELD32_GET(unit, l2x_entry, L3_f)) {
   1593             l2addr->flags |= BCM_L2_L3LOOKUP;
   1594         }
   1595     }
   1596 
   1597     if (SOC_CONTROL(unit)->l2x_group_enable) {
   1598         l2addr->group = _BCM_L2X_MEMACC_FIELD32_GET(unit, l2x_entry,
   1599                                                     CLASS_ID_f);
   1600     } else {
   1601         mb_index = _BCM_L2X_MEMACC_FIELD32_GET(unit, l2x_entry, 
   1602                                                MAC_BLOCK_INDEX_f);
   1603         if (mb_index) {
   1604             BCM_PBMP_ASSIGN(l2addr->block_bitmap,
   1605                             _mbi_entries[unit][mb_index].mb_pbmp);
   1606         }
   1607     }
   1608 
   1609     if (_BCM_L2X_MEMACC_FIELD32_GET(unit, l2x_entry, RPE_f)) {
   1610         l2addr->flags |= BCM_L2_SETPRI;
   1611     }
   1612 
   1613     l2addr->cos_dst = _BCM_L2X_MEMACC_FIELD32_GET(unit, l2x_entry, PRI_f);
   1614     l2addr->cos_src = _BCM_L2X_MEMACC_FIELD32_GET(unit, l2x_entry, PRI_f);
   1615 
   1616     if (SOC_CONTROL(unit)->l2x_group_enable) {
   1617         if (soc_feature(unit, soc_feature_overlaid_address_class) &&
   1618             !BCM_L2_PRE_SET(l2addr->flags)) {
   1619             l2addr->group |= (l2addr->cos_dst & 0xF) << 6;
   1620         }
   1621     } 
   1622 
   1623     if (_BCM_L2X_MEMACC_FIELD32_GET(unit, l2x_entry, CPU_f)) {
   1624         l2addr->flags |= BCM_L2_COPY_TO_CPU;
   1625     }
   1626 
   1627     if (_BCM_L2X_MEMACC_FIELD32_GET(unit, l2x_entry, DST_DISCARD_f)) {
   1628         l2addr->flags |= BCM_L2_DISCARD_DST;
   1629     }
   1630 
   1631     if (_BCM_L2X_MEMACC_FIELD32_GET(unit, l2x_entry, SRC_DISCARD_f)) {
   1632         l2addr->flags |= BCM_L2_DISCARD_SRC;
   1633     }
   1634 
   1635     if (_BCM_L2X_MEMACC_FIELD32_GET(unit, l2x_entry, SCP_f)) {
   1636         l2addr->flags |= BCM_L2_COS_SRC_PRI;
   1637     }
   1638 
   1639 
   1640     if (_BCM_L2X_MEMACC_FIELD32_GET(unit, l2x_entry, STATIC_BIT_f)) {
   1641         l2addr->flags |= BCM_L2_STATIC;
   1642     }
   1643 
   1644     if (_BCM_L2X_MEMACC_FIELD_VALID(unit, LIMIT_COUNTED_f)) {
   1645         if (!(l2addr->flags & (BCM_L2_L3LOOKUP | BCM_L2_MCAST |
   1646                                BCM_L2_STATIC | BCM_L2_LEARN_LIMIT))) {
   1647             if (!_BCM_L2X_MEMACC_FIELD32_GET(unit, l2x_entry,
   1648                                              LIMIT_COUNTED_f)) {
   1649                 l2addr->flags |= BCM_L2_LEARN_LIMIT_EXEMPT;
   1650             }
   1651         }
   1652     }
   1653 
   1654     if (_BCM_L2X_MEMACC_FIELD32_GET(unit, l2x_entry, PENDING_f)) {
   1655         l2addr->flags |= BCM_L2_PENDING;
   1656     }
   1657 
   1658     if (_BCM_L2X_MEMACC_FIELD32_GET(unit, l2x_entry, HITDA_f)) {
   1659         l2addr->flags |= BCM_L2_DES_HIT;
   1660         l2addr->flags |= BCM_L2_HIT;
   1661     }
   1662 
   1663     if (_BCM_L2X_MEMACC_FIELD32_GET(unit, l2x_entry, HITSA_f)) {
   1664         l2addr->flags |= BCM_L2_SRC_HIT;
   1665         l2addr->flags |= BCM_L2_HIT;
   1666     }
   1667 
   1668     if (_BCM_L2X_MEMACC_FIELD_VALID(unit, LOCAL_SA_f)) {
   1669         if (_BCM_L2X_MEMACC_FIELD32_GET(unit, l2x_entry, LOCAL_SA_f)) {
   1670             l2addr->flags |= BCM_L2_NATIVE;
   1671         }
   1672     }
   1673 
   1674     if (soc_feature(unit, soc_feature_mac_learn_limit)) {
   1675         if (_BCM_L2X_MEMACC_FIELD32_GET(unit, l2x_entry, REMOTE_f)) {
   1676             l2addr->flags |= BCM_L2_LEARN_LIMIT_EXEMPT_LOCAL;
   1677         }
   1678     }
   1679 
   1680 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   1681     my_station_config = soc_property_get(unit, spn_L2_ENTRY_USED_AS_MY_STATION, 0);
   1682     if (soc_feature(unit, soc_feature_l2_entry_used_as_my_station)
   1683         && my_station_config) {
   1684 #if defined(BCM_TRIDENT3_SUPPORT)
   1685          if (soc_feature(unit, soc_feature_mysta_profile)) {
   1686               bcm_l2_station_t station;
   1687               uint32 mysta_prof_id = 0;
   1688               uint32 dest_type = SOC_MEM_FIF_DEST_INVALID;
   1689               my_station_profile_2_entry_t entry_prof;
   1690 
   1691               sal_memset(&station, 0, sizeof(bcm_l2_station_t));
   1692               mysta_prof_id = soc_mem_field32_dest_get(unit, L2Xm, l2x_entry,
   1693                               DESTINATIONf, &dest_type);
   1694               if (dest_type == SOC_MEM_FIF_DEST_MYSTA) {
   1695                   BCM_IF_ERROR_RETURN(_bcm_l2_mysta_profile_entry_get(unit,
   1696                                       &entry_prof, 1, mysta_prof_id));
   1697                   _bcm_l2_mysta_entry_to_station(unit, &entry_prof, MY_STATION_PROFILE_2m, &station);
   1698                   l2addr->station_flags = station.flags;
   1699               } else {
   1700                   l2addr->station_flags = 0;
   1701               }
   1702           } else
   1703 #endif
   1704          {
   1705             if (_BCM_L2X_MEMACC_FIELD32_GET(unit, l2x_entry, DEST_TYPE_f) == 1) {
   1706                 uint32 dst = _BCM_L2X_MEMACC_FIELD32_GET(unit, l2x_entry,
   1707                                                          DESTINATION_f);
   1708 
   1709         if (_BCM_L2X_MEMACC_FIELD32_GET(unit, l2x_entry, DESTINATION_f)
   1710             & _BCM_L2_DEST_STATION_IPV4) {
   1711             l2addr->station_flags |= BCM_L2_STATION_IPV4;
   1712         }
   1713 
   1714         if (_BCM_L2X_MEMACC_FIELD32_GET(unit, l2x_entry, DESTINATION_f)
   1715             & _BCM_L2_DEST_STATION_IPV6) {
   1716             l2addr->station_flags |= BCM_L2_STATION_IPV6;
   1717         }
   1718 
   1719         if (_BCM_L2X_MEMACC_FIELD32_GET(unit, l2x_entry, DESTINATION_f)
   1720             & _BCM_L2_DEST_STATION_ARP_RARP) {
   1721             l2addr->station_flags |= BCM_L2_STATION_ARP_RARP;
   1722         }
   1723 
   1724         if (_BCM_L2X_MEMACC_FIELD32_GET(unit, l2x_entry, DESTINATION_f)
   1725             & _BCM_L2_DEST_STATION_OAM) {
   1726             l2addr->station_flags |= BCM_L2_STATION_OAM;
   1727         }
   1728 
   1729         if (_BCM_L2X_MEMACC_FIELD32_GET(unit, l2x_entry, DESTINATION_f)
   1730             & _BCM_L2_DEST_STATION_FCOE) {
   1731             l2addr->station_flags |= BCM_L2_STATION_FCOE;
   1732         }
   1733 
   1734         if (_BCM_L2X_MEMACC_FIELD32_GET(unit, l2x_entry, DESTINATION_f)
   1735             & _BCM_L2_DEST_STATION_IPV4_MCAST) {
   1736             l2addr->station_flags |= BCM_L2_STATION_IPV4_MCAST;
   1737         }
   1738 
   1739         if (_BCM_L2X_MEMACC_FIELD32_GET(unit, l2x_entry, DESTINATION_f)
   1740             & _BCM_L2_DEST_STATION_IPV6_MCAST) {
   1741             l2addr->station_flags |= BCM_L2_STATION_IPV6_MCAST;
   1742         }
   1743 
   1744                 if ((dst & _BCM_L2_DEST_TYPE_MASK) != _BCM_L2_DEST_TYPE_TRUNK) {
   1745                     l2addr->flags &= (~BCM_L2_TRUNK_MEMBER);
   1746                     l2addr->tgid = 0;
   1747                 }
   1748             }
   1749         }
   1750     }
   1751 #endif /* BCM_TRIDENT2PLUS_SUPPORT */
   1752 
   1753 #if defined(BCM_TSN_SUPPORT)
   1754     if (soc_feature(unit, soc_feature_tsn)) {
   1755         /*
   1756          * Provides TSN circuit ID for this packet:
   1757          *  - 0 = Invalid TSN_CIRCUIT_ID, Valid only for MAC-DA lookup
   1758          */
   1759         hw_id = soc_L2Xm_field32_get(unit, l2x_entry, TSN_CIRCUIT_IDf);
   1760         if (hw_id != 0) {
   1761             /* Convert hardware TSN flow ID to software TSN flow ID */
   1762             BCM_IF_ERROR_RETURN(
   1763                 bcmi_esw_tsn_sw_flow_id_get(unit, hw_id, &tsn_flow_id));
   1764 
   1765             /* Convert software TSN flow ID to flowset */
   1766             BCM_IF_ERROR_RETURN(
   1767                 bcmi_esw_tsn_flowset_identify(unit, tsn_flow_id,
   1768                                               &l2addr->tsn_flowset));
   1769         }
   1770     }
   1771 
   1772 #if defined(BCM_TSN_SR_SUPPORT)
   1773     if (soc_feature(unit, soc_feature_tsn_sr)) {
   1774         /* Indicates this MAC address belongs to DAN or SAN.(0: DAN, 1: SAN) */
   1775         if (soc_L2Xm_field32_get(unit, l2x_entry, SANf)) {
   1776             l2addr->flags |= BCM_L2_SR_SAN_DEST;
   1777         }
   1778 
   1779         /*
   1780          * Provides the Flow ID for Seamless Redundancy:
   1781          * - SR_Flow_ID=0 is not valid. Valid for DA or SA lookup depending on
   1782          *   PORT.SR_FLOW_ID_SOURCE_PRIORITY.
   1783          */
   1784         hw_id = soc_L2Xm_field32_get(unit, l2x_entry, SR_FLOW_IDf);
   1785         if (hw_id != 0) {
   1786             /* Convert hardware SR flow ID to software SR flow ID */
   1787             BCM_IF_ERROR_RETURN(
   1788                 bcmi_esw_tsn_sr_sw_flow_id_get(unit, hw_id, &sr_flow_id));
   1789 
   1790             /* Convert software SR flow ID to flowset */
   1791             BCM_IF_ERROR_RETURN(
   1792                 bcmi_esw_tsn_sr_flowset_identify(unit, sr_flow_id,
   1793                                                  &l2addr->sr_flowset));
   1794         }
   1795 
   1796         /* Provides the Source port filter bitmap for this SA */
   1797         mp_index = soc_L2Xm_field32_get(unit, l2x_entry,
   1798                                         SR_MAC_PROXY_PROFILE_PTRf);
   1799         if (mp_index != 0) {
   1800             BCM_PBMP_CLEAR(mp_pbmp);
   1801             BCM_IF_ERROR_RETURN(
   1802                 bcmi_esw_tsn_sr_mac_proxy_get(unit, mp_index, &mp_pbmp));
   1803             BCM_PBMP_NEGATE(l2addr->sa_source_filter_pbmp, mp_pbmp);
   1804             BCM_PBMP_AND(l2addr->sa_source_filter_pbmp, PBMP_ALL(unit));
   1805         }
   1806     }
   1807 #endif /* BCM_TSN_SR_SUPPORT */
   1808 
   1809     if (soc_feature(unit, soc_feature_tsn_taf)) {
   1810         uint32 hw_profile_id = soc_L2Xm_field32_get(unit, l2x_entry,
   1811                                                     TAF_GATE_ID_PROFILEf);
   1812         if (0 == hw_profile_id) {
   1813             l2addr->taf_gate_primap = BCM_TSN_PRI_MAP_INVALID;
   1814         } else {
   1815             bcm_tsn_pri_map_t sw_index;
   1816 
   1817             BCM_IF_ERROR_RETURN(
   1818                 bcmi_esw_tsn_pri_map_map_id_get(unit, bcmTsnPriMapTypeTafGate,
   1819                                                 hw_profile_id, &sw_index));
   1820             l2addr->taf_gate_primap = sw_index;
   1821         }
   1822     } else
   1823 #endif /* BCM_TSN_SUPPORT */
   1824     {
   1825         l2addr->taf_gate_primap = BCM_TSN_PRI_MAP_INVALID;
   1826     }
   1827 
   1828 #if defined(BCM_GLOBAL_METER_SUPPORT)
   1829     /* Global Meter Policer Configuration */
   1830     if (soc_feature(unit, soc_feature_global_meter) &&
   1831         soc_feature(unit, soc_feature_global_meter_source_l2)) {
   1832         BCM_IF_ERROR_RETURN(
   1833             _bcm_esw_get_policer_from_table(
   1834                 unit, L2Xm, 0, (void *)l2x_entry, &l2addr->policer_id, TRUE));
   1835     }
   1836 #endif /* BCM_GLOBAL_METER_SUPPORT */
   1837 
   1838     return BCM_E_NONE;
   1839 }
   1840 
   1841 /*
   1842  * Function:
   1843  *      _bcm_tr_l2_to_l2x
   1844  * Purpose:
   1845  *      Convert an L2 API data structure to a Triumph L2X entry
   1846  * Parameters:
   1847  *      unit        Unit number
   1848  *      l2x_entry   (OUT) Triumph L2X entry
   1849  *      l2addr      L2 API data structure
   1850  *      key_only    Only construct key portion
   1851  */
   1852 int
   1853 _bcm_tr_l2_to_l2x(int unit, l2x_entry_t *l2x_entry, bcm_l2_addr_t *l2addr,
   1854                   int key_only)
   1855 {
   1856     int rv = BCM_E_NONE;
   1857     int vfi;
   1858     int tid_is_vp_lag;
   1859     bcm_cos_t cos_dst = l2addr->cos_dst;
   1860     int group = l2addr->group;
   1861 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   1862     int my_station_config = 0;
   1863     uint32 dest_value = 0;
   1864 #endif
   1865     int pri_field_len;
   1866     int max_pri;
   1867 #if defined(BCM_GREYHOUND2_SUPPORT) && defined(INCLUDE_L3)
   1868     int vp = -1;
   1869     int ecmp = 0, nh_ecmp_index = 0;
   1870     bcm_vxlan_port_t vxlan_port;
   1871     int field_len = 0;
   1872     vfi_entry_t vfi_entry;
   1873 #endif /* BCM_GREYHOUND2_SUPPORT && INCLUDE_L3 */
   1874 #if defined(BCM_MONTEREY_SUPPORT) && defined(INCLUDE_L3)
   1875     uint32 mpath_flag = 0;
   1876     int nh_index = 0;
   1877     bcm_if_t egr_intf = -1;
   1878     int l3mc_index = -1;
   1879     uint32 egr_dest = 0;
   1880 #endif /* BCM_MONTEREY_SUPPORT && INCLUDE_L3 */
   1881 #if defined(BCM_TSN_SUPPORT)
   1882     uint32 hw_id = 0;
   1883     bcm_tsn_pri_map_t pri_map = BCM_TSN_PRI_MAP_INVALID;
   1884     bcm_tsn_flow_t tsn_flow_id = 0;
   1885     bcm_tsn_flow_config_t tsn_config;
   1886     bcm_tsn_pri_map_type_t map_type;
   1887 #if defined(BCM_TSN_SR_SUPPORT)
   1888     bcm_tsn_sr_flow_t sr_flow_id = 0;
   1889     bcm_tsn_sr_tx_flow_config_t sr_tx_config;
   1890     bcm_tsn_sr_rx_flow_config_t sr_rx_config;
   1891     l2mc_entry_t l2mc_entry;
   1892     int l2mc_index;
   1893     bcm_pbmp_t l2mc_pbmp;
   1894     bcm_port_t l2mc_port;
   1895     sr_port_table_entry_t sr_port_entry;
   1896     sr_lport_tab_entry_t sr_lport_entry;
   1897 #endif /* BCM_TSN_SR_SUPPORT */
   1898 #endif /* BCM_TSN_SUPPORT */
   1899 
   1900     pri_field_len = soc_mem_field_length(unit, L2Xm, PRIf);
   1901     max_pri = (1 << pri_field_len) - 1;
   1902 
   1903     /* Allow the maximum priority as per the device table support */
   1904     if ((l2addr->cos_dst < BCM_PRIO_MIN) || (l2addr->cos_dst > max_pri)) {
   1905         return BCM_E_PARAM;
   1906     }
   1907 
   1908     /*  BCM_L2_MIRROR is not supported starting from Triumph */
   1909     if (l2addr->flags & BCM_L2_MIRROR) {
   1910         return BCM_E_PARAM;
   1911     }
   1912 
   1913     /* Setting both flags is not a valid configuration. */
   1914     if (l2addr->flags & BCM_L2_LEARN_LIMIT_EXEMPT && 
   1915         l2addr->flags & BCM_L2_LEARN_LIMIT_EXEMPT_LOCAL) {
   1916         return BCM_E_PARAM;
   1917     }
   1918 
   1919     sal_memset(l2x_entry, 0, sizeof (*l2x_entry));
   1920 
   1921 #ifdef BCM_TRIDENT3_SUPPORT
   1922     if (soc_feature(unit, soc_feature_flex_flow) &&
   1923         (l2addr->flow_handle != 0)) {
   1924 
   1925         return _bcm_td3_flex_l2_to_l2x(unit, l2x_entry, l2addr, key_only);
   1926     }
   1927 #endif
   1928 
   1929     if (_BCM_VPN_VFI_IS_SET(l2addr->vid)) {
   1930         _BCM_VPN_GET(vfi, _BCM_VPN_TYPE_VFI, l2addr->vid);
   1931 
   1932 #ifdef BCM_TRIDENT3_SUPPORT
   1933         if (soc_mem_is_valid(unit, VFI_ATTRS_1m)) {
   1934             if (vfi > soc_mem_index_max(unit, VFI_ATTRS_1m)) {
   1935                 return BCM_E_PARAM;
   1936             }
   1937         }
   1938 #endif
   1939         soc_L2Xm_field32_set(unit, l2x_entry, VFIf, vfi);
   1940         soc_L2Xm_field32_set(unit, l2x_entry, KEY_TYPEf,
   1941                              TR_L2_HASH_KEY_TYPE_VFI);
   1942     } else {
   1943          if (!_BCM_MPLS_VPN_IS_VPWS(l2addr->vid)) {
   1944               VLAN_CHK_ID(unit, l2addr->vid);
   1945               soc_L2Xm_field32_set(unit, l2x_entry, VLAN_IDf, l2addr->vid);
   1946               soc_L2Xm_field32_set(unit, l2x_entry, KEY_TYPEf,
   1947                                    TR_L2_HASH_KEY_TYPE_BRIDGE);
   1948 #ifdef BCM_TRIDENT3_SUPPORT
   1949               if (soc_feature(unit, soc_feature_pvlan_on_vfi)) {
   1950                   if (l2addr->flags2 & BCM_L2_FLAGS2_ADD_VPN_TYPE) {
   1951                       soc_L2Xm_field32_set(unit, l2x_entry, KEY_TYPEf,
   1952                                            TR_L2_HASH_KEY_TYPE_VFI);
   1953                   }
   1954               }
   1955 #endif
   1956          }
   1957     }
   1958 
   1959     soc_L2Xm_mac_addr_set(unit, l2x_entry, MAC_ADDRf, l2addr->mac);
   1960 
   1961     if (key_only) {
   1962         return BCM_E_NONE;
   1963     }
   1964 
   1965     if (BCM_MAC_IS_MCAST(l2addr->mac)) {
   1966 #if defined(BCM_GREYHOUND2_SUPPORT) && defined(INCLUDE_L3)
   1967         if ((BCM_GPORT_IS_VXLAN_PORT(l2addr->port)) &&
   1968             (soc_feature(unit, soc_feature_vxlan_lite))) {
   1969             vp = BCM_GPORT_VXLAN_PORT_ID_GET(l2addr->port);
   1970             if (vp == -1) {
   1971                 return BCM_E_PARAM;
   1972             }
   1973 
   1974             BCM_IF_ERROR_RETURN(
   1975                 bcmi_gh2_vxlan_port_to_nh_ecmp_index(unit, vp,
   1976                                                      &ecmp, &nh_ecmp_index));
   1977             if (ecmp) {
   1978                 /* ECMP */
   1979                 soc_L2Xm_field32_set(unit, l2x_entry, DEST_TYPEf, 0x5);
   1980             } else {
   1981                 /* NHI */
   1982                 soc_L2Xm_field32_set(unit, l2x_entry, DEST_TYPEf, 0x4);
   1983             }
   1984 
   1985             soc_L2Xm_field32_set(unit, l2x_entry, NHI_ECMPf, nh_ecmp_index);
   1986         } else
   1987 #endif /* BCM_GREYHOUND2_SUPPORT && INCLUDE_L3 */
   1988 #if defined(BCM_MONTEREY_SUPPORT) && defined(INCLUDE_L3)
   1989         if ((soc_feature(unit,soc_feature_roe) ||
   1990              soc_feature(unit,soc_feature_roe_custom)) &&
   1991             (l2addr->flags2 & BCM_L2_FLAGS2_L3_MULTICAST)) {
   1992 
   1993             if (_BCM_MULTICAST_IS_SET(l2addr->l3mc_group)) {
   1994                 if (_BCM_MULTICAST_IS_L3(l2addr->l3mc_group)) {
   1995                     l3mc_index = _BCM_MULTICAST_ID_GET(l2addr->l3mc_group);
   1996                 } else {
   1997                     return BCM_E_PARAM;
   1998                 }
   1999             } else {
   2000                 return BCM_E_PARAM;
   2001             }
   2002 
   2003             if (-1 != l3mc_index) {
   2004                 soc_L2Xm_field32_set(unit, l2x_entry, DEST_TYPEf, 0x3);
   2005                 soc_L2Xm_field32_set(unit, l2x_entry, DESTINATIONf, l3mc_index);
   2006             }
   2007         } else
   2008 #endif /* BCM_MONTEREY_SUPPORT && INCLUDE_L3 */
   2009         {
   2010             if (l2addr->l2mc_group < 0) {
   2011                 return BCM_E_PARAM;
   2012             }
   2013 
   2014             if (soc_feature(unit, soc_feature_generic_dest)) {
   2015                 uint32 dest_type = SOC_MEM_FIF_DEST_L2MC;
   2016                 if (_BCM_MULTICAST_IS_VPLS(l2addr->l2mc_group) ||
   2017                     _BCM_MULTICAST_IS_MIM(l2addr->l2mc_group) ||
   2018                     _BCM_MULTICAST_IS_WLAN(l2addr->l2mc_group) ||
   2019                     _BCM_MULTICAST_IS_VLAN(l2addr->l2mc_group) ||
   2020                     _BCM_MULTICAST_IS_NIV(l2addr->l2mc_group) ||
   2021                     _BCM_MULTICAST_IS_L2GRE(l2addr->l2mc_group) ||
   2022                     _BCM_MULTICAST_IS_VXLAN(l2addr->l2mc_group) ||
   2023                     _BCM_MULTICAST_IS_FLOW(l2addr->l2mc_group) ||
   2024                     _BCM_MULTICAST_IS_SUBPORT(l2addr->l2mc_group) ||
   2025                     _BCM_MULTICAST_IS_EXTENDER(l2addr->l2mc_group)) {
   2026                     dest_type = SOC_MEM_FIF_DEST_IPMC;
   2027                 }
   2028                 soc_mem_field32_dest_set(unit, L2Xm, l2x_entry, DESTINATIONf,
   2029                     dest_type, _BCM_MULTICAST_ID_GET(l2addr->l2mc_group));
   2030             } else {
   2031                 if (_BCM_MULTICAST_IS_VPLS(l2addr->l2mc_group) ||
   2032                     _BCM_MULTICAST_IS_MIM(l2addr->l2mc_group) ||
   2033                     _BCM_MULTICAST_IS_WLAN(l2addr->l2mc_group) ||
   2034                     _BCM_MULTICAST_IS_VLAN(l2addr->l2mc_group) ||
   2035                     _BCM_MULTICAST_IS_NIV(l2addr->l2mc_group) ||
   2036                     _BCM_MULTICAST_IS_L2GRE(l2addr->l2mc_group) ||
   2037                     _BCM_MULTICAST_IS_VXLAN(l2addr->l2mc_group) ||
   2038                     _BCM_MULTICAST_IS_FLOW(l2addr->l2mc_group) ||
   2039                     _BCM_MULTICAST_IS_SUBPORT(l2addr->l2mc_group) ||
   2040                     _BCM_MULTICAST_IS_EXTENDER(l2addr->l2mc_group)) {
   2041                     soc_L2Xm_field32_set(unit, l2x_entry, DEST_TYPEf, 0x3);
   2042 #if defined(BCM_GREYHOUND2_SUPPORT) && defined(INCLUDE_L3)
   2043                     /* Only support for GH2-B0 */
   2044                     if (soc_feature(unit, soc_feature_vxlan_lite_riot)) {
   2045                         if (_BCM_MULTICAST_IS_VXLAN(l2addr->l2mc_group) &&
   2046                             _BCM_VPN_VFI_IS_SET(l2addr->vid)) {
   2047                             _BCM_VPN_GET(vfi, _BCM_VPN_TYPE_VFI, l2addr->vid);
   2048                             SOC_IF_ERROR_RETURN(
   2049                                 soc_mem_read(unit, VFIm, MEM_BLOCK_ANY,
   2050                                              vfi, &vfi_entry));
   2051                             /*
   2052                              * For Multicast ENCAP flow, the KEY_TYPEf = 0x3.
   2053                              * - to specify VFI is only MAC based forwarding.
   2054                              * - IPMCV4_L2_ENABLE = 1 && IPMCV6_L2_ENABLE = 1.
   2055                              * For Multicast DECAP flow, the KEY_TYPEf = 0x7.
   2056                              * - IPMCV4_L2_ENABLE = 0 && IPMCV6_L2_ENABLE = 0.
   2057                              */
   2058                             if (!(soc_VFIm_field32_get(unit, &vfi_entry,
   2059                                                        IPMCV4_L2_ENABLEf)) &&
   2060                                 !(soc_VFIm_field32_get(unit, &vfi_entry,
   2061                                                        IPMCV6_L2_ENABLEf))) {
   2062                                 soc_L2Xm_field32_set
   2063                                     (unit, l2x_entry, KEY_TYPEf,
   2064                                      GH2_L2_HASH_KEY_TYPE_VFI_MULTICAST);
   2065                             }
   2066                         }
   2067                     }
   2068 #endif /* BCM_GREYHOUND2_SUPPORT && INCLUDE_L3  */
   2069                 }
   2070 #if defined(BCM_GREYHOUND2_SUPPORT)
   2071                 else if ((soc_feature(unit, soc_feature_vxlan_lite)) &&
   2072                         (_BCM_VPN_VFI_IS_SET(l2addr->vid))) {
   2073                     /*
   2074                      * GH2 VXLAN-Lite doesn't support
   2075                      * DEST_TYPE = 0 (L2MC) for VXLAN-based (VFI) keys.
   2076                      */
   2077                     return BCM_E_PARAM;
   2078                 }
   2079 #endif /* BCM_GREYHOUND2_SUPPORT */
   2080 
   2081                 if (_BCM_MULTICAST_IS_SET(l2addr->l2mc_group)) {
   2082                     soc_L2Xm_field32_set
   2083                         (unit, l2x_entry, DESTINATIONf,
   2084                          _BCM_MULTICAST_ID_GET(l2addr->l2mc_group));
   2085                 } else {
   2086                         soc_L2Xm_field32_set(unit, l2x_entry, L2MC_PTRf,
   2087                                              l2addr->l2mc_group);
   2088                 }
   2089             }
   2090         }
   2091 #if defined(BCM_TSN_SR_SUPPORT)
   2092     } else if (soc_feature(unit, soc_feature_tsn_sr) &&
   2093         (l2addr->flags & BCM_L2_MCAST)) {
   2094         int sr_lport_idx;
   2095         bcm_module_t my_modid = -1;
   2096         int src_trk_idx = 0; /* Source Trunk table index.*/
   2097         uint32 mem_entry[SOC_MAX_MEM_WORDS];
   2098 
   2099         BCM_IF_ERROR_RETURN(
   2100             bcm_esw_stk_my_modid_get(unit, &my_modid));
   2101 
   2102         /*
   2103          * Indicates that the destination is a
   2104          * Seamless Redundancy Duplicate port and Unicast packets must be
   2105          * forwarded as Multicast (DEST_TYPE=L2MC)
   2106          */
   2107         if (l2addr->l2mc_group < 0) {
   2108             return BCM_E_PARAM;
   2109         }
   2110 
   2111         if (_BCM_MULTICAST_IS_SET(l2addr->l2mc_group)) {
   2112             if (_BCM_MULTICAST_IS_L2(l2addr->l2mc_group)) {
   2113                 l2mc_index = _BCM_MULTICAST_ID_GET(l2addr->l2mc_group);
   2114             } else {
   2115                 return BCM_E_PARAM;
   2116             }
   2117         } else {
   2118             l2mc_index = l2addr->l2mc_group;
   2119         }
   2120         soc_L2Xm_field32_set(unit, l2x_entry,
   2121                              L2MC_PTRf, l2mc_index);
   2122         soc_L2Xm_field32_set(unit, l2x_entry,
   2123                              SR_DUPLICATE_FORWARDINGf, 0x1);
   2124 
   2125         /* Update l2mc_index for related SR ports associated L2MC table */
   2126         BCM_IF_ERROR_RETURN(
   2127             soc_mem_read(unit, L2MCm, MEM_BLOCK_ANY,
   2128                          l2mc_index, &l2mc_entry));
   2129         BCM_PBMP_CLEAR(l2mc_pbmp);
   2130         soc_mem_pbmp_field_get(unit, L2MCm, &l2mc_entry,
   2131                                PORT_BITMAPf, &l2mc_pbmp);
   2132         BCM_PBMP_ITER(l2mc_pbmp, l2mc_port) {
   2133             BCM_IF_ERROR_RETURN(
   2134                 soc_mem_read(unit, SR_PORT_TABLEm, MEM_BLOCK_ANY,
   2135                              l2mc_port, &sr_port_entry));
   2136             soc_mem_field32_set(unit, SR_PORT_TABLEm, &sr_port_entry,
   2137                                 L2MCf, l2mc_index);
   2138             BCM_IF_ERROR_RETURN(
   2139                 soc_mem_write(unit, SR_PORT_TABLEm, MEM_BLOCK_ALL,
   2140                               l2mc_port, &sr_port_entry));
   2141 
   2142             BCM_IF_ERROR_RETURN(
   2143                 _bcm_esw_src_mod_port_table_index_get(unit, my_modid,
   2144                                                       l2mc_port, &src_trk_idx));
   2145             BCM_IF_ERROR_RETURN(
   2146                 soc_mem_read(unit, SOURCE_TRUNK_MAP_TABLEm, MEM_BLOCK_ANY,
   2147                              src_trk_idx, mem_entry));
   2148 
   2149             sr_lport_idx = soc_mem_field32_get(unit, SOURCE_TRUNK_MAP_TABLEm,
   2150                                                mem_entry, LPORT_PROFILE_IDXf);
   2151             BCM_IF_ERROR_RETURN(
   2152                 soc_mem_read(unit, SR_LPORT_TABm, MEM_BLOCK_ANY,
   2153                              sr_lport_idx, &sr_lport_entry));
   2154             soc_mem_field32_set(unit, SR_LPORT_TABm, &sr_lport_entry,
   2155                                 L2MCf, l2mc_index);
   2156             BCM_IF_ERROR_RETURN(
   2157                 soc_mem_write(unit, SR_LPORT_TABm, MEM_BLOCK_ALL,
   2158                               sr_lport_idx, &sr_lport_entry));
   2159         }
   2160 #endif /* BCM_TSN_SR_SUPPORT */
   2161     } else {
   2162         bcm_port_t      port = -1;
   2163         bcm_trunk_t     tgid = BCM_TRUNK_INVALID;
   2164         bcm_module_t    modid = -1;
   2165         int             gport_id = -1;
   2166         int             vpg_type = 0;
   2167 
   2168         if (BCM_GPORT_IS_SET(l2addr->port)) {
   2169             _bcm_l2_gport_params_t  g_params;
   2170 
   2171             if (BCM_GPORT_IS_BLACK_HOLE(l2addr->port)) {
   2172                 soc_L2Xm_field32_set(unit, l2x_entry, SRC_DISCARDf, 1);
   2173 #if defined(BCM_GREYHOUND2_SUPPORT) && defined(INCLUDE_L3)
   2174             } else if ((BCM_GPORT_IS_VXLAN_PORT(l2addr->port)) &&
   2175                        (soc_feature(unit, soc_feature_vxlan_lite))) {
   2176                 soc_L2Xm_field32_set(unit, l2x_entry, SRC_DISCARDf, 0);
   2177 
   2178                 vp = BCM_GPORT_VXLAN_PORT_ID_GET(l2addr->port);
   2179                 if (vp == -1) {
   2180                     return BCM_E_PARAM;
   2181                 }
   2182 #endif /* BCM_GREYHOUND2_SUPPORT && INCLUDE_L3 */
   2183             } else {
   2184                 soc_L2Xm_field32_set(unit, l2x_entry, SRC_DISCARDf, 0);
   2185                 BCM_IF_ERROR_RETURN(
   2186                         _bcm_esw_l2_gport_parse(unit, l2addr, &g_params));
   2187 
   2188                 switch (g_params.type) {
   2189                     case _SHR_GPORT_TYPE_TRUNK:
   2190                         tgid = g_params.param0;
   2191                         break;
   2192                     case  _SHR_GPORT_TYPE_MODPORT:
   2193                         port = g_params.param0;
   2194                         modid = g_params.param1;
   2195                         break;
   2196                     case _SHR_GPORT_TYPE_LOCAL_CPU:
   2197                         port = g_params.param0;
   2198                         BCM_IF_ERROR_RETURN(
   2199                                 bcm_esw_stk_my_modid_get(unit, &modid));
   2200                         break;
   2201                     case _SHR_GPORT_TYPE_SUBPORT_GROUP:
   2202                         gport_id = g_params.param0;
   2203 #if defined(BCM_SCORPION_SUPPORT) && defined(INCLUDE_L3)
   2204                         if (SOC_IS_SC_CQ(unit)) {
   2205                             /* Map the sub_port to index to L3_NEXT_HOP */
   2206                             gport_id = (int) _sc_subport_group_index[unit][gport_id/8];
   2207                         }
   2208 #endif /* BCM_SCORPION_SUPPORT && INCLUDE_L3 */
   2209                         vpg_type = 1;
   2210                         break;
   2211                 case _SHR_GPORT_TYPE_SUBPORT_PORT:
   2212 
   2213 #if defined(BCM_HGPROXY_COE_SUPPORT)
   2214                     if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) &&
   2215                         _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, l2addr->port)) {
   2216                         port = g_params.param0;
   2217                         modid = g_params.param1;
   2218                     } else
   2219 #endif
   2220 #if defined(BCM_KATANA2_SUPPORT)
   2221                     if (_BCM_KT2_GPORT_IS_LINKPHY_OR_SUBTAG_SUBPORT_GPORT(unit,
   2222                         l2addr->port)) {
   2223                         port = g_params.param0;
   2224                         modid = g_params.param1;
   2225                     } else
   2226 #endif
   2227                     {
   2228                         gport_id = g_params.param0;
   2229                         vpg_type = 1;
   2230                     }
   2231                     break;
   2232                     case _SHR_GPORT_TYPE_MPLS_PORT:
   2233                     gport_id = g_params.param0;
   2234                     vpg_type = 1;
   2235                     break;
   2236                     case _SHR_GPORT_TYPE_MIM_PORT:
   2237                     case _SHR_GPORT_TYPE_WLAN_PORT:
   2238                     case _SHR_GPORT_TYPE_VLAN_PORT:
   2239                     case _SHR_GPORT_TYPE_NIV_PORT:
   2240                     case _SHR_GPORT_TYPE_EXTENDER_PORT:
   2241                         gport_id = g_params.param0;
   2242                         vpg_type = 1;
   2243                         break;
   2244                     case _SHR_GPORT_TYPE_TRILL_PORT:
   2245                     case _SHR_GPORT_TYPE_L2GRE_PORT:
   2246                     case _SHR_GPORT_TYPE_VXLAN_PORT:
   2247                     case _SHR_GPORT_TYPE_FLOW_PORT:
   2248 
   2249                         gport_id = g_params.param0;
   2250                         vpg_type = 0;
   2251                         break;
   2252                     default:
   2253                         return BCM_E_PORT;
   2254                 }
   2255             }
   2256         } else if (l2addr->flags & BCM_L2_TRUNK_MEMBER) {
   2257             tgid = l2addr->tgid;
   2258  #if defined(BCM_MONTEREY_SUPPORT) && defined(INCLUDE_L3)
   2259         } else if ((soc_feature(unit,soc_feature_roe) ||
   2260                     soc_feature(unit,soc_feature_roe_custom)) && 
   2261                    (l2addr->flags2 & BCM_L2_FLAGS2_ROE_NHI)) {
   2262             egr_intf = l2addr->egress_if;
   2263  #endif /* BCM_MONTEREY_SUPPORT && INCLUDE_L3 */
   2264         } else {
   2265             BCM_IF_ERROR_RETURN(
   2266                 _bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_SET,
   2267                                        l2addr->modid, l2addr->port,
   2268                                        &modid, &port));
   2269             /* Check parameters */
   2270             if (!SOC_MODID_ADDRESSABLE(unit, modid)) {
   2271                 return BCM_E_BADID;
   2272             }
   2273             if (!SOC_PORT_ADDRESSABLE(unit, port)) {
   2274                 return BCM_E_PORT;
   2275             }
   2276         }
   2277 
   2278         /* Setting l2x_entry fields according to parameters */
   2279         if ( BCM_TRUNK_INVALID != tgid) {
   2280             BCM_IF_ERROR_RETURN(_bcm_esw_trunk_id_is_vp_lag(unit, tgid,
   2281                             &tid_is_vp_lag));
   2282             if (tid_is_vp_lag) {
   2283                 if (soc_feature(unit, soc_feature_vp_lag)) {
   2284                     int vp_lag_vp;
   2285                     /* Get the VP value representing VP LAG */
   2286                     BCM_IF_ERROR_RETURN(_bcm_esw_trunk_tid_to_vp_lag_vp(unit,
   2287                                 tgid, &vp_lag_vp));
   2288                     if (soc_feature(unit, soc_feature_generic_dest)) {
   2289                         soc_mem_field32_dest_set(unit, L2Xm, l2x_entry,
   2290                             DESTINATIONf, SOC_MEM_FIF_DEST_DVP, vp_lag_vp);
   2291                     } else {
   2292                     soc_L2Xm_field32_set(unit, l2x_entry, DEST_TYPEf, 0x2);
   2293                     soc_L2Xm_field32_set(unit, l2x_entry, DESTINATIONf,
   2294                             vp_lag_vp);
   2295                     }
   2296                 } else {
   2297                     return BCM_E_PORT;
   2298                 }
   2299             } else {
   2300                 if (soc_feature(unit, soc_feature_generic_dest)) {
   2301                     if (l2addr->flags & BCM_L2_REMOTE_TRUNK) {
   2302                         tgid |= 1 << SOC_MEM_FIF_DGPP_RT_SHIFT_BITS;
   2303                     }
   2304                     soc_mem_field32_dest_set(unit, L2Xm, l2x_entry,
   2305                         DESTINATIONf, SOC_MEM_FIF_DEST_LAG, tgid);
   2306                 } else {
   2307                 soc_L2Xm_field32_set(unit, l2x_entry, Tf, 1);
   2308                 soc_L2Xm_field32_set(unit, l2x_entry, TGIDf, tgid);
   2309                 /*
   2310                  * Note:  RTAG is ignored here.  Use bcm_trunk_psc_set to
   2311                  * to set for a given trunk.
   2312                  */
   2313                 if (l2addr->flags & BCM_L2_REMOTE_TRUNK) {
   2314 #if defined(BCM_TRIDENT2PLUS_SUPPORT) || defined(BCM_APACHE_SUPPORT)
   2315                     if (soc_feature(unit, soc_feature_no_l2_remote_trunk)) {
   2316                     } else
   2317 #endif
   2318                     {
   2319                         soc_L2Xm_field32_set(unit, l2x_entry, REMOTE_TRUNKf, 1);
   2320                     }
   2321                 }
   2322             }
   2323             }
   2324         } else if (-1 != port) {
   2325             if (soc_feature(unit, soc_feature_generic_dest)) {
   2326                 soc_mem_field32_dest_set(unit, L2Xm, l2x_entry,
   2327                     DESTINATIONf, SOC_MEM_FIF_DEST_DGPP,
   2328                     modid << SOC_MEM_FIF_DGPP_MOD_ID_SHIFT_BITS | port);
   2329             } else {
   2330             soc_L2Xm_field32_set(unit, l2x_entry, MODULE_IDf, modid);
   2331             soc_L2Xm_field32_set(unit, l2x_entry, PORT_NUMf, port);
   2332             }
   2333 #if defined(BCM_MONTEREY_SUPPORT) && defined(INCLUDE_L3)
   2334         } else if (-1 != egr_intf) {
   2335                 BCM_IF_ERROR_RETURN(
   2336                     bcm_xgs3_get_nh_from_egress_object(unit, egr_intf, &mpath_flag,
   2337                                                                 0, &nh_index));
   2338                 soc_L2Xm_field32_set(unit, l2x_entry, DEST_TYPEf, 0x1);
   2339                 egr_dest = _BCM_L2_DEST_TYPE_NHI;
   2340                 egr_dest |= nh_index;
   2341                 soc_L2Xm_field32_set(unit, l2x_entry, DESTINATIONf, egr_dest);
   2342 #endif /* BCM_MONTEREY_SUPPORT && INCLUDE_L3 */
   2343 #if defined(BCM_GREYHOUND2_SUPPORT) && defined(INCLUDE_L3)
   2344         } else if (-1 != vp) {
   2345             if (soc_feature(unit, soc_feature_vxlan_lite)) {
   2346                 BCM_IF_ERROR_RETURN(
   2347                     bcmi_gh2_vxlan_port_to_nh_ecmp_index(unit, vp, &ecmp,
   2348                                                          &nh_ecmp_index));
   2349                 if (ecmp) {
   2350                     /* ECMP */
   2351                     soc_L2Xm_field32_set(unit, l2x_entry, DEST_TYPEf, 0x5);
   2352                 } else {
   2353                     /* NHI */
   2354                     soc_L2Xm_field32_set(unit, l2x_entry, DEST_TYPEf, 0x4);
   2355                 }
   2356                 soc_L2Xm_field32_set(unit, l2x_entry,
   2357                                      NHI_ECMPf, nh_ecmp_index);
   2358 
   2359                 /* Only support for GH2-B0 */
   2360                 if (soc_feature(unit, soc_feature_vxlan_lite_riot)) {
   2361                     bcm_vxlan_port_t_init(&vxlan_port);
   2362 
   2363                     vxlan_port.vxlan_port_id = l2addr->port;
   2364                     BCM_IF_ERROR_RETURN(
   2365                         bcm_esw_vxlan_port_get(unit, (bcm_vpn_t)l2addr->vid,
   2366                                                &vxlan_port));
   2367 
   2368                     soc_L2Xm_field32_set(unit, l2x_entry,
   2369                                          ASSOCIATED_DATA_TYPEf, 0x1);
   2370 
   2371                     /* Set SGLP */
   2372                     if (soc_property_get(unit, spn_RIOT_ENABLE, 0)) {
   2373                         BCM_IF_ERROR_RETURN(
   2374                             _bcm_esw_gport_resolve(unit, vxlan_port.match_port,
   2375                                                    &modid, &port, &tgid,
   2376                                                    &gport_id));
   2377                         if (BCM_GPORT_IS_TRUNK(vxlan_port.match_port) &&
   2378                             tgid != BCM_TRUNK_INVALID) {
   2379                             /* Set LAG ID indicator bit */
   2380                             field_len = soc_mem_field_length(unit,
   2381                                                              L2Xm, SGLPf);
   2382                             gport_id = ((1 << (field_len - 1)) + tgid);
   2383                         } else {
   2384                             field_len = soc_mem_field_length(unit,
   2385                                                              L2Xm, PORT_NUMf);
   2386                             gport_id = ((modid << field_len) + port);
   2387                         }
   2388                         soc_L2Xm_field32_set(unit, l2x_entry, SGLPf, gport_id);
   2389                     }
   2390                 }
   2391             }
   2392 #endif /* BCM_GREYHOUND2_SUPPORT && INCLUDE_L3 */
   2393         } else if (-1 != gport_id) {
   2394             if (soc_feature(unit, soc_feature_generic_dest)) {
   2395                 soc_mem_field32_dest_set(unit, L2Xm, l2x_entry,
   2396                     DESTINATIONf, SOC_MEM_FIF_DEST_DVP, gport_id);
   2397             } else {
   2398             soc_L2Xm_field32_set(unit, l2x_entry, DEST_TYPEf, 0x2);
   2399             if (vpg_type) {
   2400                 soc_L2Xm_field32_set(unit, l2x_entry, VPGf, gport_id);
   2401                 soc_L2Xm_field32_set(unit, l2x_entry, VPG_TYPEf, vpg_type);
   2402             } else {
   2403                 soc_L2Xm_field32_set(unit, l2x_entry, DESTINATIONf, gport_id);
   2404             }
   2405         }
   2406     }
   2407     }
   2408 
   2409     if (SOC_MEM_FIELD_VALID(unit, L2Xm, L3f)) {
   2410         if (l2addr->flags & BCM_L2_L3LOOKUP) {
   2411             soc_L2Xm_field32_set(unit, l2x_entry, L3f, 1);
   2412         }
   2413     }
   2414 
   2415     if (SOC_L2X_GROUP_ENABLE_GET(unit)) {
   2416         if (soc_feature(unit, soc_feature_overlaid_address_class) &&
   2417             !BCM_L2_PRE_SET(l2addr->flags)) {
   2418             if ((l2addr->group > SOC_OVERLAID_ADDR_CLASS_MAX(unit)) ||
   2419                 (l2addr->group < 0)) {
   2420                 return BCM_E_PARAM;
   2421             }
   2422             cos_dst = (l2addr->group & 0x3C0) >> 6;
   2423             group = l2addr->group & 0x3F;
   2424         }
   2425     }
   2426 
   2427     if (SOC_CONTROL(unit)->l2x_group_enable) {
   2428         soc_L2Xm_field32_set(unit, l2x_entry, CLASS_IDf, group);
   2429     } /* else MAC_BLOCK_INDEXf is handled in the add/remove functions below */
   2430 
   2431     if (l2addr->flags & BCM_L2_SETPRI) {
   2432         soc_L2Xm_field32_set(unit, l2x_entry, RPEf, 1);
   2433     }
   2434 
   2435     if (!SOC_IS_TRIUMPH3(unit)) {
   2436         soc_L2Xm_field32_set(unit, l2x_entry, PRIf, cos_dst);
   2437     }
   2438 
   2439     if (l2addr->flags & BCM_L2_COPY_TO_CPU) {
   2440         soc_L2Xm_field32_set(unit, l2x_entry, CPUf, 1);
   2441     }
   2442 
   2443     if (l2addr->flags & BCM_L2_DISCARD_DST) {
   2444         soc_L2Xm_field32_set(unit, l2x_entry, DST_DISCARDf, 1);
   2445     }
   2446 
   2447     if (l2addr->flags & BCM_L2_DISCARD_SRC) {
   2448         soc_L2Xm_field32_set(unit, l2x_entry, SRC_DISCARDf, 1);
   2449     }
   2450 
   2451     if (l2addr->flags & BCM_L2_COS_SRC_PRI) {
   2452         soc_L2Xm_field32_set(unit, l2x_entry, SCPf, 1);
   2453     }
   2454 
   2455     if (SOC_MEM_FIELD_VALID(unit, L2Xm, LIMIT_COUNTEDf)) {
   2456         if ((!(l2addr->flags & (BCM_L2_L3LOOKUP | BCM_L2_MCAST | BCM_L2_STATIC |
   2457                                BCM_L2_LEARN_LIMIT_EXEMPT))) || 
   2458             l2addr->flags & BCM_L2_LEARN_LIMIT) {
   2459             soc_L2Xm_field32_set(unit, l2x_entry, LIMIT_COUNTEDf, 1);
   2460         }
   2461     }
   2462 
   2463     if (l2addr->flags & BCM_L2_PENDING) {
   2464         soc_L2Xm_field32_set(unit, l2x_entry, PENDINGf, 1);
   2465     }
   2466 
   2467     if (l2addr->flags & BCM_L2_STATIC) {
   2468         soc_L2Xm_field32_set(unit, l2x_entry, STATIC_BITf, 1);
   2469     }
   2470 
   2471     if (soc_feature(unit, soc_feature_base_valid)) {
   2472         soc_L2Xm_field32_set(unit, l2x_entry, BASE_VALIDf, 1);
   2473     } else {
   2474     soc_L2Xm_field32_set(unit, l2x_entry, VALIDf, 1);
   2475     }
   2476 
   2477     if ((l2addr->flags & BCM_L2_DES_HIT) ||
   2478         (l2addr->flags & BCM_L2_HIT)) {
   2479         soc_L2Xm_field32_set(unit, l2x_entry, HITDAf, 1);
   2480     }
   2481 
   2482     if ((l2addr->flags & BCM_L2_SRC_HIT) ||
   2483         (l2addr->flags & BCM_L2_HIT)) {
   2484         soc_L2Xm_field32_set(unit, l2x_entry, HITSAf, 1);
   2485     }
   2486 
   2487     if (SOC_MEM_FIELD_VALID(unit, L2Xm, LOCAL_SAf)) {
   2488         if (l2addr->flags & BCM_L2_NATIVE) {
   2489             soc_L2Xm_field32_set(unit, l2x_entry, LOCAL_SAf, 1);
   2490         }
   2491     }
   2492 
   2493     
   2494     if (l2addr->flags & BCM_L2_LEARN_LIMIT_EXEMPT_LOCAL) {
   2495         if (!soc_feature(unit, soc_feature_mac_learn_limit)) {
   2496             return BCM_E_PARAM;
   2497         }
   2498         soc_L2Xm_field32_set(unit, l2x_entry, REMOTEf, 1);
   2499         soc_L2Xm_field32_set(unit, l2x_entry, LIMIT_COUNTEDf, 1);
   2500     }
   2501 
   2502 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   2503     my_station_config = soc_property_get(unit, spn_L2_ENTRY_USED_AS_MY_STATION, 0);
   2504     if (soc_feature(unit, soc_feature_l2_entry_used_as_my_station)
   2505         && my_station_config) {
   2506 #if defined(BCM_TRIDENT3_SUPPORT)
   2507         if (soc_feature(unit, soc_feature_mysta_profile)) {
   2508             uint32 mysta_profile_id;
   2509             bcm_l2_station_t station;
   2510             my_station_profile_2_entry_t entry;
   2511             sal_memset(&station, 0, sizeof(bcm_l2_station_t));
   2512             sal_memset(&entry, 0, sizeof(entry));
   2513             station.flags = l2addr->station_flags;
   2514             if (l2addr->station_flags != 0) {
   2515                 _bcm_l2_mysta_station_to_entry(unit, &station, MY_STATION_PROFILE_2m, &entry);
   2516                 BCM_IF_ERROR_RETURN(
   2517                     _bcm_l2_mysta_profile_entry_add(unit, &entry, 1,
   2518                     &mysta_profile_id));
   2519                 soc_mem_field32_dest_set(unit, L2Xm, l2x_entry, DESTINATIONf,
   2520                                          SOC_MEM_FIF_DEST_MYSTA, mysta_profile_id);
   2521             }
   2522         } else
   2523 #endif
   2524         {
   2525             /* Program DESTINATION only if station flags are specified */
   2526             if (l2addr->station_flags != 0) {
   2527 
   2528                 if ((l2addr->flags & BCM_L2_TRUNK_MEMBER) != 0) {
   2529                     return BCM_E_UNAVAIL;
   2530                 }
   2531 
   2532         soc_L2Xm_field32_set(unit, l2x_entry, DEST_TYPEf, 1);
   2533 
   2534         dest_value = _BCM_L2_DEST_STATION_HIT;
   2535 
   2536         if (l2addr->station_flags & BCM_L2_STATION_IPV4) {
   2537             dest_value |= _BCM_L2_DEST_STATION_IPV4;
   2538         }
   2539 
   2540         if (l2addr->station_flags & BCM_L2_STATION_IPV6) {
   2541             dest_value |= _BCM_L2_DEST_STATION_IPV6;
   2542         } 
   2543 
   2544         if (l2addr->station_flags & BCM_L2_STATION_ARP_RARP) {
   2545             dest_value |= _BCM_L2_DEST_STATION_ARP_RARP;
   2546         }
   2547 
   2548         if (l2addr->station_flags & BCM_L2_STATION_OAM) {
   2549             dest_value |= _BCM_L2_DEST_STATION_OAM;
   2550         }
   2551 
   2552         if (l2addr->station_flags & BCM_L2_STATION_FCOE) {
   2553              dest_value |= _BCM_L2_DEST_STATION_FCOE;
   2554         }
   2555 
   2556         if (l2addr->station_flags & BCM_L2_STATION_IPV4_MCAST) {
   2557             dest_value |= _BCM_L2_DEST_STATION_IPV4_MCAST;
   2558         }
   2559 
   2560         if (l2addr->station_flags & BCM_L2_STATION_IPV6_MCAST) {
   2561             dest_value |= _BCM_L2_DEST_STATION_IPV6_MCAST;
   2562         }
   2563 
   2564         soc_L2Xm_field32_set(unit, l2x_entry, DESTINATIONf, dest_value);
   2565         }
   2566         }
   2567     } else {
   2568         if (l2addr->station_flags & BCM_L2_STATION_IPV4
   2569            || l2addr->station_flags & BCM_L2_STATION_IPV6
   2570            || l2addr->station_flags & BCM_L2_STATION_ARP_RARP
   2571            || l2addr->station_flags & BCM_L2_STATION_OAM
   2572            || l2addr->station_flags & BCM_L2_STATION_FCOE
   2573            || l2addr->station_flags & BCM_L2_STATION_IPV4_MCAST
   2574            || l2addr->station_flags & BCM_L2_STATION_IPV6_MCAST) {
   2575            return BCM_E_UNAVAIL;
   2576         }
   2577     }
   2578 #endif /* BCM_TRIDENT2PLUS_SUPPORT */
   2579 
   2580 #if defined(BCM_TSN_SUPPORT)
   2581     if (soc_feature(unit, soc_feature_tsn)) {
   2582         /*
   2583          * Provides TSN circuit ID for this packet:
   2584          *  - 0 = Invalid TSN_CIRCUIT_ID, Valid only for MAC-DA lookup
   2585          */
   2586         if (l2addr->tsn_flowset != 0) {
   2587             /*
   2588              * To get base flow ID from
   2589              * TSN flow set (l2addr->tsn_flowset)
   2590              */
   2591             BCM_IF_ERROR_RETURN(
   2592                 bcm_esw_tsn_flowset_flow_get(unit, l2addr->tsn_flowset, 0,
   2593                                              &tsn_flow_id));
   2594 
   2595             /* Convert software TSN flow ID to hardware TSN flow ID */
   2596             BCM_IF_ERROR_RETURN(
   2597                 bcmi_esw_tsn_hw_flow_id_get(unit, tsn_flow_id, &hw_id));
   2598             soc_L2Xm_field32_set(unit, l2x_entry, TSN_CIRCUIT_IDf, hw_id);
   2599 
   2600             /*
   2601              * To get priority map id from
   2602              * TSN flow set (l2addr->tsn_flowset)
   2603              */
   2604             bcm_tsn_flow_config_t_init(&tsn_config);
   2605             BCM_IF_ERROR_RETURN(
   2606                 bcm_esw_tsn_flowset_config_get(unit, l2addr->tsn_flowset,
   2607                                                &pri_map, &tsn_config));
   2608 
   2609             if (pri_map != BCM_TSN_PRI_MAP_INVALID) {
   2610                 /* Get HW memory base index with given pri_map */
   2611                 BCM_IF_ERROR_RETURN(
   2612                     bcmi_esw_tsn_pri_map_hw_index_get(unit, pri_map,
   2613                                                       &map_type, &hw_id));
   2614                 if (map_type == bcmTsnPriMapTypeTsnFlow) {
   2615                     soc_L2Xm_field32_set(unit, l2x_entry,
   2616                                          TSN_PRI_OFFSET_PROFILEf, hw_id);
   2617                 } else {
   2618                     return BCM_E_CONFIG;
   2619                 }
   2620             }
   2621         }
   2622     }
   2623 
   2624 #if defined(BCM_TSN_SR_SUPPORT)
   2625     if (soc_feature(unit, soc_feature_tsn_sr)) {
   2626         /* Indicates this MAC address belongs to DAN or SAN (0: DAN, 1: SAN) */
   2627         if (l2addr->flags & BCM_L2_SR_SAN_DEST) {
   2628             soc_L2Xm_field32_set(unit, l2x_entry, SANf, 1);
   2629         }
   2630 
   2631         /*
   2632          * Provides the Flow ID for Seamless Redundancy:
   2633          * - SR_Flow_ID=0 is not valid. Valid for DA or SA lookup depending on
   2634          *   PORT.SR_FLOW_ID_SOURCE_PRIORITY.
   2635          */
   2636         if (l2addr->sr_flowset != 0) {
   2637             /*
   2638              * To get base flow ID from
   2639              * SR flow set (l2addr->sr_flowset)
   2640              */
   2641             BCM_IF_ERROR_RETURN(
   2642                 bcm_esw_tsn_sr_flowset_flow_get(unit, l2addr->sr_flowset, 0,
   2643                                                 &sr_flow_id));
   2644 
   2645             /* Convert software SR flow ID to hardware SR flow ID */
   2646             BCM_IF_ERROR_RETURN(
   2647                 bcmi_esw_tsn_sr_hw_flow_id_get(unit, sr_flow_id, &hw_id));
   2648             soc_L2Xm_field32_set(unit, l2x_entry, SR_FLOW_IDf, hw_id);
   2649 
   2650             /*
   2651              * To get priority map id from
   2652              * SR flow set (l2addr->sr_flowset)
   2653              */
   2654             bcm_tsn_sr_tx_flow_config_t_init(&sr_tx_config);
   2655             rv = bcm_esw_tsn_sr_tx_flowset_config_get(unit,
   2656                                                       l2addr->sr_flowset,
   2657                                                       &pri_map,
   2658                                                       &sr_tx_config);
   2659 
   2660             if ((rv == BCM_E_NOT_FOUND) || (rv == BCM_E_BADID)) {
   2661                 bcm_tsn_sr_rx_flow_config_t_init(&sr_rx_config);
   2662                 rv = bcm_esw_tsn_sr_rx_flowset_config_get(unit,
   2663                                                           l2addr->sr_flowset,
   2664                                                           &pri_map,
   2665                                                           &sr_rx_config);
   2666 
   2667                 if (BCM_FAILURE(rv)) {
   2668                     return rv;
   2669                 }
   2670             } else if (BCM_FAILURE(rv)) {
   2671                 return rv;
   2672             }
   2673 
   2674             if (pri_map != BCM_TSN_PRI_MAP_INVALID) {
   2675                 /* Get HW memory base index with given pri_map */
   2676                 BCM_IF_ERROR_RETURN(
   2677                     bcmi_esw_tsn_pri_map_hw_index_get(unit, pri_map,
   2678                                                       &map_type, &hw_id));
   2679                 if (map_type == bcmTsnPriMapTypeSrFlow) {
   2680                     soc_L2Xm_field32_set(unit, l2x_entry,
   2681                                          SR_PRI_OFFSET_PROFILEf, hw_id);
   2682                 } else {
   2683                     return BCM_E_CONFIG;
   2684                 }
   2685             }
   2686         }
   2687     }
   2688 #endif /* BCM_TSN_SR_SUPPORT */
   2689 
   2690     if (soc_feature(unit, soc_feature_tsn_taf)) {
   2691         if (BCM_TSN_PRI_MAP_INVALID != l2addr->taf_gate_primap) {
   2692             uint32 hw_index;
   2693             bcm_tsn_pri_map_type_t map;
   2694 
   2695             BCM_IF_ERROR_RETURN(
   2696                 bcmi_esw_tsn_pri_map_hw_index_get(
   2697                     unit, l2addr->taf_gate_primap, &map, &hw_index));
   2698 
   2699             if (map != bcmTsnPriMapTypeTafGate) {
   2700                 return BCM_E_PARAM;
   2701             }
   2702 
   2703             soc_L2Xm_field32_set(unit, l2x_entry,
   2704                                  TAF_GATE_ID_PROFILEf,
   2705                                  hw_index);
   2706         } else {
   2707             soc_L2Xm_field32_set(unit, l2x_entry,
   2708                                  TAF_GATE_ID_PROFILEf,
   2709                                  0);
   2710         }
   2711     }
   2712 #endif /* BCM_TSN_SUPPORT */
   2713     return rv;
   2714 }
   2715 
   2716 /*
   2717  * Function:
   2718  *      _bcm_tr_l2_from_ext_l2
   2719  * Purpose:
   2720  *      Convert an EXT_L2_ENTRY to an L2 API data structure
   2721 
   2722  * Parameters:
   2723  *      unit         Unit number
   2724  *      l2addr       (OUT) L2 API data structure
   2725  *      ext_l2_entry EXT_L2_ENTRY hardware entry
   2726  */
   2727 int
   2728 _bcm_tr_l2_from_ext_l2(int unit, bcm_l2_addr_t *l2addr,
   2729                        ext_l2_entry_entry_t *ext_l2_entry)
   2730 {
   2731     _bcm_gport_dest_t       dest;
   2732     int                     mb_index, vfi;
   2733     bcm_module_t            mod;
   2734     bcm_port_t              port;
   2735     int  isGport = 0;
   2736 
   2737     sal_memset(l2addr, 0, sizeof(*l2addr));
   2738 
   2739      if (soc_mem_field32_get(unit, EXT_L2_ENTRYm, ext_l2_entry,
   2740                              KEY_TYPE_VFIf) == 1) {
   2741          vfi = soc_mem_field32_get(unit, EXT_L2_ENTRYm, ext_l2_entry, VFIf);
   2742          COMPILER_REFERENCE(vfi);
   2743          /* VPLS or MIM VPN */
   2744 #if defined(INCLUDE_L3)
   2745          if (_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeMpls)) {
   2746               _BCM_MPLS_VPN_SET(l2addr->vid, _BCM_MPLS_VPN_TYPE_VPLS, vfi);
   2747          } else {
   2748               _BCM_MIM_VPN_SET(l2addr->vid, _BCM_MIM_VPN_TYPE_MIM, vfi);
   2749          }
   2750 #endif
   2751     } else {
   2752          l2addr->vid = soc_mem_field32_get(unit, EXT_L2_ENTRYm, ext_l2_entry,
   2753                                            VLAN_IDf);
   2754     }
   2755 
   2756     soc_mem_mac_addr_get(unit, EXT_L2_ENTRYm, ext_l2_entry, MAC_ADDRf,
   2757                          l2addr->mac);
   2758 
   2759     _bcm_gport_dest_t_init(&dest);
   2760 #if defined(INCLUDE_L3)
   2761     if (soc_mem_field32_get(unit, EXT_L2_ENTRYm, ext_l2_entry, DEST_TYPEf) == 0x2) {
   2762          int vp;
   2763 
   2764          vp = soc_mem_field32_get(unit, EXT_L2_ENTRYm,ext_l2_entry,  DESTINATIONf);
   2765          if (soc_mem_field32_get(unit, EXT_L2_ENTRYm, ext_l2_entry, KEY_TYPE_VFIf) == 0x1) {
   2766               /* MPLS/MiM virtual port unicast */
   2767               if (_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) {
   2768                    dest.mpls_id = vp;
   2769                    dest.gport_type = _SHR_GPORT_TYPE_MPLS_PORT;
   2770                    isGport=1;
   2771               } else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeMim)) {
   2772                    dest.mim_id = vp;
   2773                    dest.gport_type = _SHR_GPORT_TYPE_MIM_PORT;
   2774                    isGport=1;
   2775               } else {
   2776                    /* The VP is deleted before clearing the L2 entry. 
   2777                    SDK will report this entry with gport invalid during
   2778                    traverse so the entry can be removed from the L2 table */
   2779                    dest.gport_type = BCM_GPORT_INVALID;
   2780                    isGport=0;
   2781               }
   2782          } else {
   2783              /* Subport/WLAN unicast */
   2784              if (_bcm_vp_used_get(unit, vp, _bcmVpTypeSubport)) {
   2785                  dest.subport_id = vp;
   2786                  dest.gport_type = _SHR_GPORT_TYPE_SUBPORT_GROUP;
   2787                  isGport=1;
   2788              } else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeWlan)) {
   2789                  dest.wlan_id = vp;
   2790                  dest.gport_type = _SHR_GPORT_TYPE_WLAN_PORT;
   2791                  isGport=1;
   2792              } else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeVlan)) {
   2793                  dest.vlan_vp_id = vp;
   2794                  dest.gport_type = _SHR_GPORT_TYPE_VLAN_PORT;
   2795                  isGport=1;
   2796              } else {
   2797                    /* The VP is deleted before clearing the L2 entry. 
   2798                    SDK will report this entry with gport invalid during
   2799                    traverse so the entry can be removed from the L2 table */
   2800                    dest.gport_type = BCM_GPORT_INVALID;
   2801                    isGport=0;
   2802              }
   2803          }
   2804     } else {
   2805 #endif /* INCLUDE_L3 */
   2806         if (soc_mem_field32_get(unit, EXT_L2_ENTRYm, ext_l2_entry, Tf)) {
   2807             int psc = 0;
   2808             l2addr->tgid = soc_mem_field32_get(unit, EXT_L2_ENTRYm,
   2809                                                ext_l2_entry, TGIDf);
   2810             bcm_esw_trunk_psc_get(unit, l2addr->tgid, &psc);
   2811             dest.tgid = l2addr->tgid;
   2812             dest.gport_type = _SHR_GPORT_TYPE_TRUNK;
   2813 
   2814             l2addr->flags |= BCM_L2_TRUNK_MEMBER;
   2815             if (soc_mem_field32_get(unit, EXT_L2_ENTRYm, ext_l2_entry,
   2816                                     REMOTE_TRUNKf)) {
   2817                 l2addr->flags |= BCM_L2_REMOTE_TRUNK;
   2818             }
   2819         } else {
   2820             mod = soc_mem_field32_get(unit, EXT_L2_ENTRYm, ext_l2_entry,
   2821                                       MODULE_IDf);
   2822             port = soc_mem_field32_get(unit, EXT_L2_ENTRYm, ext_l2_entry,
   2823                                        PORT_NUMf);
   2824             BCM_IF_ERROR_RETURN(_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET,
   2825                                                        mod, port, &mod, &port));
   2826             l2addr->modid = mod;
   2827             l2addr->port = port;
   2828             dest.port = l2addr->port;
   2829             dest.modid = l2addr->modid;
   2830             dest.gport_type = _SHR_GPORT_TYPE_MODPORT;
   2831         }
   2832         BCM_IF_ERROR_RETURN(bcm_esw_switch_control_get(unit, bcmSwitchUseGport,
   2833                                                       &isGport));
   2834 #if defined(INCLUDE_L3)
   2835     }
   2836 #endif /* INCLUDE_L3 */
   2837 	
   2838     if (isGport) {
   2839          BCM_IF_ERROR_RETURN
   2840              (_bcm_esw_gport_construct(unit, &dest, &l2addr->port));
   2841     }
   2842 
   2843     if (SOC_CONTROL(unit)->l2x_group_enable) {
   2844         l2addr->group = soc_mem_field32_get(unit, EXT_L2_ENTRYm, ext_l2_entry,
   2845                                             CLASS_IDf);
   2846     } else {
   2847         mb_index = soc_mem_field32_get(unit, EXT_L2_ENTRYm, ext_l2_entry,
   2848                                        MAC_BLOCK_INDEXf);
   2849         if (mb_index) {
   2850             BCM_PBMP_ASSIGN(l2addr->block_bitmap,
   2851                             _mbi_entries[unit][mb_index].mb_pbmp);
   2852         }
   2853     }
   2854 
   2855     if (soc_mem_field32_get(unit, EXT_L2_ENTRYm, ext_l2_entry, RPEf)) {
   2856         l2addr->flags |= BCM_L2_SETPRI;
   2857     }
   2858 
   2859     l2addr->cos_dst = soc_mem_field32_get(unit, EXT_L2_ENTRYm, ext_l2_entry,
   2860                                           PRIf);
   2861     l2addr->cos_src = l2addr->cos_dst;
   2862 
   2863     if (soc_mem_field32_get(unit, EXT_L2_ENTRYm, ext_l2_entry, CPUf)) {
   2864         l2addr->flags |= BCM_L2_COPY_TO_CPU;
   2865     }
   2866 
   2867     if (soc_mem_field32_get(unit, EXT_L2_ENTRYm, ext_l2_entry, DST_DISCARDf)) {
   2868         l2addr->flags |= BCM_L2_DISCARD_DST;
   2869     }
   2870 
   2871     if (soc_mem_field32_get(unit, EXT_L2_ENTRYm, ext_l2_entry, SRC_DISCARDf)) {
   2872         l2addr->flags |= BCM_L2_DISCARD_SRC;
   2873     }
   2874 
   2875     if (soc_mem_field32_get(unit, EXT_L2_ENTRYm, ext_l2_entry, SCPf)) {
   2876         l2addr->flags |= BCM_L2_COS_SRC_PRI;
   2877     }
   2878 
   2879     if (soc_mem_field32_get(unit, EXT_L2_ENTRYm, ext_l2_entry, STATIC_BITf)) {
   2880         l2addr->flags |= BCM_L2_STATIC;
   2881     }
   2882 
   2883     if (soc_mem_field32_get(unit, EXT_L2_ENTRYm, ext_l2_entry, DST_HITf)) {
   2884         l2addr->flags |= BCM_L2_DES_HIT;
   2885         l2addr->flags |= BCM_L2_HIT;
   2886     }
   2887 
   2888     if (soc_mem_field32_get(unit, EXT_L2_ENTRYm, ext_l2_entry, SRC_HITf)) {
   2889         l2addr->flags |= BCM_L2_SRC_HIT;
   2890         l2addr->flags |= BCM_L2_HIT;
   2891     }
   2892 
   2893     if (SOC_MEM_FIELD_VALID(unit, EXT_L2_ENTRYm, LIMIT_COUNTEDf)) {
   2894         if ((!(l2addr->flags & BCM_L2_STATIC)) || 
   2895             l2addr->flags & BCM_L2_LEARN_LIMIT ) {
   2896             if (!soc_L2Xm_field32_get(unit, ext_l2_entry, LIMIT_COUNTEDf)) {
   2897                 l2addr->flags |= BCM_L2_LEARN_LIMIT_EXEMPT;
   2898             }
   2899         }
   2900     }
   2901 
   2902     return BCM_E_NONE;
   2903 }
   2904 
   2905 /*
   2906  * Function:
   2907  *      _bcm_tr_l2_to_ext_l2
   2908  * Purpose:
   2909  *      Convert an L2 API data structure to an EXT_L2_ENTRY
   2910  * Parameters:
   2911  *      unit         Unit number
   2912  *      ext_l2_entry (OUT) EXT_L2_ENTRY hardware entry
   2913  *      l2addr       L2 API data structure
   2914  *      key_only     Only construct key portion
   2915  */
   2916 int
   2917 _bcm_tr_l2_to_ext_l2(int unit, ext_l2_entry_entry_t *ext_l2_entry,
   2918                      bcm_l2_addr_t *l2addr, int key_only)
   2919 {
   2920     _bcm_l2_gport_params_t  g_params;
   2921     bcm_module_t            mod;
   2922     bcm_port_t              port;
   2923     uint32                  fval;
   2924 
   2925     /*  BCM_L2_MIRROR is not supported starting from Triumph */
   2926     if (l2addr->flags & BCM_L2_MIRROR) {
   2927         return BCM_E_PARAM;
   2928     }
   2929 
   2930     sal_memset(ext_l2_entry, 0, sizeof(*ext_l2_entry));
   2931 
   2932     if (_BCM_MPLS_VPN_IS_VPLS(l2addr->vid)) {
   2933         _BCM_MPLS_VPN_GET(fval, _BCM_MPLS_VPN_TYPE_VPLS, l2addr->vid);
   2934         if (!SOC_MEM_FIELD32_VALUE_FIT(unit, EXT_L2_ENTRYm, VFIf, fval)) {
   2935             return BCM_E_PARAM;
   2936         }
   2937         soc_mem_field32_set(unit, EXT_L2_ENTRYm, ext_l2_entry, VFIf, fval);
   2938         soc_mem_field32_set(unit, EXT_L2_ENTRYm, ext_l2_entry, KEY_TYPE_VFIf,
   2939                             1);
   2940     } else if (_BCM_IS_MIM_VPN(l2addr->vid)) {
   2941         _BCM_MIM_VPN_GET(fval, _BCM_MIM_VPN_TYPE_MIM,  l2addr->vid);
   2942         if (!SOC_MEM_FIELD32_VALUE_FIT(unit, EXT_L2_ENTRYm, VFIf, fval)) {
   2943             return BCM_E_PARAM;
   2944         }
   2945         soc_mem_field32_set(unit, EXT_L2_ENTRYm, ext_l2_entry, VFIf, fval);
   2946         soc_mem_field32_set(unit, EXT_L2_ENTRYm, ext_l2_entry, KEY_TYPE_VFIf,
   2947                             1);
   2948     } else {
   2949         if (!SOC_MEM_FIELD32_VALUE_FIT(unit, EXT_L2_ENTRYm, VLAN_IDf,
   2950                                        l2addr->vid)) {
   2951             return BCM_E_PARAM;
   2952         }
   2953         soc_mem_field32_set(unit, EXT_L2_ENTRYm, ext_l2_entry, VLAN_IDf,
   2954                             l2addr->vid);
   2955     }
   2956 
   2957     soc_mem_mac_addr_set(unit, EXT_L2_ENTRYm, ext_l2_entry, MAC_ADDRf,
   2958                          l2addr->mac);
   2959 
   2960     if (key_only) {
   2961         return BCM_E_NONE;
   2962     }
   2963 
   2964     if (!BCM_GPORT_IS_SET(l2addr->port)) {
   2965         if (l2addr->flags & BCM_L2_TRUNK_MEMBER) {
   2966             g_params.param0 = l2addr->tgid;
   2967             g_params.type = _SHR_GPORT_TYPE_TRUNK;
   2968         } else {
   2969             PORT_DUALMODID_VALID(unit, l2addr->port);
   2970             BCM_IF_ERROR_RETURN(_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_SET,
   2971                                                        l2addr->modid, l2addr->port,
   2972                                                        &mod, &port));
   2973             g_params.param0 = port;
   2974             g_params.param1 = mod;
   2975             g_params.type = _SHR_GPORT_TYPE_MODPORT;
   2976         }
   2977     } else {
   2978         BCM_IF_ERROR_RETURN(_bcm_esw_l2_gport_parse(unit, l2addr, &g_params));
   2979     }
   2980 
   2981     switch (g_params.type) {
   2982     case _SHR_GPORT_TYPE_TRUNK:
   2983         if (!SOC_MEM_FIELD32_VALUE_FIT(unit, EXT_L2_ENTRYm, TGIDf,
   2984                                        g_params.param0)) {
   2985             return BCM_E_PARAM;
   2986         }
   2987         soc_mem_field32_set(unit, EXT_L2_ENTRYm, ext_l2_entry, Tf, 1);
   2988         soc_mem_field32_set(unit, EXT_L2_ENTRYm, ext_l2_entry, TGIDf,
   2989                             g_params.param0);
   2990         if (l2addr->flags & BCM_L2_REMOTE_TRUNK) {
   2991             soc_mem_field32_set(unit, EXT_L2_ENTRYm, ext_l2_entry,
   2992                                 REMOTE_TRUNKf, 1);
   2993         }
   2994         break;
   2995     case _SHR_GPORT_TYPE_MODPORT:
   2996         if (!SOC_MODID_ADDRESSABLE(unit, g_params.param1)) {
   2997             return BCM_E_BADID;
   2998         }
   2999         if (!SOC_PORT_ADDRESSABLE(unit, g_params.param0)) {
   3000             return BCM_E_PORT;
   3001         }
   3002         soc_mem_field32_set(unit, EXT_L2_ENTRYm, ext_l2_entry, MODULE_IDf,
   3003                             g_params.param1);
   3004         soc_mem_field32_set(unit, EXT_L2_ENTRYm, ext_l2_entry, PORT_NUMf,
   3005                             g_params.param0);
   3006         break;
   3007     case _SHR_GPORT_TYPE_LOCAL_CPU:
   3008         if (!SOC_PORT_ADDRESSABLE(unit, g_params.param0)) {
   3009             return BCM_E_PORT;
   3010         }
   3011         soc_mem_field32_set(unit, EXT_L2_ENTRYm, ext_l2_entry, PORT_NUMf,
   3012                             g_params.param0);
   3013         BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &mod));
   3014         soc_mem_field32_set(unit, EXT_L2_ENTRYm, ext_l2_entry, MODULE_IDf,
   3015                             mod);
   3016         break;
   3017     case _SHR_GPORT_TYPE_MPLS_PORT:
   3018         if (!SOC_MEM_FIELD32_VALUE_FIT(unit, EXT_L2_ENTRYm, DESTINATIONf,
   3019                                        g_params.param0)) {
   3020             return BCM_E_PARAM;
   3021         }
   3022         soc_mem_field32_set(unit, EXT_L2_ENTRYm, ext_l2_entry, DESTINATIONf,
   3023                             g_params.param0);
   3024         soc_mem_field32_set(unit, EXT_L2_ENTRYm, ext_l2_entry, DEST_TYPEf, 0x2);
   3025         break;
   3026     case _SHR_GPORT_TYPE_MIM_PORT:
   3027     case _SHR_GPORT_TYPE_SUBPORT_GROUP:
   3028     case _SHR_GPORT_TYPE_SUBPORT_PORT:
   3029     case _SHR_GPORT_TYPE_VLAN_PORT:
   3030         if (!SOC_MEM_FIELD32_VALUE_FIT(unit, EXT_L2_ENTRYm, VPGf,
   3031                                        g_params.param0)) {
   3032             return BCM_E_PARAM;
   3033         }
   3034         soc_mem_field32_set(unit, EXT_L2_ENTRYm, ext_l2_entry, VPGf,
   3035                             g_params.param0);
   3036         soc_mem_field32_set(unit, EXT_L2_ENTRYm, ext_l2_entry, VPG_TYPEf, 1);
   3037         break;
   3038     default:
   3039         return BCM_E_PORT;
   3040     }
   3041 
   3042     if (SOC_CONTROL(unit)->l2x_group_enable) {
   3043         soc_mem_field32_set(unit, EXT_L2_ENTRYm, ext_l2_entry, CLASS_IDf,
   3044                             l2addr->group);
   3045     } /* else MAC_BLOCK_INDEXf is handled in the add/remove functions */
   3046 
   3047     if (l2addr->flags & BCM_L2_SETPRI) {
   3048         soc_mem_field32_set(unit, EXT_L2_ENTRYm, ext_l2_entry, RPEf, 1);
   3049     }
   3050     /* coverity[large_shift : FALSE] */
   3051     if (!SOC_MEM_FIELD32_VALUE_FIT(unit, EXT_L2_ENTRYm, PRIf,
   3052                                    l2addr->cos_dst)) {
   3053         return BCM_E_PARAM;
   3054     }
   3055     soc_mem_field32_set(unit, EXT_L2_ENTRYm, ext_l2_entry, PRIf,
   3056                         l2addr->cos_dst);
   3057 
   3058     if (l2addr->flags & BCM_L2_COPY_TO_CPU) {
   3059         soc_mem_field32_set(unit, EXT_L2_ENTRYm, ext_l2_entry, CPUf, 1);
   3060     }
   3061 
   3062     if (l2addr->flags & BCM_L2_DISCARD_DST) {
   3063         soc_mem_field32_set(unit, EXT_L2_ENTRYm, ext_l2_entry, DST_DISCARDf,
   3064                             1);
   3065     }
   3066 
   3067     if (l2addr->flags & BCM_L2_DISCARD_SRC) {
   3068         soc_mem_field32_set(unit, EXT_L2_ENTRYm, ext_l2_entry, SRC_DISCARDf,
   3069                             1);
   3070     }
   3071 
   3072     if (l2addr->flags & BCM_L2_COS_SRC_PRI) {
   3073         soc_mem_field32_set(unit, EXT_L2_ENTRYm, ext_l2_entry, SCPf, 1);
   3074     }
   3075 
   3076     if (l2addr->flags & BCM_L2_STATIC) {
   3077         soc_mem_field32_set(unit, EXT_L2_ENTRYm, ext_l2_entry, STATIC_BITf, 1);
   3078     }
   3079 
   3080     soc_mem_field32_set(unit, EXT_L2_ENTRYm, ext_l2_entry, VALIDf, 1);
   3081 
   3082     if ((l2addr->flags & BCM_L2_DES_HIT) ||
   3083         (l2addr->flags & BCM_L2_HIT)) {
   3084         soc_mem_field32_set(unit, EXT_L2_ENTRYm, ext_l2_entry, DST_HITf, 1);
   3085     }
   3086 
   3087     if ((l2addr->flags & BCM_L2_SRC_HIT) ||
   3088         (l2addr->flags & BCM_L2_HIT)) {
   3089         soc_mem_field32_set(unit, EXT_L2_ENTRYm, ext_l2_entry, SRC_HITf, 1);
   3090     }
   3091 
   3092     if (SOC_MEM_FIELD_VALID(unit, EXT_L2_ENTRYm, LIMIT_COUNTEDf)) {
   3093         if ((!(l2addr->flags & (BCM_L2_L3LOOKUP | BCM_L2_MCAST | BCM_L2_STATIC |
   3094                                BCM_L2_LEARN_LIMIT_EXEMPT))) || 
   3095             l2addr->flags & BCM_L2_LEARN_LIMIT) {
   3096             soc_mem_field32_set(unit, EXT_L2_ENTRYm, ext_l2_entry,
   3097                                 LIMIT_COUNTEDf, 1);
   3098         }
   3099     }
   3100 
   3101     return BCM_E_NONE;
   3102 }
   3103 
   3104 /*
   3105  * Function:
   3106  *     _bcm_tr_compose_ext_l2_entry
   3107  * Description:
   3108  *      Compose ext_l2_entry from its tcam portion, data portion, and hit bit
   3109  *      Hardware does not support read and write to ext_l2_entry view.
   3110  * Parameters:
   3111  *      unit         Device number
   3112  *      tcam_entry   TCAM portion of ESM L2 entry (ext_l2_entry_tcam_entry_t)
   3113  *      data_entry   DATA portion of ESM L2 entry (ext_l2_entry_data_entry_t)
   3114  *      src_hit      SRC_HIT field value
   3115  *      dst_hit      DST_HIT field value
   3116  *      ext_l2_entry (OUT) Buffer to store the composed ext_l2_entry_entry_t
   3117  *                   result
   3118  * Return:
   3119  *      BCM_E_XXX.
   3120  */
   3121 int
   3122 _bcm_tr_compose_ext_l2_entry(int unit,
   3123                              ext_l2_entry_tcam_entry_t *tcam_entry,
   3124                              ext_l2_entry_data_entry_t *data_entry,
   3125                              int src_hit,
   3126                              int dst_hit,
   3127                              ext_l2_entry_entry_t *ext_l2_entry)
   3128 {
   3129     sal_mac_addr_t      mac;
   3130     uint32              fval;
   3131     uint32              fbuf[2];
   3132 
   3133     if (tcam_entry == NULL || data_entry == NULL || ext_l2_entry == NULL) {
   3134         return BCM_E_PARAM;
   3135     }
   3136 
   3137     sal_memset(ext_l2_entry, 0, sizeof(ext_l2_entry_entry_t));
   3138 
   3139     /******************** Values from TCAM *******************************/
   3140     fval = soc_mem_field32_get(unit, EXT_L2_ENTRY_TCAMm, tcam_entry, VLAN_IDf);
   3141     soc_mem_field32_set(unit, EXT_L2_ENTRYm, ext_l2_entry, VLAN_IDf, fval);
   3142 
   3143     soc_mem_mac_addr_get(unit, EXT_L2_ENTRY_TCAMm, tcam_entry, MAC_ADDRf, mac);
   3144     soc_mem_mac_addr_set(unit, EXT_L2_ENTRYm, ext_l2_entry, MAC_ADDRf, mac);
   3145 
   3146     fval = soc_mem_field32_get(unit, EXT_L2_ENTRY_TCAMm, tcam_entry,
   3147                                KEY_TYPE_VFIf);
   3148     soc_mem_field32_set(unit, EXT_L2_ENTRYm, ext_l2_entry, KEY_TYPE_VFIf,
   3149                         fval);
   3150 
   3151     /******************** Values from DATA *******************************/
   3152     soc_mem_field_get(unit, EXT_L2_ENTRY_DATAm, (uint32 *)data_entry,
   3153                       AD_EXT_L2f, fbuf);
   3154     soc_mem_field_set(unit, EXT_L2_ENTRYm, (uint32 *)ext_l2_entry, AD_EXT_L2f,
   3155                       fbuf);
   3156 
   3157     fval = soc_mem_field32_get(unit, EXT_L2_ENTRY_DATAm, data_entry, VALIDf);
   3158     soc_mem_field32_set(unit, EXT_L2_ENTRYm, ext_l2_entry, VALIDf, fval);
   3159 
   3160     /******************** Hit Bits *******************************/
   3161     soc_mem_field32_set(unit, EXT_L2_ENTRYm, ext_l2_entry, DST_HITf, dst_hit);
   3162     soc_mem_field32_set(unit, EXT_L2_ENTRYm, ext_l2_entry, SRC_HITf, src_hit);
   3163 
   3164     return BCM_E_NONE;
   3165 }
   3166 
   3167 /*
   3168  * function:
   3169  *     _bcm_tr_l2_traverse_mem
   3170  * Description:
   3171  *      Helper function to _bcm_esw_l2_traverse to itterate over given memory
   3172  *      and actually read the table and parse entries for Triumph external
   3173  *      memory
   3174  * Parameters:
   3175  *     unit         device number
   3176  *      mem         External L2 memory to read
   3177  *     trav_st      Traverse structure with all the data.
   3178  * Return:
   3179  *     BCM_E_XXX
   3180  */
   3181 #ifdef BCM_TRIUMPH_SUPPORT
   3182 int
   3183 _bcm_tr_l2_traverse_mem(int unit, soc_mem_t mem, _bcm_l2_traverse_t *trav_st)
   3184 {
   3185     _soc_tr_l2e_ppa_info_t    *ppa_info;
   3186     ext_l2_entry_entry_t      ext_l2_entry;
   3187     ext_l2_entry_tcam_entry_t tcam_entry;
   3188     ext_l2_entry_data_entry_t data_entry;
   3189     ext_src_hit_bits_l2_entry_t src_hit_entry;
   3190     ext_dst_hit_bits_l2_entry_t dst_hit_entry;
   3191     int                       src_hit, dst_hit;
   3192     int                       idx, idx_max;
   3193 
   3194     if (mem != EXT_L2_ENTRYm) {
   3195         return BCM_E_UNAVAIL;
   3196     }
   3197 
   3198     if (!soc_mem_index_count(unit, mem)) {
   3199         return BCM_E_NONE;
   3200     }
   3201 
   3202     ppa_info = SOC_CONTROL(unit)->ext_l2_ppa_info;
   3203     if (ppa_info == NULL) {
   3204         return BCM_E_NONE;
   3205     }
   3206 
   3207     idx_max = soc_mem_index_max(unit, mem);
   3208     for (idx = soc_mem_index_min(unit, mem); idx <= idx_max; idx++ ) {
   3209         if (!(ppa_info[idx].data & _SOC_TR_L2E_VALID)) {
   3210             continue;
   3211         }
   3212         SOC_IF_ERROR_RETURN
   3213             (soc_mem_read(unit, EXT_L2_ENTRY_TCAMm, MEM_BLOCK_ANY, idx,
   3214                           &tcam_entry));
   3215         SOC_IF_ERROR_RETURN
   3216             (soc_mem_read(unit, EXT_L2_ENTRY_DATAm, MEM_BLOCK_ANY, idx,
   3217                           &data_entry));
   3218         SOC_IF_ERROR_RETURN
   3219             (soc_mem_read(unit, EXT_SRC_HIT_BITS_L2m, MEM_BLOCK_ANY, idx >> 5,
   3220                           &src_hit_entry));
   3221         SOC_IF_ERROR_RETURN
   3222             (soc_mem_read(unit, EXT_DST_HIT_BITS_L2m, MEM_BLOCK_ANY, idx >> 5,
   3223                           &dst_hit_entry));
   3224         src_hit = (soc_mem_field32_get
   3225                    (unit, EXT_SRC_HIT_BITS_L2m, &src_hit_entry, SRC_HITf) >>
   3226                    (idx & 0x1f)) & 1;
   3227         dst_hit = (soc_mem_field32_get
   3228                    (unit, EXT_DST_HIT_BITS_L2m, &dst_hit_entry, DST_HITf) >>
   3229                    (idx & 0x1f)) & 1;
   3230         BCM_IF_ERROR_RETURN
   3231             (_bcm_tr_compose_ext_l2_entry(unit, &tcam_entry, &data_entry,
   3232                                           src_hit, dst_hit, &ext_l2_entry));
   3233         trav_st->data = (uint32 *)&ext_l2_entry;
   3234         trav_st->mem = mem;
   3235 
   3236         BCM_IF_ERROR_RETURN(trav_st->int_cb(unit, trav_st));
   3237     }
   3238 
   3239     return BCM_E_NONE;
   3240 }
   3241 #endif /* BCM_TRIUMPH_SUPPORT */
   3242 
   3243 /*
   3244  * Function:
   3245  *      _bcm_mac_block_insert
   3246  * Purpose:
   3247  *      Find or create a MAC_BLOCK table entry matching the given bitmap.
   3248  * Parameters:
   3249  *      unit - Unit number
   3250  *      mb_pbmp - egress port bitmap for source MAC blocking
   3251  *      mb_index - (OUT) Index of MAC_BLOCK table with bitmap.
   3252  * Returns:
   3253  *      BCM_E_NONE              Success
   3254  *      BCM_E_INTERNAL          Chip access failure
   3255  *      BCM_E_RESOURCE          No more MAC_BLOCK entries available
   3256  *      BCM_E_PARAM             Bad bitmap supplied
   3257  */
   3258 static int
   3259 _bcm_mac_block_insert(int unit, bcm_pbmp_t mb_pbmp, int *mb_index)
   3260 {
   3261     int cur_index = 0;
   3262     _bcm_mac_block_info_t *mbi = _mbi_entries[unit];
   3263     mac_block_entry_t mbe;
   3264     bcm_pbmp_t temp_pbmp;
   3265 #if defined(BCM_KATANA2_SUPPORT)
   3266     uint32     fldbuf[SOC_PBMP_WORD_MAX];
   3267     bcm_pbmp_t mb_pbmp0, mb_pbmp1;
   3268     int        mask_w0_width = 0;
   3269     int        mask_w1_width = 0;
   3270     int        i = 0;
   3271 
   3272     SOC_PBMP_CLEAR(mb_pbmp0);
   3273     SOC_PBMP_CLEAR(mb_pbmp1);
   3274 #endif
   3275 
   3276     /* Check for reasonable pbmp */
   3277     BCM_PBMP_ASSIGN(temp_pbmp, mb_pbmp);
   3278     BCM_PBMP_AND(temp_pbmp, PBMP_ALL(unit));
   3279     if (BCM_PBMP_NEQ(mb_pbmp, temp_pbmp)) {
   3280         return BCM_E_PARAM;
   3281     }
   3282 
   3283     for (cur_index = 0; cur_index < _mbi_num[unit]; cur_index++) {
   3284         if (BCM_PBMP_EQ(mbi[cur_index].mb_pbmp, mb_pbmp)) {
   3285             mbi[cur_index].ref_count++;
   3286             *mb_index = cur_index;
   3287             return BCM_E_NONE;
   3288         }
   3289     }
   3290 
   3291     /* Not in table already, see if any space free */
   3292     for (cur_index = 1; cur_index < _mbi_num[unit]; cur_index++) {
   3293         if (mbi[cur_index].ref_count == 0) {
   3294             /* Attempt insert */
   3295             sal_memset(&mbe, 0, sizeof(mac_block_entry_t));
   3296 
   3297             if (soc_mem_field_valid(unit, MAC_BLOCKm, MAC_BLOCK_MASK_LOf)) {
   3298 #if defined(BCM_GREYHOUND2_SUPPORT)
   3299                 if (SOC_IS_GREYHOUND2(unit)) {
   3300                     soc_mem_pbmp_field_set(unit, MAC_BLOCKm, &mbe, MAC_BLOCK_MASKf,
   3301                                            &mb_pbmp);
   3302                 } else
   3303 #endif /* BCM_GREYHOUND2_SUPPORT */
   3304                 {
   3305                 soc_MAC_BLOCKm_field32_set(unit, &mbe, MAC_BLOCK_MASK_LOf,
   3306                                            SOC_PBMP_WORD_GET(mb_pbmp, 0));
   3307                 }
   3308             } else if (soc_mem_field_valid(unit, MAC_BLOCKm,
   3309                                            MAC_BLOCK_MASK_W0f)) {
   3310 #if defined(BCM_KATANA2_SUPPORT)
   3311                 if (SOC_IS_KATANA2(unit)) {
   3312                     mask_w0_width = soc_mem_field_length(unit, MAC_BLOCKm,
   3313                                                          MAC_BLOCK_MASK_W0f);
   3314                     for (i = 0; i < mask_w0_width; i++) {
   3315                         if (SOC_PBMP_MEMBER(mb_pbmp, i)) {
   3316                             SOC_PBMP_PORT_ADD(mb_pbmp0, i);
   3317                         }
   3318                     }
   3319 
   3320                     sal_memset(fldbuf, 0, SOC_PBMP_WORD_MAX * sizeof(uint32));
   3321                     for (i = 0; i < SOC_PBMP_WORD_MAX; i++) {
   3322                         fldbuf[i] = SOC_PBMP_WORD_GET(mb_pbmp0, i);
   3323                     }
   3324                     soc_MAC_BLOCKm_field_set(unit, &mbe,
   3325                                              MAC_BLOCK_MASK_W0f, fldbuf);
   3326                 } else
   3327 #endif /* BCM_KATANA2_SUPPORT */
   3328                 {
   3329                     soc_MAC_BLOCKm_field32_set(unit, &mbe, MAC_BLOCK_MASK_W0f,
   3330                                            SOC_PBMP_WORD_GET(mb_pbmp, 0));
   3331                 }
   3332             } else if (soc_mem_field_valid(unit, MAC_BLOCKm,
   3333                                            MAC_BLOCK_MASKf)) {
   3334                 soc_mem_pbmp_field_set(unit, MAC_BLOCKm, &mbe, MAC_BLOCK_MASKf,
   3335                                        &mb_pbmp); 
   3336             } else {
   3337                 return BCM_E_INTERNAL;
   3338             }
   3339             if (soc_mem_field_valid(unit, MAC_BLOCKm, MAC_BLOCK_MASK_HIf)) {
   3340                 soc_MAC_BLOCKm_field32_set(unit, &mbe, MAC_BLOCK_MASK_HIf,
   3341                                            SOC_PBMP_WORD_GET(mb_pbmp, 1));
   3342             } else if (soc_mem_field_valid(unit, MAC_BLOCKm, MAC_BLOCK_MASK_W1f)) {
   3343 #if defined(BCM_KATANA2_SUPPORT)
   3344                 if (SOC_IS_KATANA2(unit)) {
   3345                     mask_w1_width = soc_mem_field_length(unit, MAC_BLOCKm,
   3346                                                          MAC_BLOCK_MASK_W1f);
   3347 
   3348                     for (i = mask_w0_width;
   3349                          i < (mask_w0_width + mask_w1_width); i++) {
   3350                         if (SOC_PBMP_MEMBER(mb_pbmp, i)) {
   3351                             SOC_PBMP_PORT_ADD(mb_pbmp1, (i - mask_w0_width));
   3352                         }
   3353                     }
   3354 
   3355                     sal_memset(fldbuf, 0, SOC_PBMP_WORD_MAX * sizeof(uint32));
   3356                     for (i = 0; i < SOC_PBMP_WORD_MAX; i++) {
   3357                         fldbuf[i] = SOC_PBMP_WORD_GET(mb_pbmp1, i);
   3358                     }
   3359                     soc_MAC_BLOCKm_field_set(unit, &mbe,
   3360                                              MAC_BLOCK_MASK_W1f, fldbuf);
   3361                 } else
   3362 #endif /* BCM_KATANA2_SUPPORT */
   3363                 {
   3364                     soc_MAC_BLOCKm_field32_set(unit, &mbe, MAC_BLOCK_MASK_W1f,
   3365                                            SOC_PBMP_WORD_GET(mb_pbmp, 1));
   3366                 }
   3367             }
   3368             if (soc_mem_field_valid(unit, MAC_BLOCKm, MAC_BLOCK_MASK_W2f)) {
   3369 #if defined(BCM_TRIDENT_SUPPORT)
   3370                 if (SOC_IS_TRIDENT(unit)) {
   3371                     soc_MAC_BLOCKm_field32_set(unit, &mbe, MAC_BLOCK_MASK_W2f,
   3372                                                SOC_PBMP_WORD_GET(mb_pbmp, 2));
   3373                 }
   3374 #endif
   3375             }
   3376 
   3377             SOC_IF_ERROR_RETURN(WRITE_MAC_BLOCKm(unit, MEM_BLOCK_ALL,
   3378                                                  cur_index, &mbe));
   3379             mbi[cur_index].ref_count++;
   3380             BCM_PBMP_ASSIGN(mbi[cur_index].mb_pbmp, mb_pbmp);
   3381             *mb_index = cur_index;
   3382             return BCM_E_NONE;
   3383         }
   3384     }
   3385 
   3386     /* Didn't find a free slot, out of table space */
   3387     return BCM_E_RESOURCE;
   3388 }
   3389 
   3390 /*
   3391  * Function:
   3392  *      _bcm_mac_block_delete
   3393  * Purpose:
   3394  *      Remove reference to MAC_BLOCK table entry matching the given bitmap.
   3395  * Parameters:
   3396  *      unit - Unit number
   3397  *      mb_index - Index of MAC_BLOCK table with bitmap.
   3398  */
   3399 static void
   3400 _bcm_mac_block_delete(int unit, int mb_index)
   3401 {
   3402     if (_mbi_entries[unit][mb_index].ref_count > 0) {
   3403         _mbi_entries[unit][mb_index].ref_count--;
   3404     } else if (mb_index) {
   3405         
   3406         /* Someone reran init without flushing the L2 table */
   3407     } /* else mb_index = 0, as expected for learning */
   3408 }
   3409 
   3410 #ifdef BCM_TRIUMPH_SUPPORT
   3411 STATIC int
   3412 _bcm_tr_l2e_ppa_match(int unit, _bcm_l2_replace_t *rep_st)
   3413 {
   3414     _soc_tr_l2e_ppa_info_t      *ppa_info;
   3415     _soc_tr_l2e_ppa_vlan_t      *ppa_vlan;
   3416     int                         i, imin, imax, rv, nmatches;
   3417     soc_mem_t                   mem;
   3418     uint32                      entdata, entmask, entvalue, newdata, newmask;
   3419     ext_l2_entry_entry_t        l2entry, old_l2entry;
   3420     int                         same_dest;
   3421 
   3422     ppa_info = SOC_CONTROL(unit)->ext_l2_ppa_info;
   3423     ppa_vlan = SOC_CONTROL(unit)->ext_l2_ppa_vlan;
   3424     if (ppa_info == NULL) {
   3425         return BCM_E_NONE;
   3426     }
   3427 
   3428     mem = EXT_L2_ENTRYm;
   3429     imin = soc_mem_index_min(unit, mem);
   3430     imax = soc_mem_index_max(unit, mem);
   3431 
   3432     /* convert match data */
   3433     entdata = _SOC_TR_L2E_VALID;
   3434     entmask = _SOC_TR_L2E_VALID;
   3435     if (!(rep_st->flags & BCM_L2_REPLACE_MATCH_STATIC)) {
   3436         entdata |= 0x00000000;
   3437         entmask |= _SOC_TR_L2E_STATIC;
   3438     }
   3439     if (rep_st->flags & BCM_L2_REPLACE_MATCH_VLAN) {
   3440         entdata |= (rep_st->key_vlan & _SOC_TR_L2E_VLAN_MASK) <<
   3441             _SOC_TR_L2E_VLAN_SHIFT;
   3442         entmask |= _SOC_TR_L2E_VLAN_MASK << _SOC_TR_L2E_VLAN_SHIFT;
   3443         imin = ppa_vlan->vlan_min[rep_st->key_vlan];
   3444         imax = ppa_vlan->vlan_max[rep_st->key_vlan];
   3445     }
   3446     if (rep_st->flags & BCM_L2_REPLACE_MATCH_DEST) {
   3447         if (rep_st->match_dest.trunk != -1) {
   3448             entdata |= _SOC_TR_L2E_T |
   3449                 ((rep_st->match_dest.trunk & _SOC_TR_L2E_TRUNK_MASK)
   3450                  << _SOC_TR_L2E_TRUNK_SHIFT);
   3451             entmask |= _SOC_TR_L2E_T |
   3452                 (_SOC_TR_L2E_TRUNK_MASK << _SOC_TR_L2E_TRUNK_SHIFT);
   3453         } else {
   3454             entdata |= 
   3455                 ((rep_st->match_dest.module & _SOC_TR_L2E_MOD_MASK) <<
   3456                  _SOC_TR_L2E_MOD_SHIFT) |
   3457                 ((rep_st->match_dest.port & _SOC_TR_L2E_PORT_MASK) <<
   3458                  _SOC_TR_L2E_PORT_SHIFT);
   3459             entmask |= _SOC_TR_L2E_T |
   3460                 (_SOC_TR_L2E_MOD_MASK << _SOC_TR_L2E_MOD_SHIFT) |
   3461                 (_SOC_TR_L2E_PORT_MASK << _SOC_TR_L2E_PORT_SHIFT);
   3462         }
   3463     }
   3464 
   3465     nmatches = 0;
   3466 
   3467     if (imin >= 0) {
   3468         soc_mem_lock(unit, mem);
   3469         for (i = imin; i <= imax; i++) {
   3470             entvalue = ppa_info[i].data;
   3471             if ((entvalue & entmask) != entdata) {
   3472                 continue;
   3473             }
   3474             if (rep_st->flags & BCM_L2_REPLACE_MATCH_MAC) {
   3475                 if (ENET_CMP_MACADDR(rep_st->key_mac, ppa_info[i].mac)) {
   3476                     continue;
   3477                 }
   3478             }
   3479             nmatches += 1;
   3480 
   3481             /* lookup the matched entry */
   3482             sal_memset(&l2entry, 0, sizeof(l2entry));
   3483             soc_mem_field32_set(unit, mem, &l2entry, VLAN_IDf,
   3484                                 (entvalue >> 16) & 0xfff);
   3485             soc_mem_mac_addr_set(unit, mem, &l2entry, MAC_ADDRf,
   3486                                  ppa_info[i].mac);
   3487 
   3488             /* operate on matched entry */
   3489             if (rep_st->flags & BCM_L2_REPLACE_DELETE) {
   3490                 int             mb_index;
   3491 
   3492                 /* coverity[value_overwrite] */
   3493                 rv = soc_mem_generic_delete(unit, mem, MEM_BLOCK_ANY, 0,
   3494                                             &l2entry, &l2entry, NULL);
   3495                 if (rv < 0) {
   3496                     soc_mem_unlock(unit, mem);
   3497                     return rv;
   3498                 }
   3499                 if (!SOC_CONTROL(unit)->l2x_group_enable) {
   3500                     mb_index = soc_mem_field32_get(unit, mem, &l2entry,
   3501                                                    MAC_BLOCK_INDEXf);
   3502                     _bcm_mac_block_delete(unit, mb_index);
   3503                 }
   3504                 if (entvalue & _SOC_TR_L2E_LIMIT_COUNTED) {
   3505                     /* coverity[returned_value] */
   3506                     rv = soc_triumph_learn_count_update(unit, &l2entry,
   3507                                                         TRUE, -1);
   3508                 }
   3509             } else {
   3510                 /* replace destination fields */
   3511                 /* coverity[value_overwrite] */
   3512                 rv = soc_mem_generic_lookup(unit, mem, MEM_BLOCK_ANY, 0,
   3513                                             &l2entry, &l2entry, NULL);
   3514                 if (rep_st->flags & BCM_L2_REPLACE_NEW_TRUNK) {
   3515                     newdata = _SOC_TR_L2E_T |
   3516                         ((rep_st->new_dest.trunk & _SOC_TR_L2E_TRUNK_MASK) <<
   3517                          _SOC_TR_L2E_TRUNK_SHIFT);
   3518                     newmask = _SOC_TR_L2E_T |
   3519                         (_SOC_TR_L2E_TRUNK_MASK << _SOC_TR_L2E_TRUNK_SHIFT);
   3520                     soc_mem_field32_set(unit, mem, &l2entry, Tf, 1);
   3521                     soc_mem_field32_set(unit, mem, &l2entry, TGIDf,
   3522                                         rep_st->new_dest.trunk);
   3523                 } else {
   3524                     newdata =
   3525                         (rep_st->new_dest.module << _SOC_TR_L2E_MOD_SHIFT) |
   3526                         (rep_st->new_dest.port << _SOC_TR_L2E_PORT_SHIFT);
   3527                     newmask = _SOC_TR_L2E_T |
   3528                         (_SOC_TR_L2E_MOD_MASK << _SOC_TR_L2E_MOD_SHIFT) |
   3529                         (_SOC_TR_L2E_PORT_MASK << _SOC_TR_L2E_PORT_SHIFT);
   3530                     soc_mem_field32_set(unit, mem, &l2entry, MODULE_IDf,
   3531                                         rep_st->new_dest.module);
   3532                     soc_mem_field32_set(unit, mem, &l2entry, PORT_NUMf,
   3533                                         rep_st->new_dest.port);
   3534                 }
   3535                 same_dest = !((entvalue ^ newdata) & newmask);
   3536 
   3537                 if ((entvalue & _SOC_TR_L2E_LIMIT_COUNTED) && !same_dest) {
   3538                     rv = soc_triumph_learn_count_update(unit, &l2entry, FALSE,
   3539                                                         1);
   3540                     if (SOC_FAILURE(rv)) {
   3541                         soc_mem_unlock(unit, mem);
   3542                         return rv;
   3543                     }
   3544                 }
   3545 
   3546                 /* re-insert entry */
   3547                 rv = soc_mem_generic_insert(unit, mem, MEM_BLOCK_ANY, 0,
   3548                                             &l2entry, &old_l2entry, NULL);
   3549                 if (rv == BCM_E_EXISTS) {
   3550                     rv = BCM_E_NONE;
   3551                 }
   3552                 if (rv < 0) {
   3553                     soc_mem_unlock(unit, mem);
   3554                     return rv;
   3555                 }
   3556                 if ((entvalue & _SOC_TR_L2E_LIMIT_COUNTED) && !same_dest) {
   3557                     rv = soc_triumph_learn_count_update(unit, &old_l2entry,
   3558                                                         FALSE, -1);
   3559                     if (SOC_FAILURE(rv)) {
   3560                         soc_mem_unlock(unit, mem);
   3561                         return rv;
   3562                     }
   3563                 }
   3564             }
   3565         }
   3566         soc_mem_unlock(unit, EXT_L2_ENTRYm);
   3567     }
   3568     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   3569                 (BSL_META_U(unit,
   3570                             "tr_l2e_ppa_match: imin=%d imax=%d nmatches=%d flags=0x%x\n"),
   3571                  imin, imax, nmatches, rep_st->flags));
   3572     return BCM_E_NONE;
   3573 }
   3574 #endif /* BCM_TRIUMPH_SUPPORT */
   3575 
   3576 /*
   3577  * Function:
   3578  *      _bcm_l2_hash_dynamic_replace
   3579  * Purpose:
   3580  *      Replace dynamic L2 entries in a dual hash.
   3581  * Parameters:
   3582  *      unit - Unit number
   3583  *      l2x_entry - Entry to insert instead of dynamic entry.
   3584  * Returns:
   3585  *      BCM_E_NONE              Success
   3586  *      BCM_E_XXX          		Error 
   3587  */
   3588 
   3589 int _bcm_l2_hash_dynamic_replace(int unit, l2x_entry_t *l2x_entry)
   3590 {
   3591     l2x_entry_t     l2ent;
   3592     int             rv;
   3593     uint32          fval;
   3594     bcm_mac_t       mac;
   3595     int             cf_hit, cf_unhit;
   3596     int             bank, bucket, slot, index;
   3597     int             num_banks;
   3598     int             entries_per_bank, entries_per_row, entries_per_bucket;
   3599     int             bank_base, bucket_offset;
   3600 
   3601 #ifdef BCM_APACHE_SUPPORT
   3602     if (SOC_IS_APACHE(unit)) {
   3603         BCM_IF_ERROR_RETURN
   3604             (soc_apache_hash_bank_count_get(unit, L2Xm, &num_banks));
   3605     } else
   3606 #endif /* BCM_APACHE_SUPPORT */
   3607 #ifdef BCM_HELIX5_SUPPORT
   3608     if (SOC_IS_HELIX5(unit)) {
   3609          BCM_IF_ERROR_RETURN
   3610             (soc_helix5_hash_bank_count_get(unit, L2Xm, &num_banks));
   3611     } else
   3612 #endif /* BCM_HELIX5_SUPPORT */
   3613 #ifdef BCM_TRIDENT3_SUPPORT
   3614     if (SOC_IS_TRIDENT3X(unit)) {
   3615         BCM_IF_ERROR_RETURN
   3616             (soc_trident3_hash_bank_count_get(unit, L2Xm, &num_banks));
   3617     } else
   3618 #endif /* BCM_TRIDENT3_SUPPORT */
   3619 #ifdef BCM_TRIDENT2_SUPPORT
   3620     if (!SOC_IS_TOMAHAWKX(unit) && SOC_IS_TD2_TT2(unit)) {
   3621         BCM_IF_ERROR_RETURN
   3622             (soc_trident2_hash_bank_count_get(unit, L2Xm, &num_banks));
   3623     } else
   3624 #endif /* BCM_TRIDENT2_SUPPORT */
   3625 #ifdef BCM_TOMAHAWK_SUPPORT
   3626     if (SOC_IS_TOMAHAWKX(unit)) {
   3627         BCM_IF_ERROR_RETURN
   3628             (soc_tomahawk_hash_bank_count_get(unit, L2Xm, &num_banks));
   3629     } else
   3630 #endif /* BCM_TOMAHAWK_SUPPORT */
   3631     {
   3632         num_banks = 2;
   3633     }
   3634 
   3635     BCM_IF_ERROR_RETURN(soc_l2x_freeze(unit));
   3636 
   3637     cf_hit = cf_unhit = -1;
   3638     for (bank = 0; bank < num_banks; bank++) {
   3639 #ifdef BCM_APACHE_SUPPORT
   3640         if (SOC_IS_APACHE(unit)) {
   3641             int phy_bank;
   3642             rv = soc_apache_hash_bank_number_get(unit, L2Xm, bank, &phy_bank);
   3643             if (SOC_FAILURE(rv)) {
   3644                 (void)soc_l2x_thaw(unit);
   3645                 return rv;
   3646             }
   3647 
   3648             rv = soc_apache_hash_bank_info_get(unit, L2Xm, phy_bank,
   3649                                                  &entries_per_bank,
   3650                                                  &entries_per_row,
   3651                                                  &entries_per_bucket,
   3652                                                  &bank_base, &bucket_offset);
   3653             if (SOC_FAILURE(rv)) {
   3654                 (void)soc_l2x_thaw(unit);
   3655                 return rv;
   3656             }
   3657             bucket = soc_ap_l2x_bank_entry_hash(unit, phy_bank,
   3658                                                 (uint32 *)l2x_entry);
   3659         } else
   3660 #endif /* BCM_APACHE_SUPPORT */
   3661 #ifdef BCM_HELIX5_SUPPORT
   3662         if (SOC_IS_HELIX5(unit)) {
   3663             int phy_bank;
   3664             rv = soc_hx5_hash_bank_number_get(unit, L2Xm, bank, &phy_bank);
   3665             if (SOC_FAILURE(rv)) {
   3666                 (void)soc_l2x_thaw(unit);
   3667                 return rv;
   3668             }
   3669             rv = soc_hx5_hash_bank_info_get(unit, L2Xm, phy_bank,
   3670                                             &entries_per_bank,
   3671                                             &entries_per_row,
   3672                                             &entries_per_bucket,
   3673                                             &bank_base, &bucket_offset);
   3674             if (SOC_FAILURE(rv)) {
   3675                 (void)soc_l2x_thaw(unit);
   3676                 return rv;
   3677             }
   3678             bucket = soc_hx5_l2x_bank_entry_hash(unit, phy_bank,
   3679                                                  (uint32 *)l2x_entry);
   3680         } else
   3681 #endif
   3682 #ifdef BCM_TRIDENT3_SUPPORT
   3683         if (SOC_IS_TRIDENT3X(unit)) {
   3684             int phy_bank;
   3685             rv = soc_td3_hash_bank_number_get(unit, L2Xm, bank, &phy_bank);
   3686             if (SOC_FAILURE(rv)) {
   3687                 (void)soc_l2x_thaw(unit);
   3688                 return rv;
   3689             }
   3690             rv = soc_td3_hash_bank_info_get(unit, L2Xm, phy_bank,
   3691                                             &entries_per_bank,
   3692                                             &entries_per_row,
   3693                                             &entries_per_bucket,
   3694                                             &bank_base, &bucket_offset);
   3695             if (SOC_FAILURE(rv)) {
   3696                 (void)soc_l2x_thaw(unit);
   3697                 return rv;
   3698             }
   3699             bucket = soc_td3_l2x_bank_entry_hash(unit, phy_bank,
   3700                                                  (uint32 *)l2x_entry);
   3701         } else
   3702 #endif
   3703 #ifdef BCM_TRIDENT2_SUPPORT
   3704         if (!SOC_IS_TOMAHAWKX(unit) && SOC_IS_TD2_TT2(unit)) {
   3705             int phy_bank;
   3706             rv = soc_trident2_hash_bank_number_get(unit, L2Xm, bank, &phy_bank);
   3707             if (SOC_FAILURE(rv)) {
   3708                 (void)soc_l2x_thaw(unit);
   3709                 return rv;
   3710             }
   3711             rv = soc_trident2_hash_bank_info_get(unit, L2Xm, phy_bank,
   3712                                                  &entries_per_bank,
   3713                                                  &entries_per_row,
   3714                                                  &entries_per_bucket,
   3715                                                  &bank_base, &bucket_offset);
   3716             if (SOC_FAILURE(rv)) {
   3717                 (void)soc_l2x_thaw(unit);
   3718                 return rv;
   3719             }
   3720             bucket = soc_td2_l2x_bank_entry_hash(unit, phy_bank,
   3721                                                  (uint32 *)l2x_entry);
   3722         } else
   3723 #endif
   3724 #ifdef BCM_TOMAHAWK_SUPPORT
   3725         if (SOC_IS_TOMAHAWKX(unit)) {
   3726             int phy_bank;
   3727             rv = soc_tomahawk_hash_bank_number_get(unit, L2Xm, bank, &phy_bank);
   3728             if (SOC_FAILURE(rv)) {
   3729                 (void)soc_l2x_thaw(unit);
   3730                 return rv;
   3731             }
   3732             rv = soc_tomahawk_hash_bank_info_get(unit, L2Xm, phy_bank,
   3733                                                  &entries_per_bank,
   3734                                                  &entries_per_row,
   3735                                                  &entries_per_bucket,
   3736                                                  &bank_base, &bucket_offset);
   3737             if (SOC_FAILURE(rv)) {
   3738                 (void)soc_l2x_thaw(unit);
   3739                 return rv;
   3740             }
   3741             bucket = soc_th_l2x_bank_entry_hash(unit, phy_bank,
   3742                                                  (uint32 *)l2x_entry);
   3743         } else
   3744 #endif
   3745         {
   3746             entries_per_bank = soc_mem_index_count(unit, L2Xm) / 2;
   3747             entries_per_row = SOC_L2X_BUCKET_SIZE;
   3748             entries_per_bucket = entries_per_row / 2;
   3749             bank_base = 0;
   3750             bucket_offset = bank * entries_per_bucket;
   3751             bucket = soc_tr_l2x_bank_entry_hash(unit, bank,
   3752                                                 (uint32 *)l2x_entry);
   3753         }
   3754 
   3755         for (slot = 0; slot < entries_per_bucket; slot++) {
   3756             uint32 valid = 0;
   3757             index = bank_base + bucket * entries_per_row + bucket_offset +
   3758                 slot;
   3759             rv = soc_mem_read(unit, L2Xm, MEM_BLOCK_ANY, index, &l2ent);
   3760             if (SOC_FAILURE(rv)) {
   3761                 (void)soc_l2x_thaw(unit);
   3762                 return rv;
   3763             }
   3764 
   3765             if (soc_feature(unit, soc_feature_base_valid)) {
   3766                 valid = soc_L2Xm_field32_get(unit, &l2ent, BASE_VALIDf);
   3767             } else {
   3768                 valid = soc_L2Xm_field32_get(unit, &l2ent, VALIDf);
   3769             }
   3770             if (!valid) {
   3771                 /* Found invalid entry - stop the search victim found */
   3772                 cf_unhit = index; 
   3773                 break;
   3774             }
   3775 
   3776             fval = soc_mem_field32_get(unit, L2Xm, &l2ent, KEY_TYPEf);
   3777 #ifdef BCM_TRIDENT2_SUPPORT
   3778             if (SOC_IS_TD2_TT2(unit)) {
   3779                 if (fval != TD2_L2_HASH_KEY_TYPE_BRIDGE &&
   3780                     fval != TD2_L2_HASH_KEY_TYPE_VFI) {
   3781                     continue;
   3782                 }
   3783             } else
   3784 #endif /* BCM_TRIDENT2_SUPPORT */
   3785             if (fval != TR_L2_HASH_KEY_TYPE_BRIDGE &&
   3786                 fval != TR_L2_HASH_KEY_TYPE_VFI) {
   3787                 continue;
   3788             }
   3789 
   3790             soc_L2Xm_mac_addr_get(unit, &l2ent, MAC_ADDRf, mac);
   3791             /* Skip static entries */
   3792             if ((soc_L2Xm_field32_get(unit, &l2ent, STATIC_BITf)) ||
   3793                 (BCM_MAC_IS_MCAST(mac)) ||
   3794                 (soc_mem_field_valid(unit, L2Xm, L3f) && 
   3795                  soc_L2Xm_field32_get(unit, &l2ent, L3f))) {
   3796                 continue;
   3797             }
   3798 
   3799             if (soc_L2Xm_field32_get(unit, &l2ent, HITDAf) || 
   3800                 soc_L2Xm_field32_get(unit, &l2ent, HITSAf) ) {
   3801                 cf_hit =  index;
   3802             } else {
   3803                 /* Found unhit entry - stop search victim found */
   3804                 cf_unhit = index;
   3805                 break;
   3806             }
   3807         }
   3808         if (cf_unhit != -1) {
   3809             break;
   3810         }
   3811     }
   3812 
   3813     COMPILER_REFERENCE(entries_per_bank);
   3814 
   3815     if (cf_unhit >= 0) {
   3816         index = cf_unhit;   /* take last unhit dynamic */
   3817     } else if (cf_hit >= 0) {
   3818         index = cf_hit;     /* or last hit dynamic */
   3819     } else {
   3820         rv = BCM_E_FULL;     /* no dynamics to delete */
   3821         (void) soc_l2x_thaw(unit);
   3822          return rv;
   3823     }
   3824 
   3825     rv = soc_mem_delete_index(unit, L2Xm, MEM_BLOCK_ALL, index);
   3826     if (SOC_SUCCESS(rv)) {
   3827         rv = soc_mem_generic_insert(unit, L2Xm, MEM_BLOCK_ANY, 0,
   3828                                     l2x_entry, NULL, NULL);
   3829     }
   3830     if (SOC_FAILURE(rv)) {
   3831         (void) soc_l2x_thaw(unit);
   3832         return rv;
   3833     }
   3834 
   3835     return soc_l2x_thaw(unit);
   3836 }
   3837 
   3838 /*
   3839  * Function:
   3840  *      _bcm_l2_hash_pending_override
   3841  * Purpose:
   3842  *      Override pending L2 entries in a dual hash.
   3843  * Parameters:
   3844  *      unit - Unit number
   3845  *      l2x_entry - Entry to insert instead of pending entry.
   3846  * Returns:
   3847  *      BCM_E_NONE              Success
   3848  *      BCM_E_XXX          		Error
   3849  */
   3850 
   3851 int _bcm_l2_hash_pending_override(int unit, l2x_entry_t *l2x_entry)
   3852 {
   3853     l2x_entry_t     l2ent;
   3854     int             rv;
   3855     uint32          fval;
   3856     bcm_mac_t       mac;
   3857     int             p_hit;
   3858     int             bank, bucket, slot, index;
   3859     int             num_banks;
   3860     int             entries_per_bank, entries_per_row, entries_per_bucket;
   3861     int             bank_base, bucket_offset;
   3862 
   3863 #ifdef BCM_APACHE_SUPPORT
   3864     if (SOC_IS_APACHE(unit)) {
   3865         BCM_IF_ERROR_RETURN
   3866             (soc_apache_hash_bank_count_get(unit, L2Xm, &num_banks));
   3867     } else
   3868 #endif /* BCM_APACHE_SUPPORT */
   3869 #ifdef BCM_HELIX5_SUPPORT
   3870     if (SOC_IS_HELIX5(unit)) {
   3871         BCM_IF_ERROR_RETURN
   3872             (soc_helix5_hash_bank_count_get(unit, L2Xm, &num_banks));
   3873     } else
   3874 #endif /* BCM_HELIX5_SUPPORT */
   3875 #ifdef BCM_TRIDENT3_SUPPORT
   3876     if (SOC_IS_TRIDENT3X(unit)) {
   3877         BCM_IF_ERROR_RETURN
   3878             (soc_trident3_hash_bank_count_get(unit, L2Xm, &num_banks));
   3879     } else
   3880 #endif /* BCM_TRIDENT3_SUPPORT */
   3881 #ifdef BCM_TRIDENT2_SUPPORT
   3882     if (!SOC_IS_TOMAHAWKX(unit) && SOC_IS_TD2_TT2(unit)) {
   3883         BCM_IF_ERROR_RETURN
   3884             (soc_trident2_hash_bank_count_get(unit, L2Xm, &num_banks));
   3885     } else
   3886 #endif /* BCM_TRIDENT2_SUPPORT */
   3887 #ifdef BCM_TOMAHAWK_SUPPORT
   3888     if (SOC_IS_TOMAHAWKX(unit)) {
   3889         BCM_IF_ERROR_RETURN
   3890             (soc_tomahawk_hash_bank_count_get(unit, L2Xm, &num_banks));
   3891     } else
   3892 #endif /* BCM_TOMAHAWK_SUPPORT */
   3893     {
   3894         num_banks = 2;
   3895     }
   3896 
   3897     BCM_IF_ERROR_RETURN(soc_l2x_freeze(unit));
   3898 
   3899     p_hit = -1;
   3900     for (bank = 0; bank < num_banks; bank++) {
   3901 #ifdef BCM_APACHE_SUPPORT
   3902         if (SOC_IS_APACHE(unit)) {
   3903             int phy_bank;
   3904             rv = soc_apache_hash_bank_number_get(unit, L2Xm, bank, &phy_bank);
   3905             if (SOC_FAILURE(rv)) {
   3906                 (void)soc_l2x_thaw(unit);
   3907                 return rv;
   3908             }
   3909 
   3910             rv = soc_apache_hash_bank_info_get(unit, L2Xm, phy_bank,
   3911                                                &entries_per_bank,
   3912                                                &entries_per_row,
   3913                                                &entries_per_bucket,
   3914                                                &bank_base, &bucket_offset);
   3915             if (SOC_FAILURE(rv)) {
   3916                 (void)soc_l2x_thaw(unit);
   3917                 return rv;
   3918             }
   3919             bucket = soc_ap_l2x_bank_entry_hash(unit, phy_bank,
   3920                                                 (uint32 *)l2x_entry);
   3921         } else
   3922 #endif /* BCM_APACHE_SUPPORT */
   3923 #ifdef BCM_HELIX5_SUPPORT
   3924         if (SOC_IS_HELIX5(unit)) {
   3925             int phy_bank;
   3926             rv = soc_hx5_hash_bank_number_get(unit, L2Xm, bank, &phy_bank);
   3927             if (SOC_FAILURE(rv)) {
   3928                 (void)soc_l2x_thaw(unit);
   3929                 return rv;
   3930             }
   3931             rv = soc_hx5_hash_bank_info_get(unit, L2Xm, phy_bank,
   3932                                             &entries_per_bank,
   3933                                             &entries_per_row,
   3934                                             &entries_per_bucket,
   3935                                             &bank_base, &bucket_offset);
   3936             if (SOC_FAILURE(rv)) {
   3937                 (void)soc_l2x_thaw(unit);
   3938                 return rv;
   3939             }
   3940             bucket = soc_hx5_l2x_bank_entry_hash(unit, phy_bank,
   3941                                                  (uint32 *)l2x_entry);
   3942         } else
   3943 #endif
   3944 #ifdef BCM_TRIDENT3_SUPPORT
   3945         if (SOC_IS_TRIDENT3X(unit)) {
   3946             int phy_bank;
   3947             rv = soc_td3_hash_bank_number_get(unit, L2Xm, bank, &phy_bank);
   3948             if (SOC_FAILURE(rv)) {
   3949                 (void)soc_l2x_thaw(unit);
   3950                 return rv;
   3951             }
   3952             rv = soc_td3_hash_bank_info_get(unit, L2Xm, phy_bank,
   3953                                             &entries_per_bank,
   3954                                             &entries_per_row,
   3955                                             &entries_per_bucket,
   3956                                             &bank_base, &bucket_offset);
   3957             if (SOC_FAILURE(rv)) {
   3958                 (void)soc_l2x_thaw(unit);
   3959                 return rv;
   3960             }
   3961             bucket = soc_td3_l2x_bank_entry_hash(unit, phy_bank,
   3962                                                  (uint32 *)l2x_entry);
   3963         } else
   3964 #endif
   3965 #ifdef BCM_TRIDENT2_SUPPORT
   3966         if (!SOC_IS_TOMAHAWKX(unit) && SOC_IS_TD2_TT2(unit)) {
   3967             int phy_bank;
   3968             rv = soc_trident2_hash_bank_number_get(unit, L2Xm, bank, &phy_bank);
   3969             if (SOC_FAILURE(rv)) {
   3970                 (void)soc_l2x_thaw(unit);
   3971                 return rv;
   3972             }
   3973             rv = soc_trident2_hash_bank_info_get(unit, L2Xm, phy_bank,
   3974                                                  &entries_per_bank,
   3975                                                  &entries_per_row,
   3976                                                  &entries_per_bucket,
   3977                                                  &bank_base, &bucket_offset);
   3978             if (SOC_FAILURE(rv)) {
   3979                 (void)soc_l2x_thaw(unit);
   3980                 return rv;
   3981             }
   3982             bucket = soc_td2_l2x_bank_entry_hash(unit, phy_bank,
   3983                                                  (uint32 *)l2x_entry);
   3984         } else
   3985 #endif
   3986 #ifdef BCM_TOMAHAWK_SUPPORT
   3987         if (SOC_IS_TOMAHAWKX(unit)) {
   3988             int phy_bank;
   3989             rv = soc_tomahawk_hash_bank_number_get(unit, L2Xm, bank, &phy_bank);
   3990             if (SOC_FAILURE(rv)) {
   3991                 (void)soc_l2x_thaw(unit);
   3992                 return rv;
   3993             }
   3994             rv = soc_tomahawk_hash_bank_info_get(unit, L2Xm, phy_bank,
   3995                                                  &entries_per_bank,
   3996                                                  &entries_per_row,
   3997                                                  &entries_per_bucket,
   3998                                                  &bank_base, &bucket_offset);
   3999             if (SOC_FAILURE(rv)) {
   4000                 (void)soc_l2x_thaw(unit);
   4001                 return rv;
   4002             }
   4003             bucket = soc_th_l2x_bank_entry_hash(unit, phy_bank,
   4004                                                 (uint32 *)l2x_entry);
   4005         } else
   4006 #endif
   4007         {
   4008             entries_per_bank = soc_mem_index_count(unit, L2Xm) / 2;
   4009             entries_per_row = SOC_L2X_BUCKET_SIZE;
   4010             entries_per_bucket = entries_per_row / 2;
   4011             bank_base = 0;
   4012             bucket_offset = bank * entries_per_bucket;
   4013             bucket = soc_tr_l2x_bank_entry_hash(unit, bank,
   4014                                                 (uint32 *)l2x_entry);
   4015         }
   4016 
   4017         for (slot = 0; slot < entries_per_bucket; slot++) {
   4018             uint32 valid = 0;
   4019             index = bank_base + bucket * entries_per_row + bucket_offset +
   4020                 slot;
   4021             rv = soc_mem_read(unit, L2Xm, MEM_BLOCK_ANY, index, &l2ent);
   4022             if (SOC_FAILURE(rv)) {
   4023                 (void)soc_l2x_thaw(unit);
   4024                 return rv;
   4025             }
   4026 
   4027             if (soc_feature(unit, soc_feature_base_valid)) {
   4028                 valid = soc_L2Xm_field32_get(unit, &l2ent, BASE_VALIDf);
   4029             } else {
   4030                 valid = soc_L2Xm_field32_get(unit, &l2ent, VALIDf);
   4031             }
   4032             if (!valid) {
   4033                 /* Found invalid entry - stop the search victim found */
   4034                 p_hit = index;
   4035                 break;
   4036             }
   4037 
   4038             fval = soc_mem_field32_get(unit, L2Xm, &l2ent, KEY_TYPEf);
   4039 #ifdef BCM_TRIDENT2_SUPPORT
   4040             if (SOC_IS_TD2_TT2(unit)) {
   4041                 if (fval != TD2_L2_HASH_KEY_TYPE_BRIDGE &&
   4042                     fval != TD2_L2_HASH_KEY_TYPE_VFI) {
   4043                     continue;
   4044                 }
   4045             } else
   4046 #endif /* BCM_TRIDENT2_SUPPORT */
   4047             if (fval != TR_L2_HASH_KEY_TYPE_BRIDGE &&
   4048                 fval != TR_L2_HASH_KEY_TYPE_VFI) {
   4049                 continue;
   4050             }
   4051 
   4052             soc_L2Xm_mac_addr_get(unit, &l2ent, MAC_ADDRf, mac);
   4053             /* Skip static entries */
   4054             if ((soc_L2Xm_field32_get(unit, &l2ent, STATIC_BITf)) ||
   4055                 (BCM_MAC_IS_MCAST(mac)) ||
   4056                 (soc_mem_field_valid(unit, L2Xm, L3f) &&
   4057                  soc_L2Xm_field32_get(unit, &l2ent, L3f))) {
   4058                 continue;
   4059             }
   4060 
   4061             if (soc_L2Xm_field32_get(unit, &l2ent, L2__PENDINGf)) {
   4062                 p_hit =  index;
   4063                 break;
   4064             }
   4065         }
   4066         if (p_hit != -1) {
   4067             break;
   4068         }
   4069     }
   4070 
   4071     COMPILER_REFERENCE(entries_per_bank);
   4072 
   4073     if (p_hit >= 0) {
   4074         index = p_hit;   /* take last hit pending */
   4075     } else {
   4076         rv = BCM_E_FULL; /* no pending entry to delete */
   4077         (void) soc_l2x_thaw(unit);
   4078          return rv;
   4079     }
   4080 
   4081     rv = soc_mem_delete_index(unit, L2Xm, MEM_BLOCK_ALL, index);
   4082     if (SOC_SUCCESS(rv)) {
   4083         rv = soc_mem_generic_insert(unit, L2Xm, MEM_BLOCK_ANY, 0,
   4084                                     l2x_entry, NULL, NULL);
   4085     }
   4086     if (SOC_FAILURE(rv)) {
   4087         (void) soc_l2x_thaw(unit);
   4088         return rv;
   4089     }
   4090 
   4091     return soc_l2x_thaw(unit);
   4092 }
   4093 
   4094 
   4095 /*
   4096  * Function:
   4097  *      bcm_bfd_l2_hash_dynamic_replace
   4098  * Purpose:
   4099  *      Replace dynamic L2 entries in a dual hash.
   4100  * Parameters:
   4101  *      unit - Unit number
   4102  *      l2x_entry - Entry to insert instead of dynamic entry.
   4103  * Returns:
   4104  *      BCM_E_NONE              Success
   4105  *      BCM_E_XXX               Error
   4106  */
   4107 
   4108 int bcm_bfd_l2_hash_dynamic_replace(int unit, l2x_entry_t *l2x_entry)
   4109 {
   4110     int rv;
   4111 
   4112 #if defined(BCM_TRIUMPH3_SUPPORT)
   4113     if (SOC_IS_TRIUMPH3(unit)) {
   4114         rv = bcm_tr3_bfd_l2_hash_dynamic_replace(unit, (void *)l2x_entry);
   4115     } else
   4116 #endif /* BCM_TRIUMPH3_SUPPORT */
   4117     {
   4118         rv = _bcm_l2_hash_dynamic_replace(unit, l2x_entry);
   4119     }
   4120 
   4121     return rv;
   4122 }
   4123 
   4124 #if defined(BCM_TRIDENT2_SUPPORT)
   4125 /*
   4126  * Function:
   4127  *      _bcm_td2_l2_hit_retrieve
   4128  * Purpose:
   4129  *      Retrieve the hit bit from both x and y pipe, then "or" the hitbit values and assign it to 
   4130  *      L2_ENTRY data structure.
   4131  * Parameters:
   4132  *      unit        Unit number
   4133  *      l2addr      (OUT) L2 API data structure
   4134  *      l2x_entry   L2X entry
   4135  *      l2_hw_index   L2X entry hardware index
   4136  */
   4137 int
   4138 _bcm_td2_l2_hit_retrieve(int unit, l2x_entry_t *l2x_entry,
   4139                                  int l2_hw_index)
   4140 { 
   4141     uint32 hit_sa, hit_da, hit_local_sa;          /* composite hit = hit_x|hit_y */    
   4142     int idx_offset, hit_idx_shift;
   4143     l2_hitsa_only_x_entry_t hit_sa_x;
   4144     l2_hitsa_only_y_entry_t hit_sa_y;
   4145     l2_hitda_only_x_entry_t hit_da_x;
   4146     l2_hitda_only_y_entry_t hit_da_y;  
   4147     soc_field_t hit_saf[] = { HITSA_0f, HITSA_1f, HITSA_2f, HITSA_3f};
   4148     soc_field_t hit_daf[] = { HITDA_0f, HITDA_1f, HITDA_2f, HITDA_3f};   
   4149     soc_field_t hit_local_saf[] = { LOCAL_SA_0f, LOCAL_SA_1f, 
   4150                                     LOCAL_SA_2f, LOCAL_SA_3f};     
   4151 
   4152     idx_offset = (l2_hw_index & 0x3);
   4153     hit_idx_shift = 2;
   4154 
   4155     /* Retrieve DA HIT */
   4156     BCM_IF_ERROR_RETURN(
   4157         BCM_XGS3_MEM_READ(unit, L2_HITDA_ONLY_Xm,
   4158           (l2_hw_index >> hit_idx_shift), &hit_da_x));
   4159     
   4160     BCM_IF_ERROR_RETURN(
   4161         BCM_XGS3_MEM_READ(unit, L2_HITDA_ONLY_Ym,
   4162           (l2_hw_index >> hit_idx_shift), &hit_da_y)); 
   4163 
   4164     hit_da = 0;
   4165     hit_da |= soc_mem_field32_get(unit, L2_HITDA_ONLY_Xm,
   4166                                    &hit_da_x, hit_daf[idx_offset]);
   4167     
   4168     hit_da |= soc_mem_field32_get(unit, L2_HITDA_ONLY_Ym,
   4169                                    &hit_da_y, hit_daf[idx_offset]);
   4170     
   4171     _BCM_L2X_MEMACC_FIELD32_SET(unit, l2x_entry, HITDA_f, hit_da);  
   4172 
   4173     /* Retrieve SA HIT */
   4174     BCM_IF_ERROR_RETURN(
   4175         BCM_XGS3_MEM_READ(unit, L2_HITSA_ONLY_Xm,
   4176           (l2_hw_index >> hit_idx_shift), &hit_sa_x));
   4177     
   4178     BCM_IF_ERROR_RETURN(
   4179         BCM_XGS3_MEM_READ(unit, L2_HITSA_ONLY_Ym,
   4180           (l2_hw_index >> hit_idx_shift), &hit_sa_y)); 
   4181 
   4182     hit_sa = 0;
   4183     hit_sa |= soc_mem_field32_get(unit, L2_HITSA_ONLY_Xm,
   4184                                    &hit_sa_x, hit_saf[idx_offset]);
   4185     
   4186     hit_sa |= soc_mem_field32_get(unit, L2_HITSA_ONLY_Ym,
   4187                                    &hit_sa_y, hit_saf[idx_offset]);
   4188     
   4189     _BCM_L2X_MEMACC_FIELD32_SET(unit, l2x_entry, HITSA_f, hit_sa);        
   4190     
   4191     /* Retrieve LOCAL_SA HIT */
   4192     hit_local_sa = 0;
   4193     hit_local_sa |= soc_mem_field32_get(unit, L2_HITSA_ONLY_Xm,
   4194                                    &hit_sa_x, hit_local_saf[idx_offset]);
   4195     
   4196     hit_local_sa |= soc_mem_field32_get(unit, L2_HITSA_ONLY_Ym,
   4197                                    &hit_sa_y, hit_local_saf[idx_offset]);
   4198     
   4199     _BCM_L2X_MEMACC_FIELD32_SET(unit, l2x_entry, LOCAL_SA_f, hit_local_sa);        
   4200     
   4201     return BCM_E_NONE;    
   4202 }
   4203 
   4204 /*
   4205  * Function:
   4206  *      _bcm_td2_l2_hit_range_retrieve
   4207  * Purpose:
   4208  *      Range retrieve the hit bit from both x and y pipe
   4209  * Parameters:
   4210  *      unit         (IN) Unit number
   4211  *      mem          (IN) Unit number
   4212  *      idx_min      (IN) L2 API data structure
   4213  *      idx_max      (IN) L2X entry
   4214  *      l2_tbl_chnk  (OUT) L2X entry chunck
   4215  */
   4216 int
   4217 _bcm_td2_l2_hit_range_retrieve(int unit, soc_mem_t mem, int idx_min,
   4218                                int idx_max, uint32 *l2_tbl_chnk)
   4219 {
   4220     int rv = BCM_E_NONE;
   4221     int i, ent_idx, ent_idx_end;
   4222     int buf_size, offset, hit_idx_shift;
   4223     int valid, key_type;
   4224     uint32 *l2_entry;
   4225     uint32 *l2_hit_ptr;
   4226     struct _l2_hit_chnk_t {
   4227         soc_mem_t mem;
   4228         uint32 *_hit_chnk;
   4229     } _td2_l2_hitda[] = {{L2_HITDA_ONLY_Xm, NULL},{L2_HITDA_ONLY_Ym, NULL}},
   4230       _td2_l2_hitsa[] = {{L2_HITSA_ONLY_Xm, NULL},{L2_HITSA_ONLY_Ym, NULL}},
   4231       *_l2_hitda = NULL,
   4232       *_l2_hitsa = NULL;
   4233     int _l2_hitda_cnt;
   4234     int _l2_hitsa_cnt;
   4235     int hit_da, hit_sa, hit_local_sa;
   4236 
   4237     _l2_hitda = &_td2_l2_hitda[0];
   4238     _l2_hitsa = &_td2_l2_hitsa[0];
   4239     _l2_hitda_cnt = COUNTOF(_td2_l2_hitda);
   4240     _l2_hitsa_cnt = COUNTOF(_td2_l2_hitsa);
   4241 
   4242 
   4243     hit_idx_shift = 2;
   4244 
   4245     /* HITDA */
   4246     for (i = 0; i < _l2_hitda_cnt; i++) {
   4247         buf_size = 4 * SOC_MAX_MEM_FIELD_WORDS * ((idx_max - idx_min + 3) / 4);
   4248         _l2_hitda[i]._hit_chnk = soc_cm_salloc(unit, buf_size, "l2 hit range");
   4249         if (NULL == _l2_hitda[i]._hit_chnk) {
   4250             rv = BCM_E_MEMORY;
   4251             goto clean_up;
   4252         }
   4253         rv = soc_mem_read_range(unit, _l2_hitda[i].mem, MEM_BLOCK_ANY,
   4254                                 (idx_min >> hit_idx_shift), 
   4255                                 (idx_max >> hit_idx_shift), 
   4256                                 _l2_hitda[i]._hit_chnk);
   4257         if (SOC_FAILURE(rv)) {
   4258             goto clean_up;
   4259         }
   4260     }
   4261 
   4262     /* HITSA */
   4263     for (i = 0; i < _l2_hitsa_cnt; i++) {
   4264         buf_size = 4 * SOC_MAX_MEM_FIELD_WORDS * ((idx_max - idx_min + 3) / 4);
   4265         _l2_hitsa[i]._hit_chnk = soc_cm_salloc(unit, buf_size, "l2 hit range");
   4266         if (NULL == _l2_hitsa[i]._hit_chnk) {
   4267             rv = BCM_E_MEMORY;
   4268             goto clean_up;
   4269         }
   4270         rv = soc_mem_read_range(unit, _l2_hitsa[i].mem, MEM_BLOCK_ANY,
   4271                                 (idx_min >> hit_idx_shift), 
   4272                                 (idx_max >> hit_idx_shift), 
   4273                                 _l2_hitsa[i]._hit_chnk);
   4274         if (SOC_FAILURE(rv)) {
   4275             goto clean_up;
   4276         }
   4277     }
   4278 
   4279     ent_idx_end = idx_max - idx_min;
   4280     for (ent_idx = 0; ent_idx <= ent_idx_end; ent_idx++) {
   4281         l2_entry = soc_mem_table_idx_to_pointer(unit, mem, uint32 *, 
   4282                                                 l2_tbl_chnk, ent_idx);
   4283         valid = _BCM_L2X_MEMACC_FIELD32_GET(unit, l2_entry, VALID_f);
   4284         key_type = _BCM_L2X_MEMACC_FIELD32_GET(unit, l2_entry, KEY_TYPE_f);
   4285 
   4286         if (!valid || (key_type != TR_L2_HASH_KEY_TYPE_BRIDGE && 
   4287                        key_type != TR_L2_HASH_KEY_TYPE_VFI)) {
   4288             continue;
   4289         }
   4290         offset = (ent_idx & 0x3);
   4291         /* Retrieve DA HIT */
   4292         hit_da = 0;
   4293         for (i = 0; i < _l2_hitda_cnt; i++) {
   4294             l2_hit_ptr = soc_mem_table_idx_to_pointer(unit, _l2_hitda[i].mem,
   4295                                             uint32 *, _l2_hitda[i]._hit_chnk,
   4296                                             (ent_idx >> hit_idx_shift));
   4297             if (!hit_da) {
   4298                 hit_da |= _TD2_L2HIT_MEMACC_FIELD32_GET(unit, 
   4299                                 _TD2_L2HIT_MEM(unit, L2HITDA, i), l2_hit_ptr, 
   4300                                 _TD2_L2HIT_FIELD(unit, L2HITDA,
   4301                                                  HITDA_f, offset));
   4302             }
   4303         }
   4304         _BCM_L2X_MEMACC_FIELD32_SET(unit, l2_entry, HITDA_f, hit_da);  
   4305 
   4306         /* Retrieve SA and LOCAL_SA HIT */
   4307         hit_sa = 0;
   4308         hit_local_sa = 0;
   4309         for (i = 0; i < _l2_hitsa_cnt; i++) {
   4310             l2_hit_ptr = soc_mem_table_idx_to_pointer(unit, _l2_hitsa[i].mem,
   4311                                             uint32 *, _l2_hitsa[i]._hit_chnk,
   4312                                             (ent_idx >> hit_idx_shift));
   4313             if (!hit_sa) {
   4314                 hit_sa |= _TD2_L2HIT_MEMACC_FIELD32_GET(unit, 
   4315                                 _TD2_L2HIT_MEM(unit, L2HITSA, i), l2_hit_ptr,
   4316                                 _TD2_L2HIT_FIELD(unit, L2HITSA,
   4317                                                  HITSA_f, offset));
   4318             }
   4319             if (!hit_local_sa) {
   4320                 hit_local_sa |= _TD2_L2HIT_MEMACC_FIELD32_GET(unit,
   4321                                 _TD2_L2HIT_MEM(unit, L2HITSA, i), l2_hit_ptr,
   4322                                 _TD2_L2HIT_FIELD(unit, L2HITSA, 
   4323                                                  LOCAL_SA_f, offset));
   4324             }
   4325         }
   4326         
   4327         _BCM_L2X_MEMACC_FIELD32_SET(unit, l2_entry, HITSA_f, hit_sa);        
   4328         _BCM_L2X_MEMACC_FIELD32_SET(unit, l2_entry, LOCAL_SA_f, hit_local_sa);        
   4329     }
   4330 
   4331 clean_up:
   4332     for (i = 0; i < _l2_hitda_cnt; i++) {
   4333         if (_l2_hitda[i]._hit_chnk) {
   4334             soc_cm_sfree(unit, _l2_hitda[i]._hit_chnk);
   4335         }
   4336     }
   4337     for (i = 0; i < _l2_hitsa_cnt; i++) {
   4338         if (_l2_hitsa[i]._hit_chnk) {
   4339             soc_cm_sfree(unit, _l2_hitsa[i]._hit_chnk);
   4340         }
   4341     }
   4342     
   4343     return (rv);    
   4344 }
   4345 #endif /* BCM_TRIDENT2_SUPPORT */
   4346 
   4347 /*
   4348  * Function:
   4349  *      bcm_tr_l2_addr_add
   4350  * Description:
   4351  *      Add a MAC address to the Switch Address Resolution Logic (ARL)
   4352  *      port with the given VLAN ID and parameters.
   4353  * Parameters:
   4354  *      unit - StrataSwitch PCI device unit number (driver internal).
   4355  *      l2addr - Pointer to bcm_l2_addr_t containing all valid fields
   4356  * Returns:
   4357  *      BCM_E_NONE              Success
   4358  *      BCM_E_INTERNAL          Chip access failure
   4359  *      BCM_E_RESOURCE          No MAC_BLOCK entries available
   4360  * Notes:
   4361  *      Use CMIC_PORT(unit) to associate the entry with the CPU.
   4362  *      Use flag of BCM_L2_COPY_TO_CPU to send a copy to the CPU.
   4363  *      Use flag of BCM_L2_TRUNK_MEMBER to set trunking (TGID must be
   4364  *      passed as well with non-zero trunk group ID)
   4365  *      In case the L2X table is full (e.g. bucket full), an attempt
   4366  *      will be made to store the entry in the L2_USER_ENTRY table.
   4367  */
   4368 int
   4369 bcm_tr_l2_addr_add(int unit, bcm_l2_addr_t *l2addr)
   4370 {
   4371     l2x_entry_t  l2x_entry, l2x_lookup, l2x_old;
   4372 #ifdef BCM_TRIUMPH_SUPPORT
   4373     _soc_tr_l2e_ppa_info_t *ppa_info;
   4374     ext_l2_entry_entry_t ext_l2_entry, ext_l2_lookup;
   4375     int          exist_in_ext_l2, same_dest, update_limit, limit_counted;
   4376     int          rv1, ext_l2_index;
   4377 #endif /* BCM_TRIUMPH_SUPPORT */
   4378     int          enable_ppa_war;
   4379     int          rv, l2_index, mb_index = 0;
   4380 #if defined(BCM_TSN_SUPPORT)
   4381     bcm_l2_addr_t old_l2addr;
   4382     int is_tsn_or_sr_flow = FALSE; /* TSN or SR related flow */
   4383 #if defined(BCM_TSN_SR_SUPPORT)
   4384     int mp_index = 0; /* TSN SR MAC Proxy profile index */
   4385     bcm_pbmp_t mp_pbmp;
   4386 #endif /* BCM_TSN_SR_SUPPORT */
   4387 #endif /* BCM_TSN_SUPPORT */
   4388 #ifdef BCM_TRIDENT3_SUPPORT
   4389     int         l2_flex_view = FALSE;
   4390     uint32      view_id;
   4391     uint32      action_set;
   4392 #endif /* BCM_TRIDENT_SUPPORT */
   4393 #if defined(BCM_GLOBAL_METER_SUPPORT)
   4394     uint32 associated_data_type = 0;
   4395 #endif /* BCM_GLOBAL_METER_SUPPORT */
   4396     int rv2 = 0;
   4397     int goto_done = 0;
   4398     int rv_exists = 0;
   4399     int fifo_modified = 0;
   4400     uint32 rval = 0;
   4401     uint32 l2_insert = 0;
   4402     uint32 l2_delete = 0;
   4403 
   4404 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_GREYHOUND2_SUPPORT)
   4405     if (SOC_IS_TRIDENT(unit) || SOC_IS_KATANAX(unit) ||
   4406          SOC_IS_TD2_TT2(unit) || soc_feature(unit, soc_feature_gh2_my_station)) {
   4407         if (soc_mem_is_valid(unit, MY_STATION_TCAMm) &&
   4408             (l2addr->flags & BCM_L2_L3LOOKUP)) {
   4409             BCM_IF_ERROR_RETURN(bcm_td_l2_myStation_add(unit, l2addr));
   4410         }
   4411         else if (soc_mem_is_valid(unit, MY_STATION_TCAMm) &&
   4412                 !(l2addr->flags & BCM_L2_L3LOOKUP)) {
   4413             /* If VPN specified do not perform myStation delete */
   4414             if (!_BCM_VPN_VFI_IS_SET(l2addr->vid)) {
   4415                 rv = bcm_td_l2_myStation_delete(unit, 
   4416                             l2addr->mac, l2addr->vid, &l2_index);
   4417                 if (rv != BCM_E_NONE && rv != BCM_E_NOT_FOUND) {
   4418                     return rv;
   4419                 }
   4420             }
   4421         }
   4422     }
   4423 #endif /* BCM_TRIDENT_SUPPORT || BCM_GREYHOUND2_SUPPORT */
   4424 
   4425     BCM_IF_ERROR_RETURN(_bcm_tr_l2_to_l2x(unit, &l2x_entry, l2addr, FALSE));
   4426 
   4427 #ifdef BCM_TRIDENT3_SUPPORT
   4428     if (soc_feature(unit, soc_feature_flex_flow) &&
   4429         (l2addr->flow_handle != 0)) {
   4430 
   4431         l2_flex_view = TRUE;
   4432        /* Get view id corresponding to the specified flow. */
   4433         rv = soc_flow_db_ffo_to_mem_view_id_get(unit,
   4434                               l2addr->flow_handle,
   4435                               l2addr->flow_option_handle,
   4436                               SOC_FLOW_DB_FUNC_L2_SWITCH_ID,
   4437                               &view_id);
   4438         BCM_IF_ERROR_RETURN(rv);
   4439     }
   4440 #endif /* BCM_TRIDENT3_SUPPORT */
   4441 
   4442 #ifdef BCM_TRIUMPH_SUPPORT
   4443     exist_in_ext_l2 = FALSE;
   4444     ppa_info = SOC_CONTROL(unit)->ext_l2_ppa_info;
   4445     if (soc_mem_is_valid(unit, EXT_L2_ENTRYm) &&
   4446         soc_mem_index_count(unit, EXT_L2_ENTRYm) > 0) {
   4447         same_dest = FALSE;
   4448         update_limit =
   4449             (l2addr->flags & (BCM_L2_STATIC | BCM_L2_LEARN_LIMIT_EXEMPT) && 
   4450              !(l2addr->flags & BCM_L2_LEARN_LIMIT)) ? FALSE : TRUE;
   4451         limit_counted = FALSE;
   4452         BCM_IF_ERROR_RETURN
   4453             (_bcm_tr_l2_to_ext_l2(unit, &ext_l2_entry, l2addr, FALSE));
   4454         soc_mem_lock(unit, EXT_L2_ENTRYm);
   4455         rv1 = soc_mem_generic_lookup(unit, EXT_L2_ENTRYm, MEM_BLOCK_ANY, 0,
   4456                                      &ext_l2_entry, &ext_l2_lookup,
   4457                                      &ext_l2_index);
   4458         if (SOC_SUCCESS(rv1)) {
   4459             exist_in_ext_l2 = TRUE;
   4460         } else if (rv1 != SOC_E_NOT_FOUND) {
   4461             soc_mem_unlock(unit, EXT_L2_ENTRYm);
   4462             return rv1;
   4463         }
   4464 
   4465         if (!(l2addr->flags & (BCM_L2_L3LOOKUP | BCM_L2_MCAST |
   4466                                BCM_L2_PENDING | BCM_L2_STATIC))) {
   4467             if (exist_in_ext_l2) {
   4468                 if (soc_mem_field32_get(unit, EXT_L2_ENTRYm, &ext_l2_entry,
   4469                                         DEST_TYPEf) ==
   4470                     soc_mem_field32_get(unit, EXT_L2_ENTRYm, &ext_l2_lookup,
   4471                                         DEST_TYPEf) &&
   4472                     soc_mem_field32_get(unit, EXT_L2_ENTRYm, &ext_l2_entry,
   4473                                         DESTINATIONf) ==
   4474                     soc_mem_field32_get(unit, EXT_L2_ENTRYm, &ext_l2_lookup,
   4475                                         DESTINATIONf)) {
   4476                     same_dest = TRUE;
   4477                 }
   4478                 limit_counted =
   4479                     ppa_info[ext_l2_index].data & _SOC_TR_L2E_LIMIT_COUNTED;
   4480             }
   4481             if (update_limit) {
   4482                 rv1 = SOC_E_NONE;
   4483                 if (!limit_counted) {
   4484                     rv1 = soc_triumph_learn_count_update(unit, &ext_l2_entry,
   4485                                                          TRUE, 1);
   4486                 } else if (!same_dest) {
   4487                     rv1 = soc_triumph_learn_count_update(unit, &ext_l2_entry,
   4488                                                          FALSE, 1);
   4489                 }
   4490                 if (SOC_FAILURE(rv1)) {
   4491                     soc_mem_unlock(unit, EXT_L2_ENTRYm);
   4492                     return rv1;
   4493                 }
   4494             }
   4495             if (!SOC_CONTROL(unit)->l2x_group_enable) {
   4496                 /* Mac blocking, attempt to associate with bitmap entry */
   4497                 rv1 = _bcm_mac_block_insert(unit, l2addr->block_bitmap,
   4498                                            &mb_index);
   4499                 if (SOC_FAILURE(rv1)) {
   4500                     soc_mem_unlock(unit, EXT_L2_ENTRYm);
   4501                     return rv1;
   4502                 }
   4503                 soc_mem_field32_set(unit, EXT_L2_ENTRYm, &ext_l2_entry,
   4504                                     MAC_BLOCK_INDEXf, mb_index);
   4505             }
   4506             rv = soc_mem_generic_insert(unit, EXT_L2_ENTRYm, MEM_BLOCK_ANY, 0,
   4507                                         &ext_l2_entry, &ext_l2_lookup, NULL);
   4508             if (rv == SOC_E_EXISTS) {
   4509                 /* entry exists, clear setting for old entry */
   4510                 if (!SOC_CONTROL(unit)->l2x_group_enable) {
   4511                     mb_index = soc_mem_field32_get(unit, EXT_L2_ENTRYm,
   4512                                                    &ext_l2_lookup,
   4513                                                    MAC_BLOCK_INDEXf);
   4514                     _bcm_mac_block_delete(unit, mb_index);
   4515                 }
   4516                 if (limit_counted) {
   4517                     if (!update_limit) {
   4518                         (void)soc_triumph_learn_count_update(unit,
   4519                                                              &ext_l2_lookup,
   4520                                                              TRUE, -1);
   4521                     } else if (!same_dest) {
   4522                         (void)soc_triumph_learn_count_update(unit,
   4523                                                              &ext_l2_lookup,
   4524                                                              FALSE, -1);
   4525                     }
   4526                 }
   4527                 rv = BCM_E_NONE;
   4528             } else if (SOC_FAILURE(rv)) {
   4529                 /* insert fail, undo setting for new entry */
   4530                 if (update_limit) {
   4531                     if (!limit_counted) {
   4532                         (void)soc_triumph_learn_count_update(unit,
   4533                                                              &ext_l2_entry,
   4534                                                              TRUE, -1);
   4535                     } else if (!same_dest) {
   4536                         (void)soc_triumph_learn_count_update(unit,
   4537                                                              &ext_l2_entry,
   4538                                                              FALSE, -1);
   4539                     }
   4540                 }
   4541             }
   4542             soc_mem_unlock(unit, EXT_L2_ENTRYm);
   4543             if (SOC_SUCCESS(rv)) {
   4544                 /* insert to ext_l2_entry OK, delete from l2x if present */
   4545                 soc_mem_lock(unit, L2Xm);
   4546                 if (SOC_L2_DEL_SYNC_LOCK(SOC_CONTROL(unit)) >= 0) {
   4547                     rv1 = soc_mem_generic_delete(unit, L2Xm, MEM_BLOCK_ANY, 0,
   4548                                                  &l2x_entry, &l2x_lookup,
   4549                                                  &l2_index);
   4550                     if (SOC_SUCCESS(rv1)) {
   4551                         if (!SOC_CONTROL(unit)->l2x_group_enable) {
   4552                             mb_index =
   4553                                 soc_mem_field32_get(unit, L2Xm, &l2x_lookup,
   4554                                                     MAC_BLOCK_INDEXf);
   4555                             _bcm_mac_block_delete(unit, mb_index);
   4556                         }
   4557                         rv1 = soc_l2x_sync_delete(unit, (uint32 *)&l2x_lookup,
   4558                                                   l2_index, 0);
   4559                     } else if (rv1 == SOC_E_NOT_FOUND) {
   4560                         rv1 = BCM_E_NONE;
   4561                     }
   4562                     SOC_L2_DEL_SYNC_UNLOCK(SOC_CONTROL(unit));
   4563                 } else {
   4564                     rv1 = BCM_E_INTERNAL;
   4565                 }
   4566                 soc_mem_unlock(unit, L2Xm);
   4567                 return rv1;
   4568             }
   4569             if (rv != SOC_E_FULL) {
   4570                 goto done;
   4571             }
   4572         } else {
   4573             soc_mem_unlock(unit, EXT_L2_ENTRYm);
   4574         }
   4575     }
   4576 #endif
   4577 
   4578     rv = soc_mem_generic_lookup(unit, L2Xm, MEM_BLOCK_ANY, 0, &l2x_entry,
   4579                                 &l2x_lookup, &l2_index);
   4580     if (BCM_FAILURE(rv) && rv != BCM_E_NOT_FOUND) {
   4581         return rv;
   4582     }
   4583 
   4584     if (!SOC_CONTROL(unit)->l2x_group_enable) {
   4585         /* Mac blocking, attempt to associate with bitmap entry */
   4586         BCM_IF_ERROR_RETURN
   4587             (_bcm_mac_block_insert(unit, l2addr->block_bitmap, &mb_index));
   4588 #ifdef BCM_TRIDENT3_SUPPORT
   4589         if (l2_flex_view) {
   4590             if (soc_mem_field_valid(unit, view_id, MAC_BLOCK_ACTION_SETf)) {
   4591                 action_set = 0;
   4592                 soc_format_field32_set(unit, MAC_BLOCK_ACTION_SETfmt,
   4593                                     &action_set, MAC_BLOCK_INDEXf, mb_index);
   4594                 soc_mem_field32_set(unit, view_id, &l2x_entry,
   4595                                    MAC_BLOCK_ACTION_SETf, action_set);
   4596             }
   4597         } else
   4598 #endif
   4599         {
   4600         soc_mem_field32_set(unit, L2Xm, &l2x_entry, MAC_BLOCK_INDEXf,
   4601                             mb_index);
   4602     }
   4603     }
   4604 
   4605 #if defined(BCM_TSN_SR_SUPPORT)
   4606     if (soc_feature(unit, soc_feature_tsn_sr)) {
   4607         /* SR Mac Proxy profile, attempt to associate with bitmap entry */
   4608         if (!BCM_PBMP_IS_NULL(l2addr->sa_source_filter_pbmp)) {
   4609             /* The value should be inverted between SW and HW view */
   4610             BCM_PBMP_NEGATE(mp_pbmp, l2addr->sa_source_filter_pbmp);
   4611             BCM_PBMP_AND(mp_pbmp, PBMP_ALL(unit));
   4612             rv = bcmi_esw_tsn_sr_mac_proxy_insert(unit, mp_pbmp, &mp_index);
   4613             if (BCM_FAILURE(rv)) {
   4614                 if (!SOC_CONTROL(unit)->l2x_group_enable) {
   4615                     _bcm_mac_block_delete(unit, mb_index);
   4616                 }
   4617                 return rv;
   4618             }
   4619             soc_mem_field32_set(unit, L2Xm, &l2x_entry,
   4620                                 SR_MAC_PROXY_PROFILE_PTRf, mp_index);
   4621         }
   4622     }
   4623 #endif /* BCM_TSN_SR_SUPPORT */
   4624 
   4625 #if defined(BCM_GLOBAL_METER_SUPPORT)
   4626     /* Global Meter Policer Configuration */
   4627     if (soc_feature(unit, soc_feature_global_meter) &&
   4628         soc_feature(unit, soc_feature_global_meter_source_l2)) {
   4629         /* The SGLPf (used by VXLAN) is overlay with Global Meter Policer */
   4630         if (soc_feature(unit, soc_feature_vxlan_lite_riot)) {
   4631             associated_data_type =
   4632                 soc_L2Xm_field32_get(unit, &l2x_entry, ASSOCIATED_DATA_TYPEf);
   4633         }
   4634         if (associated_data_type != 0x1) {
   4635             BCM_IF_ERROR_RETURN(
   4636                 _bcm_esw_add_policer_to_table(
   4637                     unit, l2addr->policer_id, L2Xm, 0, (void *)(&l2x_entry)));
   4638         }
   4639     }
   4640 #endif /* BCM_GLOBAL_METER_SUPPORT */
   4641 
   4642     enable_ppa_war = FALSE;
   4643     if (SOC_CONTROL(unit)->l2x_ppa_bypass == FALSE &&
   4644         soc_feature(unit, soc_feature_ppa_bypass) &&
   4645         soc_mem_field32_get(unit, L2Xm, &l2x_entry, KEY_TYPEf) !=
   4646         TR_L2_HASH_KEY_TYPE_BRIDGE) {
   4647         enable_ppa_war = TRUE;
   4648     }
   4649 
   4650     soc_mem_lock(unit, L2Xm);
   4651     SOC_L2_SR_LOCK(unit);
   4652     if (l2addr->flags2 & BCM_L2_FLAGS2_ADD_NO_CALLBACKS) {
   4653         if (SOC_CONTROL(unit)->l2x_mode == L2MODE_FIFO &&
   4654             soc_l2mod_running(unit, NULL, NULL)) {
   4655             if (SOC_REG_IS_VALID(unit, L2_MOD_FIFO_ENABLEr)) {
   4656                 rv = READ_L2_MOD_FIFO_ENABLEr(unit, &rval);
   4657                 if (rv < 0) {
   4658                     SOC_L2_SR_UNLOCK(unit);
   4659                     soc_mem_unlock(unit, L2Xm);
   4660                     goto done;
   4661                 }
   4662                 l2_insert = soc_reg_field_get(
   4663                     unit, L2_MOD_FIFO_ENABLEr, rval, L2_INSERTf);
   4664                 l2_delete = soc_reg_field_get(
   4665                     unit, L2_MOD_FIFO_ENABLEr, rval, L2_DELETEf);
   4666                 soc_reg_field_set(unit, L2_MOD_FIFO_ENABLEr, &rval, L2_INSERTf, 0);
   4667                 soc_reg_field_set(unit, L2_MOD_FIFO_ENABLEr, &rval, L2_DELETEf, 0);
   4668                 rv = WRITE_L2_MOD_FIFO_ENABLEr(unit, rval);
   4669                 if (rv < 0) {
   4670                     SOC_L2_SR_UNLOCK(unit);
   4671                     soc_mem_unlock(unit, L2Xm);
   4672                     goto done;
   4673                 }
   4674             /* coverity[CONSTANT_EXPRESSION_RESULT] */
   4675             } else if (SOC_REG_IS_VALID(unit, AUX_ARB_CONTROLr)) {
   4676                 rv = READ_AUX_ARB_CONTROLr(unit, &rval);
   4677                 if (rv < 0) {
   4678                     SOC_L2_SR_UNLOCK(unit);
   4679                     soc_mem_unlock(unit, L2Xm);
   4680                     goto done;
   4681                 }
   4682                 if (soc_reg_field_valid(unit, AUX_ARB_CONTROLr,
   4683                         L2_MOD_FIFO_ENABLE_L2_INSERTf)) {
   4684                     l2_insert = soc_reg_field_get(unit, AUX_ARB_CONTROLr,
   4685                         rval, L2_MOD_FIFO_ENABLE_L2_INSERTf);
   4686                     soc_reg_field_set(unit, AUX_ARB_CONTROLr,
   4687                         &rval, L2_MOD_FIFO_ENABLE_L2_INSERTf, 0);
   4688                 }
   4689                 if (soc_reg_field_valid(unit, AUX_ARB_CONTROLr,
   4690                     L2_MOD_FIFO_ENABLE_L2_DELETEf)) {
   4691                     l2_delete = soc_reg_field_get(unit, AUX_ARB_CONTROLr,
   4692                         rval, L2_MOD_FIFO_ENABLE_L2_DELETEf);
   4693                     soc_reg_field_set(unit, AUX_ARB_CONTROLr,
   4694                         &rval, L2_MOD_FIFO_ENABLE_L2_DELETEf, 0);
   4695                 }
   4696                 rv = WRITE_AUX_ARB_CONTROLr(unit, rval);
   4697                 if (rv < 0) {
   4698                     SOC_L2_SR_UNLOCK(unit);
   4699                     soc_mem_unlock(unit, L2Xm);
   4700                     goto done;
   4701                 }
   4702             }
   4703             fifo_modified = TRUE;
   4704         }
   4705     }
   4706     rv = soc_mem_insert_return_old(unit, L2Xm, MEM_BLOCK_ANY,
   4707                                    (void *)&l2x_entry, (void *)&l2x_old);
   4708     if ((rv == BCM_E_FULL) && (l2addr->flags & BCM_L2_REPLACE_DYNAMIC)) {
   4709         rv = _bcm_l2_hash_dynamic_replace( unit, &l2x_entry);
   4710         if (rv < 0) {
   4711             goto_done = TRUE;
   4712         }
   4713     } else if ((rv == BCM_E_FULL) &&
   4714                (l2addr->flags & BCM_L2_ADD_OVERRIDE_PENDING)) {
   4715         rv = _bcm_l2_hash_pending_override( unit, &l2x_entry);
   4716         if (rv < 0) {
   4717             goto_done = TRUE;
   4718         }
   4719     } else if (rv == BCM_E_EXISTS) {
   4720         rv_exists = TRUE;
   4721     }
   4722 
   4723     if (l2addr->flags2 & BCM_L2_FLAGS2_ADD_NO_CALLBACKS) {
   4724         if (fifo_modified) {
   4725             if (SOC_REG_IS_VALID(unit, L2_MOD_FIFO_ENABLEr)) {
   4726                 rv2 = READ_L2_MOD_FIFO_ENABLEr(unit, &rval);
   4727                 if (rv2 < 0) {
   4728                     rv = rv2;
   4729                     SOC_L2_SR_UNLOCK(unit);
   4730                     soc_mem_unlock(unit, L2Xm);
   4731                     goto done;
   4732                 }
   4733                 soc_reg_field_set(unit, L2_MOD_FIFO_ENABLEr,
   4734                     &rval, L2_INSERTf, l2_insert);
   4735                 soc_reg_field_set(unit, L2_MOD_FIFO_ENABLEr,
   4736                     &rval, L2_DELETEf, l2_delete);
   4737                 rv2 = WRITE_L2_MOD_FIFO_ENABLEr(unit, rval);
   4738                 if (rv2 < 0) {
   4739                     rv = rv2;
   4740                     SOC_L2_SR_UNLOCK(unit);
   4741                     soc_mem_unlock(unit, L2Xm);
   4742                     goto done;
   4743                 }
   4744             /* coverity[CONSTANT_EXPRESSION_RESULT] */
   4745             } else if (SOC_REG_IS_VALID(unit, AUX_ARB_CONTROLr)) {
   4746                 rv2 = READ_AUX_ARB_CONTROLr(unit, &rval);
   4747                 if (rv2 < 0) {
   4748                     rv = rv2;
   4749                     SOC_L2_SR_UNLOCK(unit);
   4750                     soc_mem_unlock(unit, L2Xm);
   4751                     goto done;
   4752                 }
   4753                 if (soc_reg_field_valid(unit, AUX_ARB_CONTROLr,
   4754                         L2_MOD_FIFO_ENABLE_L2_INSERTf)) {
   4755                     soc_reg_field_set(unit, AUX_ARB_CONTROLr,
   4756                         &rval, L2_MOD_FIFO_ENABLE_L2_INSERTf, l2_insert);
   4757                 }
   4758                 if (soc_reg_field_valid(unit, AUX_ARB_CONTROLr,
   4759                     L2_MOD_FIFO_ENABLE_L2_DELETEf)) {
   4760                     soc_reg_field_set(unit, AUX_ARB_CONTROLr,
   4761                         &rval, L2_MOD_FIFO_ENABLE_L2_DELETEf, l2_delete);
   4762                 }
   4763                 rv2 = WRITE_AUX_ARB_CONTROLr(unit, rval);
   4764                 if (rv2 < 0) {
   4765                     rv = rv2;
   4766                     SOC_L2_SR_UNLOCK(unit);
   4767                     soc_mem_unlock(unit, L2Xm);
   4768                     goto done;
   4769                 }
   4770             }
   4771         }
   4772     }
   4773 
   4774     if (goto_done) {
   4775         SOC_L2_SR_UNLOCK(unit);
   4776         soc_mem_unlock(unit, L2Xm);
   4777         goto done;
   4778     } else if (rv_exists) {
   4779         if (!SOC_CONTROL(unit)->l2x_group_enable) {
   4780 #ifdef BCM_TRIDENT3_SUPPORT
   4781             if (l2_flex_view) {
   4782                 if (soc_mem_field_valid(unit, view_id, MAC_BLOCK_ACTION_SETf)) {
   4783                     action_set = soc_mem_field32_get(unit, view_id, &l2x_entry,
   4784                                        MAC_BLOCK_ACTION_SETf);
   4785                     mb_index = soc_format_field32_get(unit,
   4786                                          MAC_BLOCK_ACTION_SETfmt,
   4787                                         &action_set, MAC_BLOCK_INDEXf);
   4788                 }
   4789             } else
   4790 #endif
   4791             {
   4792             mb_index = soc_mem_field32_get(unit, L2Xm, &l2x_lookup,
   4793                                            MAC_BLOCK_INDEXf);
   4794             }
   4795             _bcm_mac_block_delete(unit, mb_index);
   4796         }
   4797 
   4798 #if defined(BCM_TSN_SR_SUPPORT)
   4799         if (soc_feature(unit, soc_feature_tsn_sr)) {
   4800             mp_index = soc_mem_field32_get(unit, L2Xm,
   4801                                            &l2x_old,
   4802                                            SR_MAC_PROXY_PROFILE_PTRf);
   4803             if (mp_index != 0) {
   4804                 rv = bcmi_esw_tsn_sr_mac_proxy_delete(unit, mp_index);
   4805                 if (rv < 0) {
   4806                     SOC_L2_SR_UNLOCK(unit);
   4807                     soc_mem_unlock(unit, L2Xm);
   4808                     return rv;
   4809                 }
   4810             }
   4811         }
   4812 #endif /* BCM_TSN_SR_SUPPORT */
   4813 
   4814 #if defined(BCM_TSN_SUPPORT)
   4815         if (soc_feature(unit, soc_feature_tsn)) {
   4816             /* Decrease reference count for the existed TSN flowset */
   4817             if (soc_L2Xm_field32_get(unit, &l2x_old,
   4818                                      TSN_CIRCUIT_IDf) != 0) {
   4819                 rv = _bcm_tr_l2_from_l2x(unit, &old_l2addr, &l2x_old);
   4820                 if (rv < 0) {
   4821                     SOC_L2_SR_UNLOCK(unit);
   4822                     soc_mem_unlock(unit, L2Xm);
   4823                     return rv;
   4824                 }
   4825                 rv = bcmi_esw_tsn_flowset_ref_dec(unit,
   4826                                                   old_l2addr.tsn_flowset);
   4827                 if (rv < 0) {
   4828                     SOC_L2_SR_UNLOCK(unit);
   4829                     soc_mem_unlock(unit, L2Xm);
   4830                     return rv;
   4831                 }
   4832             }
   4833         }
   4834 #if defined(BCM_TSN_SR_SUPPORT)
   4835         if (soc_feature(unit, soc_feature_tsn_sr)) {
   4836             /* Decrease reference count for the existed SR flowset */
   4837             if (soc_L2Xm_field32_get(unit, &l2x_old,
   4838                                      SR_FLOW_IDf) != 0) {
   4839                 rv = _bcm_tr_l2_from_l2x(unit, &old_l2addr, &l2x_old);
   4840                 if (rv < 0) {
   4841                     SOC_L2_SR_UNLOCK(unit);
   4842                     soc_mem_unlock(unit, L2Xm);
   4843                     return rv;
   4844                 }
   4845                 rv = bcmi_esw_tsn_sr_flowset_ref_dec(unit,
   4846                                                      old_l2addr.sr_flowset);
   4847                 if (rv < 0) {
   4848                     SOC_L2_SR_UNLOCK(unit);
   4849                     soc_mem_unlock(unit, L2Xm);
   4850                     return rv;
   4851                 }
   4852             }
   4853         }
   4854 #endif /* BCM_TSN_SR_SUPPORT */
   4855 #endif /* BCM_TSN_SUPPORT */
   4856 
   4857 #if defined(BCM_GLOBAL_METER_SUPPORT)
   4858         if (soc_feature(unit, soc_feature_global_meter) &&
   4859             soc_feature(unit, soc_feature_global_meter_source_l2)) {
   4860             bcm_policer_t policer_id;
   4861 
   4862             rv = _bcm_esw_get_policer_from_table(
   4863                     unit, L2Xm, 0, &l2x_lookup, &policer_id, TRUE);
   4864             if (rv < 0) {
   4865                 SOC_L2_SR_UNLOCK(unit);
   4866                 soc_mem_unlock(unit, L2Xm);
   4867                 return rv;
   4868             }
   4869             _bcm_esw_policer_decrement_ref_count(unit, policer_id);
   4870         }
   4871 #endif /* BCM_GLOBAL_METER_SUPPORT */
   4872         rv = BCM_E_NONE;
   4873     }
   4874 
   4875 #if defined(BCM_TSN_SUPPORT)
   4876     if (BCM_SUCCESS(rv)) {
   4877         /*
   4878          * For manual L2 add and L2 delete:
   4879          * - Update the TSN/SR flowset reference count bitmap for L2X reference.
   4880          * (this is for L2MODE_POLL mode, not required for L2MOD_FIFO mode).
   4881          * For packet learn and age (including ppa):
   4882          * - the TSN/SR flowset reference count will be handled in
   4883          * soc_l2x_callback with SOC_L2X_ENTRY_TSN_SR_FLOWSET_REF_CNT flag.
   4884          */
   4885         if (soc_feature(unit, soc_feature_tsn)) {
   4886             /* Increase reference count for the specified TSN flowset */
   4887             if (l2addr->tsn_flowset != 0) {
   4888                 rv = bcmi_esw_tsn_flowset_ref_inc(unit, l2addr->tsn_flowset);
   4889                 if (rv < 0) {
   4890                     SOC_L2_SR_UNLOCK(unit);
   4891                     soc_mem_unlock(unit, L2Xm);
   4892                     return rv;
   4893                 }
   4894                 is_tsn_or_sr_flow = TRUE;
   4895             }
   4896         }
   4897 #if defined(BCM_TSN_SR_SUPPORT)
   4898         if (soc_feature(unit, soc_feature_tsn_sr)) {
   4899             /* Increase reference count for the specified SR flowset */
   4900             if (l2addr->sr_flowset != 0) {
   4901                 rv = bcmi_esw_tsn_sr_flowset_ref_inc(unit, l2addr->sr_flowset);
   4902                 if (rv < 0) {
   4903                     SOC_L2_SR_UNLOCK(unit);
   4904                     soc_mem_unlock(unit, L2Xm);
   4905                     return rv;
   4906                 }
   4907                 is_tsn_or_sr_flow = TRUE;
   4908             }
   4909         }
   4910 #endif /* BCM_TSN_SR_SUPPORT */
   4911         if (is_tsn_or_sr_flow == TRUE) {
   4912             /* Update the TSN/SR flowset ref cnt bitmap for L2X reference. */
   4913             /* Get L2 index */
   4914             rv = soc_mem_generic_lookup(unit, L2Xm, MEM_BLOCK_ANY, 0,
   4915                                         &l2x_entry, &l2x_lookup, &l2_index);
   4916             if (rv < 0) {
   4917                 SOC_L2_SR_UNLOCK(unit);
   4918                 soc_mem_unlock(unit, L2Xm);
   4919                 return rv;
   4920             }
   4921             rv = soc_l2x_sr_ref_sync(unit, l2_index);
   4922             if (rv < 0) {
   4923                 SOC_L2_SR_UNLOCK(unit);
   4924                 soc_mem_unlock(unit, L2Xm);
   4925                 return rv;
   4926             }
   4927         }
   4928     }
   4929 #endif /* BCM_TSN_SUPPORT */
   4930 
   4931     SOC_L2_SR_UNLOCK(unit);
   4932     soc_mem_unlock(unit, L2Xm);
   4933 
   4934     if (BCM_SUCCESS(rv) && enable_ppa_war) {
   4935         SOC_CONTROL(unit)->l2x_ppa_bypass = TRUE;
   4936     }
   4937 
   4938 #ifdef BCM_TRIUMPH_SUPPORT
   4939     if (SOC_SUCCESS(rv)) {
   4940         if (exist_in_ext_l2) {
   4941             soc_mem_lock(unit, EXT_L2_ENTRYm);
   4942             limit_counted =
   4943                 ppa_info[ext_l2_index].data & _SOC_TR_L2E_LIMIT_COUNTED;
   4944             rv1 = soc_mem_generic_delete(unit, EXT_L2_ENTRYm, MEM_BLOCK_ANY,
   4945                                          0, &ext_l2_entry, &ext_l2_lookup,
   4946                                          &ext_l2_index);
   4947             if (SOC_SUCCESS(rv1)) {
   4948                 if (!SOC_CONTROL(unit)->l2x_group_enable) {
   4949                     mb_index =
   4950                         soc_mem_field32_get(unit, EXT_L2_ENTRYm,
   4951                                             &ext_l2_lookup, MAC_BLOCK_INDEXf);
   4952                     _bcm_mac_block_delete(unit, mb_index);
   4953                 }
   4954                 if (limit_counted) {
   4955                     (void)soc_triumph_learn_count_update(unit, &ext_l2_lookup,
   4956                                                          TRUE, -1);
   4957                 }
   4958             }
   4959             soc_mem_unlock(unit, EXT_L2_ENTRYm);
   4960         }
   4961     }
   4962 #endif
   4963 
   4964 done:
   4965     if (rv < 0) {
   4966         _bcm_mac_block_delete(unit, mb_index);
   4967 
   4968 #if defined(BCM_TSN_SR_SUPPORT)
   4969         if (soc_feature(unit, soc_feature_tsn_sr)) {
   4970             if (mp_index != 0) {
   4971                 BCM_IF_ERROR_RETURN(
   4972                     bcmi_esw_tsn_sr_mac_proxy_delete(unit, mp_index));
   4973             }
   4974         }
   4975 #endif /* BCM_TSN_SR_SUPPORT */
   4976 #if defined(BCM_GLOBAL_METER_SUPPORT)
   4977         if (soc_feature(unit, soc_feature_global_meter) &&
   4978             soc_feature(unit, soc_feature_global_meter_source_l2)) {
   4979             _bcm_esw_policer_decrement_ref_count(unit, l2addr->policer_id);
   4980         }
   4981 #endif /* BCM_GLOBAL_METER_SUPPORT */
   4982     }
   4983 
   4984     return rv;
   4985 }
   4986 
   4987 /*
   4988  * Function:
   4989  *      bcm_tr_l2_addr_delete
   4990  * Description:
   4991  *      Delete an L2 address (MAC+VLAN) from the device
   4992  * Parameters:
   4993  *      unit - device unit
   4994  *      mac  - MAC address to delete
   4995  *      vid  - VLAN id
   4996  * Returns:
   4997  *      BCM_E_XXX
   4998  */
   4999 int
   5000 bcm_tr_l2_addr_delete(int unit, bcm_mac_t mac, bcm_vlan_t vid)
   5001 {
   5002     bcm_l2_addr_t  l2addr;
   5003     l2x_entry_t    l2x_entry, l2x_lookup;
   5004 #ifdef BCM_TRIUMPH_SUPPORT
   5005     _soc_tr_l2e_ppa_info_t *ppa_info;
   5006     ext_l2_entry_entry_t ext_l2_entry, ext_l2_lookup;
   5007     int limit_counted;
   5008 #endif /* BCM_TRIUMPH_SUPPORT */
   5009     int            l2_index, mb_index;
   5010     int            rv;
   5011 #if defined(BCM_TSN_SUPPORT)
   5012     int is_tsn_or_sr_flow = FALSE; /* TSN or SR related flow */
   5013 #if defined(BCM_TSN_SR_SUPPORT)
   5014     int mp_index = 0; /* TSN SR MAC Proxy profile index */
   5015 #endif /* BCM_TSN_SR_SUPPORT */
   5016 #endif /* BCM_TSN_SUPPORT */
   5017     soc_control_t  *soc = SOC_CONTROL(unit);
   5018 
   5019     bcm_l2_addr_t_init(&l2addr, mac, vid);
   5020 
   5021 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_GREYHOUND2_SUPPORT)
   5022     if (SOC_IS_TRIDENT(unit) || (SOC_IS_KATANAX(unit)) ||
   5023         SOC_IS_TD2_TT2(unit) || soc_feature(unit, soc_feature_gh2_my_station)) {
   5024         if (soc_mem_is_valid(unit, MY_STATION_TCAMm) && BCM_VLAN_VALID(vid)) {
   5025               rv = bcm_td_l2_myStation_delete (unit, mac, vid, &l2_index);
   5026             if ((rv != BCM_E_NOT_FOUND) && (rv != BCM_E_FULL)) {
   5027                    if (rv != BCM_E_NONE) {
   5028                         return rv;
   5029                    }
   5030               }
   5031          }
   5032     }
   5033 #endif /* BCM_TRIDENT_SUPPORT || BCM_GREYHOUND2_SUPPORT */
   5034 
   5035 #ifdef BCM_TRIUMPH_SUPPORT
   5036     if (soc_mem_is_valid(unit, EXT_L2_ENTRYm) &&
   5037         soc_mem_index_count(unit, EXT_L2_ENTRYm)) {
   5038         BCM_IF_ERROR_RETURN
   5039             (_bcm_tr_l2_to_ext_l2(unit, &ext_l2_entry, &l2addr, TRUE));
   5040         soc_mem_lock(unit, EXT_L2_ENTRYm);
   5041         rv = soc_mem_generic_lookup(unit, EXT_L2_ENTRYm, MEM_BLOCK_ANY, 0,
   5042                                     &ext_l2_entry, NULL, &l2_index);
   5043         if (BCM_SUCCESS(rv)) {
   5044             ppa_info = SOC_CONTROL(unit)->ext_l2_ppa_info;
   5045             limit_counted =
   5046                 ppa_info[l2_index].data & _SOC_TR_L2E_LIMIT_COUNTED;
   5047             rv = soc_mem_generic_delete(unit, EXT_L2_ENTRYm, MEM_BLOCK_ANY, 0,
   5048                                         &ext_l2_entry, &ext_l2_lookup, NULL);
   5049             if (BCM_SUCCESS(rv)) {
   5050                 if (!SOC_CONTROL(unit)->l2x_group_enable) {
   5051                     mb_index =
   5052                         soc_mem_field32_get(unit, EXT_L2_ENTRYm,
   5053                                             &ext_l2_lookup, MAC_BLOCK_INDEXf);
   5054                     _bcm_mac_block_delete(unit, mb_index);
   5055                 }
   5056                 if (limit_counted) {
   5057                     rv = soc_triumph_learn_count_update(unit, &ext_l2_lookup,
   5058                                                         TRUE, -1);
   5059                 }
   5060             }
   5061         }
   5062         if (rv != BCM_E_NOT_FOUND) {
   5063             soc_mem_unlock(unit, EXT_L2_ENTRYm);
   5064             return rv;
   5065         }
   5066         soc_mem_unlock(unit, EXT_L2_ENTRYm);
   5067     }
   5068 #endif
   5069 
   5070     BCM_IF_ERROR_RETURN(_bcm_tr_l2_to_l2x(unit, &l2x_entry, &l2addr, TRUE));
   5071 
   5072     soc_mem_lock(unit, L2Xm);
   5073 
   5074 #if defined(BCM_GREYHOUND2_SUPPORT) && defined(INCLUDE_L3)
   5075     /* Only support for GH2-B0 */
   5076     if (soc_feature(unit, soc_feature_vxlan_lite_riot)) {
   5077         rv = soc_mem_search(unit, L2Xm, MEM_BLOCK_ANY, &l2_index,
   5078                             (void *)&l2x_entry, (void *)&l2x_lookup, 0);
   5079         if (rv == BCM_E_NOT_FOUND) {
   5080             if (_BCM_VPN_VFI_IS_SET(l2addr.vid)) {
   5081                 soc_L2Xm_field32_set(unit, &l2x_entry, KEY_TYPEf,
   5082                                      GH2_L2_HASH_KEY_TYPE_VFI_MULTICAST);
   5083                 rv = soc_mem_search(unit, L2Xm, MEM_BLOCK_ANY, &l2_index,
   5084                                     (void *)&l2x_entry,
   5085                                     (void *)&l2x_lookup, 0);
   5086             }
   5087         }
   5088     } else
   5089 #endif /* BCM_GREYHOUND2_SUPPORT && INCLUDE_L3  */
   5090     {
   5091         rv = soc_mem_search(unit, L2Xm, MEM_BLOCK_ANY, &l2_index,
   5092                             (void *)&l2x_entry, (void *)&l2x_lookup, 0);
   5093 #ifdef BCM_TRIDENT3_SUPPORT
   5094         if (rv == BCM_E_NOT_FOUND) {
   5095             if (soc_feature(unit, soc_feature_pvlan_on_vfi)) {
   5096                 soc_L2Xm_field32_set(unit, &l2x_entry, KEY_TYPEf,
   5097                                      TR_L2_HASH_KEY_TYPE_VFI);
   5098                 rv = soc_mem_search(unit, L2Xm, MEM_BLOCK_ANY, &l2_index,
   5099                                     (void *)&l2x_entry,
   5100                                     (void *)&l2x_lookup, 0);
   5101             }
   5102         }
   5103 #endif
   5104     }
   5105     if (BCM_E_NONE != rv) {
   5106         soc_mem_unlock(unit, L2Xm);
   5107         return rv;
   5108     }
   5109 
   5110     if (!SOC_CONTROL(unit)->l2x_group_enable) {
   5111         mb_index = soc_L2Xm_field32_get(unit, &l2x_lookup, MAC_BLOCK_INDEXf);
   5112         _bcm_mac_block_delete(unit, mb_index);
   5113     }
   5114 
   5115 #if defined(BCM_TSN_SR_SUPPORT)
   5116     if (soc_feature(unit, soc_feature_tsn_sr)) {
   5117         mp_index = soc_L2Xm_field32_get(unit, &l2x_lookup,
   5118                                         SR_MAC_PROXY_PROFILE_PTRf);
   5119         if (mp_index != 0) {
   5120             rv = bcmi_esw_tsn_sr_mac_proxy_delete(unit, mp_index);
   5121             if (BCM_FAILURE(rv)) {
   5122                 soc_mem_unlock(unit, L2Xm);
   5123                 return rv;
   5124             }
   5125         }
   5126     }
   5127 #endif /* BCM_TSN_SR_SUPPORT */
   5128 
   5129 #if defined(BCM_GLOBAL_METER_SUPPORT)
   5130     if (soc_feature(unit, soc_feature_global_meter) &&
   5131         soc_feature(unit, soc_feature_global_meter_source_l2)) {
   5132         bcm_policer_t policer_id;
   5133         rv = _bcm_esw_get_policer_from_table(unit, L2Xm, 0, &l2x_lookup,
   5134                                              &policer_id, TRUE);
   5135         if (BCM_FAILURE(rv)) {
   5136             soc_mem_unlock(unit, L2Xm);
   5137             return rv;
   5138         }
   5139         _bcm_esw_policer_decrement_ref_count(unit, policer_id);
   5140     }
   5141 #endif /* BCM_GLOBAL_METER_SUPPORT */
   5142 
   5143     if (SOC_L2_DEL_SYNC_LOCK(soc) < 0) {
   5144         soc_mem_unlock(unit, L2Xm);
   5145         return BCM_E_RESOURCE;
   5146     }
   5147     SOC_L2_SR_LOCK(unit);
   5148     rv = soc_mem_delete_return_old(unit, L2Xm, MEM_BLOCK_ANY,
   5149                                    (void *)&l2x_entry, (void *)&l2x_entry);
   5150     if (rv >= 0) {
   5151         rv = soc_l2x_sync_delete(unit, (uint32 *) &l2x_lookup, l2_index, 0);
   5152     }
   5153 
   5154 #if defined(BCM_TSN_SUPPORT)
   5155     /*
   5156      * For manual L2 add and L2 delete:
   5157      * - Update the TSN/SR flowset reference count bitmap for L2X reference.
   5158      * (this is for L2MODE_POLL mode, not required for L2MOD_FIFO mode).
   5159      * For packet learn and age (including ppa):
   5160      * - the TSN/SR flowset reference count will be handled in
   5161      * soc_l2x_callback with SOC_L2X_ENTRY_TSN_SR_FLOWSET_REF_CNT flag.
   5162      */
   5163     if (soc_feature(unit, soc_feature_tsn)) {
   5164         /* Decrease reference count for the associated TSN flowset */
   5165         if (soc_L2Xm_field32_get(unit, &l2x_entry, TSN_CIRCUIT_IDf) != 0) {
   5166             rv = _bcm_tr_l2_from_l2x(unit, &l2addr, &l2x_entry);
   5167             if (BCM_FAILURE(rv)) {
   5168                 SOC_L2_SR_UNLOCK(unit);
   5169                 SOC_L2_DEL_SYNC_UNLOCK(soc);
   5170                 soc_mem_unlock(unit, L2Xm);
   5171                 return rv;
   5172             }
   5173             rv = bcmi_esw_tsn_flowset_ref_dec(unit, l2addr.tsn_flowset);
   5174             if (BCM_FAILURE(rv)) {
   5175                 SOC_L2_SR_UNLOCK(unit);
   5176                 SOC_L2_DEL_SYNC_UNLOCK(soc);
   5177                 soc_mem_unlock(unit, L2Xm);
   5178                 return rv;
   5179             }
   5180             is_tsn_or_sr_flow = TRUE;
   5181         }
   5182     }
   5183 #if defined(BCM_TSN_SR_SUPPORT)
   5184     if (soc_feature(unit, soc_feature_tsn_sr)) {
   5185         /* Decrease reference count for the associated SR flowset */
   5186         if (soc_L2Xm_field32_get(unit, &l2x_entry, SR_FLOW_IDf) != 0) {
   5187             rv = _bcm_tr_l2_from_l2x(unit, &l2addr, &l2x_entry);
   5188             if (BCM_FAILURE(rv)) {
   5189                 SOC_L2_SR_UNLOCK(unit);
   5190                 SOC_L2_DEL_SYNC_UNLOCK(soc);
   5191                 soc_mem_unlock(unit, L2Xm);
   5192                 return rv;
   5193             }
   5194             rv = bcmi_esw_tsn_sr_flowset_ref_dec(unit, l2addr.sr_flowset);
   5195             if (BCM_FAILURE(rv)) {
   5196                 SOC_L2_SR_UNLOCK(unit);
   5197                 SOC_L2_DEL_SYNC_UNLOCK(soc);
   5198                 soc_mem_unlock(unit, L2Xm);
   5199                 return rv;
   5200             }
   5201             is_tsn_or_sr_flow = TRUE;
   5202         }
   5203     }
   5204 #endif /* BCM_TSN_SR_SUPPORT */
   5205 
   5206     if (is_tsn_or_sr_flow == TRUE) {
   5207         /* Update the TSN/SR flowset ref cnt bitmap for L2X reference. */
   5208         rv = soc_l2x_sr_ref_sync(unit, l2_index);
   5209     }
   5210 #endif /* BCM_TSN_SUPPORT */
   5211 
   5212     SOC_L2_SR_UNLOCK(unit);
   5213     SOC_L2_DEL_SYNC_UNLOCK(soc);
   5214     soc_mem_unlock(unit, L2Xm);
   5215 
   5216     return rv;
   5217 }
   5218 
   5219 #ifdef BCM_TRIUMPH_SUPPORT
   5220 STATIC int
   5221 bcm_tr_l2_addr_ext_get(int unit, sal_mac_addr_t mac, bcm_vlan_t vid,
   5222                    bcm_l2_addr_t *l2addr)
   5223 {
   5224     bcm_l2_addr_t           l2addr_key;
   5225     ext_l2_entry_entry_t    ext_l2_entry, ext_l2_lookup;
   5226     int                     rv;
   5227 
   5228     bcm_l2_addr_t_init(&l2addr_key, mac, vid);
   5229 
   5230     BCM_IF_ERROR_RETURN(
   5231         _bcm_tr_l2_to_ext_l2(unit, &ext_l2_entry, &l2addr_key, TRUE));
   5232 
   5233     soc_mem_lock(unit, EXT_L2_ENTRYm);
   5234     rv = soc_mem_generic_lookup(unit, EXT_L2_ENTRYm, MEM_BLOCK_ANY, 0,
   5235                                &ext_l2_entry, &ext_l2_lookup, NULL);
   5236     soc_mem_unlock(unit, EXT_L2_ENTRYm);
   5237 
   5238     if (BCM_SUCCESS(rv)) {
   5239         rv = _bcm_tr_l2_from_ext_l2(unit, l2addr, &ext_l2_lookup);
   5240     }
   5241 
   5242     return rv;
   5243 }
   5244 
   5245 #endif /* BCM_TRIUMPH_SUPPORT */
   5246 
   5247 /*
   5248  * Function:
   5249  *      bcm_tr_l2_addr_get
   5250  * Description:
   5251  *      Given a MAC address and VLAN ID, check if the entry is present
   5252  *      in the L2 table, and if so, return all associated information.
   5253  * Parameters:
   5254  *      unit - Device unit number
   5255  *      mac - input MAC address to search
   5256  *      vid - input VLAN ID to search
   5257  *      check_l2_only - only check if the target exist in L2 table.
   5258  *      l2addr - Pointer to bcm_l2_addr_t structure to receive results
   5259  * Returns:
   5260  *      BCM_E_NONE              Success (l2addr filled in)
   5261  *      BCM_E_PARAM             Illegal parameter (NULL pointer)
   5262  *      BCM_E_INTERNAL          Chip access failure
   5263  *      BCM_E_NOT_FOUND Address not found (l2addr not filled in)
   5264  */
   5265 
   5266 int
   5267 _bcm_tr_l2_addr_get(int unit, sal_mac_addr_t mac, bcm_vlan_t vid,
   5268     int check_l2_only, bcm_l2_addr_t *l2addr)
   5269 {
   5270     bcm_l2_addr_t l2addr_key;
   5271     l2x_entry_t  l2x_entry, l2x_lookup;
   5272     int          l2_hw_index;
   5273     int          rv;
   5274 
   5275     bcm_l2_addr_t_init(&l2addr_key, mac, vid);
   5276 
   5277 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_GREYHOUND2_SUPPORT)
   5278     if (SOC_IS_TRIDENT(unit) || SOC_IS_KATANAX(unit) ||       
   5279         SOC_IS_TD2_TT2(unit) || soc_feature(unit, soc_feature_gh2_my_station)) {
   5280         if (soc_mem_is_valid(unit, MY_STATION_TCAMm) && (!check_l2_only)) {
   5281               rv = bcm_td_l2_myStation_get (unit, mac, vid, l2addr);
   5282               if (BCM_SUCCESS(rv)) {
   5283                    return rv;
   5284               }
   5285          }
   5286     }
   5287 #endif /* BCM_TRIDENT_SUPPORT || BCM_GREYHOUND2_SUPPORT */
   5288 
   5289 #ifdef BCM_TRIDENT3_SUPPORT
   5290     if (soc_feature(unit, soc_feature_flex_flow) &&
   5291         (l2addr->flow_handle != 0)) {
   5292         l2addr_key.flow_handle = l2addr->flow_handle;
   5293         l2addr_key.flow_option_handle = l2addr->flow_option_handle;
   5294         l2addr_key.num_of_fields = l2addr->num_of_fields;
   5295         sal_memcpy(l2addr_key.logical_fields, l2addr->logical_fields,
   5296                    l2addr->num_of_fields*sizeof(bcm_flow_logical_field_t));
   5297     }
   5298 #endif
   5299 
   5300     BCM_IF_ERROR_RETURN(
   5301         _bcm_tr_l2_to_l2x(unit, &l2x_entry, &l2addr_key, TRUE));
   5302 
   5303     soc_mem_lock(unit, L2Xm);
   5304 
   5305 #if defined(BCM_GREYHOUND2_SUPPORT) && defined(INCLUDE_L3)
   5306     /* Only support for GH2-B0 */
   5307     if (soc_feature(unit, soc_feature_vxlan_lite_riot)) {
   5308         rv = soc_mem_generic_lookup(unit, L2Xm, MEM_BLOCK_ANY, 0, &l2x_entry,
   5309                                     &l2x_lookup, &l2_hw_index);
   5310         if (rv == BCM_E_NOT_FOUND) {
   5311             if (_BCM_VPN_VFI_IS_SET(vid)) {
   5312                 soc_L2Xm_field32_set(unit, &l2x_entry, KEY_TYPEf,
   5313                                      GH2_L2_HASH_KEY_TYPE_VFI_MULTICAST);
   5314                 rv = soc_mem_generic_lookup(unit, L2Xm, MEM_BLOCK_ANY, 0,
   5315                                             &l2x_entry, &l2x_lookup,
   5316                                             &l2_hw_index);
   5317             }
   5318         }
   5319     } else
   5320 #endif /* BCM_GREYHOUND2_SUPPORT && INCLUDE_L3  */
   5321     {
   5322         rv = soc_mem_generic_lookup(unit, L2Xm, MEM_BLOCK_ANY, 0, &l2x_entry,
   5323                                     &l2x_lookup, &l2_hw_index);
   5324 #ifdef BCM_TRIDENT3_SUPPORT
   5325         if (rv == BCM_E_NOT_FOUND) {
   5326             if (soc_feature(unit, soc_feature_pvlan_on_vfi)) {
   5327                 soc_L2Xm_field32_set(unit, &l2x_entry, KEY_TYPEf,
   5328                                      TR_L2_HASH_KEY_TYPE_VFI);
   5329                 rv = soc_mem_generic_lookup(unit, L2Xm, MEM_BLOCK_ANY, 0,
   5330                                             &l2x_entry, &l2x_lookup,
   5331                                             &l2_hw_index);
   5332             }
   5333         }
   5334 #endif
   5335     }
   5336 
   5337     /* If not found in Internal memory and external is available serach there */
   5338 #ifdef BCM_TRIUMPH_SUPPORT
   5339     if (rv == BCM_E_NOT_FOUND && soc_mem_is_valid(unit, EXT_L2_ENTRYm) &&
   5340         soc_mem_index_count(unit, EXT_L2_ENTRYm) > 0) {
   5341         rv = bcm_tr_l2_addr_ext_get(unit, mac, vid, l2addr);
   5342             soc_mem_unlock(unit, L2Xm);
   5343             return rv;
   5344         }
   5345 #endif /* BCM_TRIUMPH_SUPPORT */
   5346 
   5347     soc_mem_unlock(unit, L2Xm);
   5348 
   5349     if (check_l2_only) {
   5350         return rv;
   5351     }
   5352 
   5353     if (SOC_SUCCESS(rv)) {
   5354         /* Retrieve the hit bit for TD2/TT2 */
   5355 #ifdef BCM_TRIDENT2_SUPPORT
   5356         if (!SOC_IS_TOMAHAWKX(unit) && !SOC_IS_APACHE(unit) &&
   5357             !SOC_IS_TRIDENT3X(unit) &&
   5358                 SOC_IS_TD2_TT2(unit)) {
   5359             BCM_IF_ERROR_RETURN(
   5360                 _bcm_td2_l2_hit_retrieve(unit, &l2x_lookup, l2_hw_index));
   5361         }
   5362 #endif /* BCM_TRIDENT2_SUPPORT */
   5363         rv = _bcm_tr_l2_from_l2x(unit, l2addr, &l2x_lookup);
   5364     }
   5365 
   5366     return rv;
   5367 }
   5368 
   5369 int
   5370 bcm_tr_l2_addr_get(int unit, sal_mac_addr_t mac, bcm_vlan_t vid,
   5371                    bcm_l2_addr_t *l2addr)
   5372 {
   5373     return _bcm_tr_l2_addr_get(unit, mac, vid, FALSE, l2addr);
   5374 }
   5375 
   5376 #ifdef BCM_WARM_BOOT_SUPPORT
   5377 #if defined(BCM_KATANA2_SUPPORT) || defined(BCM_TRIDENT2PLUS_SUPPORT)
   5378 STATIC int
   5379 _bcm_l2_station_non_tcam_reload(int unit, _bcm_l2_station_control_t *sc) 
   5380 {
   5381     int index = 0, entry_index=0;
   5382     int rv  = BCM_E_NONE; 
   5383     _bcm_l2_station_entry_t   *s_ent_p;          /* Station table entry.      */
   5384     uint32              mac_field[2];
   5385     egr_olp_dgpp_config_entry_t *eolp_dgpp_cfg_buf;
   5386     egr_olp_dgpp_config_entry_t *eolp_dgpp_cfg = NULL;
   5387     int                       entry_mem_size;    /* Size of table entry. */
   5388     egr_olp_config_entry_t    eolp_cfg;
   5389     bcm_mac_t                 mac_addr; 
   5390     uint32                       non_tcam_count = 0;
   5391 #ifdef BCM_KATANA2_SUPPORT
   5392     if (SOC_IS_KATANA2(unit)) {
   5393         port_tab_entry_t          *ptab_buf;        
   5394         port_tab_entry_t          *ptab;        
   5395 
   5396         entry_mem_size = sizeof(port_tab_entry_t);
   5397         /* Allocate buffer to store the DMAed table entries. */
   5398         ptab_buf = soc_cm_salloc(unit, entry_mem_size * sc->port_entries_total,
   5399                 "Port table entry buffer");
   5400         if (NULL == ptab_buf) {
   5401             return (BCM_E_MEMORY);
   5402         }
   5403         /* Initialize the entry buffer. */
   5404         sal_memset(ptab_buf, 0, sizeof(entry_mem_size) * sc->port_entries_total);
   5405 
   5406         /* Read the table entries into the buffer. */
   5407         rv = soc_mem_read_range(unit, PORT_TABm, MEM_BLOCK_ALL,
   5408                 0, (sc->port_entries_total - 1), ptab_buf);
   5409         if (BCM_FAILURE(rv)) {
   5410             if (ptab_buf) {
   5411                 soc_cm_sfree(unit, ptab_buf);
   5412             }
   5413             return rv;
   5414         }
   5415 
   5416         /* Iterate over the port table entries. */
   5417         for (index = 0; index < sc->port_entries_total; index++) {
   5418             ptab = soc_mem_table_idx_to_pointer
   5419                 (unit, PORT_TABm, port_tab_entry_t *,
   5420                  ptab_buf, index);
   5421 
   5422             soc_mem_field_get(unit, PORT_TABm, (uint32 *)ptab, 
   5423                     MAC_ADDRESSf, mac_field);
   5424 
   5425             if ((mac_field[0] > 0) || (mac_field[1] > 0)) {
   5426                 s_ent_p = (_bcm_l2_station_entry_t *)
   5427                     sal_alloc(sizeof(_bcm_l2_station_entry_t),
   5428                             "Sw L2 station entry");
   5429                 if (NULL == s_ent_p) {
   5430                     if (ptab_buf) {
   5431                         soc_cm_sfree(unit, ptab_buf);
   5432                     }
   5433                     return (BCM_E_MEMORY);
   5434                 }
   5435                 sal_memset(s_ent_p, 0, sizeof(_bcm_l2_station_entry_t));
   5436 
   5437                 s_ent_p->hw_index = index;
   5438                 soc_mem_mac_addr_get(unit, PORT_TABm, &ptab,
   5439                         MAC_ADDRESSf, mac_addr);
   5440                 s_ent_p->flags = _BCM_L2_STATION_ENTRY_INSTALLED;
   5441                 s_ent_p->flags |= _BCM_L2_STATION_ENTRY_TYPE_NON_TCAM;
   5442                 s_ent_p->flags |= _BCM_L2_STATION_ENTRY_TYPE_OAM_MAC;
   5443                 s_ent_p->prio = 0;
   5444                 s_ent_p->sid = ++sc->last_allocated_sid;
   5445                 sc->entry_arr[sc->entries_total + index] = s_ent_p;
   5446                 sc->port_entries_free--;
   5447                 non_tcam_count++;
   5448                 LOG_DEBUG(BSL_LS_BCM_L2,
   5449                         (BSL_META_U(unit,
   5450                                     "port station, sid %d, hw_index %d, entry_index %d,port_station_max %d\n"),
   5451                          s_ent_p->sid, s_ent_p->hw_index, sc->entries_total + index,sc->port_entries_total));
   5452 
   5453             }
   5454         }
   5455         if (ptab_buf) {
   5456             soc_cm_sfree(unit, ptab_buf);
   5457         }
   5458     }
   5459 #endif
   5460     entry_mem_size = sizeof(egr_olp_dgpp_config_entry_t);
   5461 
   5462     /* Allocate buffer to store the DMAed table entries. */
   5463     eolp_dgpp_cfg_buf = soc_cm_salloc(unit, entry_mem_size * sc->olp_entries_total,
   5464                               "Port table entry buffer");
   5465     if (NULL == eolp_dgpp_cfg_buf) {
   5466         return (BCM_E_MEMORY);
   5467     }
   5468     /* Initialize the entry buffer. */
   5469     sal_memset(eolp_dgpp_cfg_buf, 0, 
   5470                sizeof(entry_mem_size) * sc->olp_entries_total);
   5471 
   5472     /* Read the table entries into the buffer. */
   5473     rv = soc_mem_read_range(unit, EGR_OLP_DGPP_CONFIGm, MEM_BLOCK_ALL,
   5474                             0, (sc->olp_entries_total - 1), eolp_dgpp_cfg_buf);
   5475     if (BCM_FAILURE(rv)) {
   5476         if (eolp_dgpp_cfg_buf) {
   5477             soc_cm_sfree(unit, eolp_dgpp_cfg_buf);
   5478         }
   5479         return rv;
   5480     }
   5481     /* Iterate over the olp mac entries. */
   5482     for (index = 0; index < sc->olp_entries_total; index++) {
   5483         eolp_dgpp_cfg = soc_mem_table_idx_to_pointer
   5484                     (unit, EGR_OLP_DGPP_CONFIGm, egr_olp_dgpp_config_entry_t *,
   5485                      eolp_dgpp_cfg_buf, index);
   5486 
   5487         soc_mem_field_get(unit, EGR_OLP_DGPP_CONFIGm, (uint32 *)eolp_dgpp_cfg, 
   5488                                                   MACDAf, mac_field);
   5489 
   5490         if ((mac_field[0] > 0) || (mac_field[1] > 0)) {
   5491             s_ent_p = (_bcm_l2_station_entry_t *)
   5492                 sal_alloc(sizeof(_bcm_l2_station_entry_t),
   5493                                     "Sw L2 station entry");
   5494             if (NULL == s_ent_p) {
   5495                 if (eolp_dgpp_cfg_buf) {
   5496                     soc_cm_sfree(unit, eolp_dgpp_cfg_buf);
   5497                 }
   5498                 return (BCM_E_MEMORY);
   5499             }
   5500             sal_memset(s_ent_p, 0, sizeof(_bcm_l2_station_entry_t));
   5501 
   5502             s_ent_p->flags = _BCM_L2_STATION_ENTRY_INSTALLED;
   5503             s_ent_p->flags |= _BCM_L2_STATION_ENTRY_TYPE_NON_TCAM;
   5504             s_ent_p->flags |= _BCM_L2_STATION_ENTRY_TYPE_OLP_MAC;
   5505             s_ent_p->prio = 0;
   5506             s_ent_p->sid = ++sc->last_allocated_sid;
   5507             s_ent_p->hw_index = index;
   5508 #if defined(BCM_KATANA2_SUPPORT) 
   5509             if (SOC_IS_KATANA2(unit)) {
   5510                 entry_index = sc->entries_total + sc->port_entries_total + 
   5511                                 index;
   5512             }
   5513 #endif
   5514 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   5515             if (soc_feature(unit, soc_feature_fp_based_oam)) {
   5516                 entry_index = sc->entries_total + index;                
   5517             }
   5518 #endif
   5519             sc->entry_arr[entry_index] = s_ent_p;
   5520 
   5521             sc->olp_entries_free--;
   5522             non_tcam_count++;
   5523             LOG_DEBUG(BSL_LS_BCM_L2,
   5524                     (BSL_META_U(unit,
   5525                                 "OLP station, sid %d, hw_index %d, entry_index %d, olp_station_max %d\n"),
   5526                      s_ent_p->sid, s_ent_p->hw_index, entry_index, sc->olp_entries_total));
   5527 
   5528         }
   5529     }
   5530 
   5531     if (eolp_dgpp_cfg_buf) {
   5532         soc_cm_sfree(unit, eolp_dgpp_cfg_buf);
   5533     }
   5534 
   5535     SOC_IF_ERROR_RETURN(
   5536              READ_EGR_OLP_CONFIGm(unit, MEM_BLOCK_ANY, 0, &eolp_cfg));
   5537 
   5538     soc_mem_field_get(unit, EGR_OLP_CONFIGm, (uint32 *)&eolp_cfg, 
   5539                                                   MACSAf, mac_field);
   5540     if ((mac_field[0] > 0) || (mac_field[1] > 0)) {
   5541         s_ent_p = (_bcm_l2_station_entry_t *)
   5542                 sal_alloc(sizeof(_bcm_l2_station_entry_t),
   5543                                     "Sw L2 station entry");
   5544         if (NULL == s_ent_p) {
   5545             return (BCM_E_MEMORY);
   5546         }
   5547         sal_memset(s_ent_p, 0, sizeof(_bcm_l2_station_entry_t));
   5548         soc_mem_mac_addr_get(unit, EGR_OLP_CONFIGm, &eolp_cfg,
   5549                                              MACSAf, mac_addr);
   5550         s_ent_p->flags = _BCM_L2_STATION_ENTRY_INSTALLED;
   5551         s_ent_p->flags |= _BCM_L2_STATION_ENTRY_TYPE_NON_TCAM;
   5552         s_ent_p->flags |= _BCM_L2_STATION_ENTRY_TYPE_XGS_MAC;
   5553         s_ent_p->prio = 0;
   5554         s_ent_p->sid = ++sc->last_allocated_sid;
   5555         s_ent_p->hw_index = 0;
   5556 #if defined(BCM_KATANA2_SUPPORT) 
   5557         if (SOC_IS_KATANA2(unit)) {
   5558             entry_index = sc->entries_total + sc->port_entries_total +
   5559                             sc->olp_entries_total + s_ent_p->hw_index;
   5560         }
   5561 #endif
   5562 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   5563         if (soc_feature(unit, soc_feature_fp_based_oam)) {
   5564             entry_index = sc->entries_total + sc->olp_entries_total + s_ent_p->hw_index;
   5565         }
   5566 #endif
   5567         sc->entry_arr[entry_index] = s_ent_p;
   5568         non_tcam_count++;
   5569         LOG_DEBUG(BSL_LS_BCM_L2,
   5570                 (BSL_META_U(unit,
   5571                             "XGS station, sid %d, hw_index %d, entry_index %d\n"),
   5572                  s_ent_p->sid, s_ent_p->hw_index, entry_index));
   5573 
   5574     }
   5575     if (non_tcam_count > 0) {
   5576         /* Found NON TCAM valid entry, set OLP API ver */
   5577         _BCM_SWITCH_OLP_APIV_SET(unit, _BCM_SWITCH_OLP_L2_STATION_API);
   5578         LOG_DEBUG(BSL_LS_BCM_L2,
   5579                 (BSL_META_U(unit,
   5580                             "setting _BCM_SWITCH_OLP_L2_STATION_API OLP API ver\n")));
   5581     }
   5582     return (BCM_E_NONE);
   5583 }
   5584 #endif /* BCM_KATANA2_SUPPORT OR BCM_TRIDENT2PLUS_SUPPORT*/
   5585 /*
   5586  * Function:
   5587  *      _bcm_tr_l2_reload_mbi
   5588  * Description:
   5589  *      Load MAC block info from hardware into software data structures.
   5590  * Parameters:
   5591  *      unit - StrataSwitch unit number.
   5592  */
   5593 int
   5594 _bcm_tr_l2_reload_mbi(int unit)
   5595 {
   5596     _bcm_mac_block_info_t *mbi = _mbi_entries[unit];
   5597     l2x_entry_t         *l2x_entry, *l2x_table;
   5598     mac_block_entry_t   mbe;
   5599     int                 index, mb_index, l2x_size;
   5600     pbmp_t              mb_pbmp;
   5601 #if defined(BCM_KATANA2_SUPPORT)
   5602     uint32              fldbuf[SOC_PBMP_WORD_MAX];
   5603     int                 i = 0;
   5604     pbmp_t              mb_pbmp0, mb_pbmp1;
   5605     int                 mask_w0_width = 0;
   5606     int                 member;
   5607 
   5608     SOC_PBMP_CLEAR(mb_pbmp0);
   5609     SOC_PBMP_CLEAR(mb_pbmp1);
   5610 #endif /* BCM_KATANA2_SUPPORT */
   5611 
   5612     /*
   5613      * Refresh MAC Block information from the hardware tables.
   5614      */
   5615 
   5616     for (mb_index = 0; mb_index < _mbi_num[unit]; mb_index++) {
   5617         SOC_IF_ERROR_RETURN
   5618             (READ_MAC_BLOCKm(unit, MEM_BLOCK_ANY, mb_index, &mbe));
   5619 
   5620         SOC_PBMP_CLEAR(mb_pbmp);
   5621 
   5622         if (soc_mem_field_valid(unit, MAC_BLOCKm, MAC_BLOCK_MASK_LOf)) {
   5623 #if defined(BCM_GREYHOUND2_SUPPORT)
   5624                 if (SOC_IS_GREYHOUND2(unit)) {
   5625                     soc_mem_pbmp_field_get(unit, MAC_BLOCKm, &mbe, MAC_BLOCK_MASKf,
   5626                                            &mb_pbmp);
   5627                 } else
   5628 #endif /* BCM_GREYHOUND2_SUPPORT */
   5629                 {
   5630             SOC_PBMP_WORD_SET(mb_pbmp, 0,
   5631                               soc_MAC_BLOCKm_field32_get(unit, &mbe, 
   5632                                                          MAC_BLOCK_MASK_LOf));
   5633                 }
   5634         } else if (soc_mem_field_valid(unit, MAC_BLOCKm, MAC_BLOCK_MASK_W0f)) {
   5635 #if defined(BCM_KATANA2_SUPPORT)
   5636             if (SOC_IS_KATANA2(unit)) {
   5637                 mask_w0_width = soc_mem_field_length(unit, MAC_BLOCKm,
   5638                                                      MAC_BLOCK_MASK_W0f);
   5639                 sal_memset(fldbuf, 0, SOC_PBMP_WORD_MAX * sizeof(uint32));
   5640                 soc_MAC_BLOCKm_field_get(unit, &mbe,
   5641                                          MAC_BLOCK_MASK_W0f, fldbuf);
   5642                 for (i = 0; i < SOC_PBMP_WORD_MAX; i++) {
   5643                     SOC_PBMP_WORD_SET(mb_pbmp0, i, fldbuf[i]);
   5644                 }
   5645             } else
   5646 #endif /* BCM_KATANA2_SUPPORT */
   5647             {
   5648                 SOC_PBMP_WORD_SET(mb_pbmp, 0,
   5649                               soc_MAC_BLOCKm_field32_get(unit, &mbe, 
   5650                                                          MAC_BLOCK_MASK_W0f));
   5651             }
   5652         }else {
   5653             soc_mem_pbmp_field_set(unit, MAC_BLOCKm, &mbe, MAC_BLOCK_MASKf,
   5654                                        &mb_pbmp); 
   5655         }
   5656         if (soc_mem_field_valid(unit, MAC_BLOCKm, MAC_BLOCK_MASK_HIf)) {
   5657             SOC_PBMP_WORD_SET(mb_pbmp, 1,
   5658                           soc_MAC_BLOCKm_field32_get(unit, &mbe, 
   5659                                                      MAC_BLOCK_MASK_HIf));
   5660         } else if (soc_mem_field_valid(unit, MAC_BLOCKm, MAC_BLOCK_MASK_W1f)) {
   5661 #if defined(BCM_KATANA2_SUPPORT)
   5662             if (SOC_IS_KATANA2(unit)) {
   5663                 sal_memset(fldbuf, 0, SOC_PBMP_WORD_MAX * sizeof(uint32));
   5664                 soc_MAC_BLOCKm_field_get(unit, &mbe,
   5665                                          MAC_BLOCK_MASK_W0f, fldbuf);
   5666                 for (i = 0; i < SOC_PBMP_WORD_MAX; i++) {
   5667                     SOC_PBMP_WORD_SET(mb_pbmp1, i, fldbuf[i]);
   5668                 }
   5669             } else
   5670 #endif /* BCM_KATANA2_SUPPORT */
   5671             {
   5672                 SOC_PBMP_WORD_SET(mb_pbmp, 1,
   5673                           soc_MAC_BLOCKm_field32_get(unit, &mbe, 
   5674                                                      MAC_BLOCK_MASK_W1f));
   5675             }
   5676         }
   5677 #if defined(BCM_KATANA2_SUPPORT)
   5678         if (SOC_IS_KATANA2(unit)) {
   5679             SOC_PBMP_OR(mb_pbmp, mb_pbmp0);
   5680             SOC_PBMP_ITER(mb_pbmp1, member) {
   5681                SOC_PBMP_PORT_ADD(mb_pbmp, (member + mask_w0_width));
   5682             }
   5683         }
   5684 #endif /* BCM_KATANA2_SUPPORT */
   5685 
   5686         BCM_PBMP_ASSIGN(mbi[mb_index].mb_pbmp, mb_pbmp);
   5687     }
   5688 
   5689     if (!SOC_CONTROL(unit)->l2x_group_enable) {
   5690         l2x_size = sizeof(l2x_entry_t) * soc_mem_index_count(unit, L2Xm);
   5691         l2x_table = soc_cm_salloc(unit, l2x_size, "l2 reload");
   5692         if (l2x_table == NULL) {
   5693             return BCM_E_MEMORY;
   5694         }
   5695 
   5696         memset((void *)l2x_table, 0, l2x_size);
   5697         if (soc_mem_read_range(unit, L2Xm, MEM_BLOCK_ANY,
   5698                                soc_mem_index_min(unit, L2Xm),
   5699                                soc_mem_index_max(unit, L2Xm),
   5700                                l2x_table) < 0) {
   5701             soc_cm_sfree(unit, l2x_table);
   5702             return SOC_E_INTERNAL;
   5703         }
   5704 
   5705         for (index = soc_mem_index_min(unit, L2Xm);
   5706              index <= soc_mem_index_max(unit, L2Xm); index++) {
   5707 
   5708              l2x_entry = soc_mem_table_idx_to_pointer(unit, L2Xm,
   5709                                                       l2x_entry_t *,
   5710                                                       l2x_table, index);
   5711              if (soc_feature(unit, soc_feature_base_valid)) {
   5712                  if (!soc_L2Xm_field32_get(unit, l2x_entry, BASE_VALIDf)) {
   5713                      continue;
   5714                  }
   5715              } else {
   5716              if (!soc_L2Xm_field32_get(unit, l2x_entry, VALIDf)) {
   5717                  continue;
   5718              }
   5719              }
   5720   
   5721              mb_index = soc_L2Xm_field32_get(unit, l2x_entry, MAC_BLOCK_INDEXf);
   5722              mbi[mb_index].ref_count++;
   5723         }
   5724         soc_cm_sfree(unit, l2x_table);
   5725     }
   5726 
   5727     return BCM_E_NONE;
   5728 }
   5729 
   5730 #if defined(BCM_TRIUMPH_SUPPORT) /* BCM_TRIUMPH_SUPPORT */
   5731  
   5732 /*
   5733  * Function:
   5734  *     _bcm_tr_l2_station_entry_reload
   5735  * Purpose:
   5736  *     Re-construct L2 station control structure software state
   5737  *     from installed hardware entries
   5738  * Parameters:
   5739  *     unit       - (IN) BCM device number
   5740  * Returns:
   5741  *     BCM_E_XXX
   5742  */
   5743 STATIC int
   5744 _bcm_tr_l2_station_entry_reload(int unit, int overlay)
   5745 {
   5746     _bcm_l2_station_control_t *sc;               /* Pointer to station        */
   5747                                                  /* control structure.        */
   5748     int                       rv;                /* Operation return status.  */
   5749     uint32                    *tcam_buf = NULL;  /* Buffer to store TCAM      */
   5750                                                  /* table entries.            */
   5751     soc_mem_t                 tcam_mem;          /* Memory name.              */
   5752     int                       entry_mem_size;    /* Size of TCAM table entry. */
   5753     int                       index;             /* Table index iterator.     */
   5754     _bcm_l2_station_entry_t   *s_ent_p;          /* Station table entry.      */
   5755     mpls_station_tcam_entry_t *mpls_station_ent; /* Table entry pointer.      */
   5756 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_GREYHOUND2_SUPPORT)
   5757     my_station_tcam_entry_t   *my_station_ent;   /* Table entry pointer.      */
   5758 #endif
   5759 
   5760 #ifdef BCM_RIOT_SUPPORT
   5761     if (overlay == _BCM_L2_STATION_ENTRY_OVERLAY) {
   5762         entry_mem_size = sizeof(my_station_tcam_2_entry_t);
   5763     } else
   5764 #endif /* BCM_RIOT_SUPPORT */
   5765 
   5766 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_GREYHOUND2_SUPPORT)
   5767     if (SOC_IS_KATANAX(unit)
   5768         || SOC_IS_TRIDENT(unit)
   5769         || SOC_IS_TRIUMPH3(unit) || SOC_IS_TD2_TT2(unit)
   5770         || soc_feature(unit, soc_feature_gh2_my_station)) {
   5771 
   5772         entry_mem_size = sizeof(my_station_tcam_entry_t);
   5773 
   5774     } else 
   5775 #endif
   5776 
   5777     if (SOC_IS_ENDURO(unit) || SOC_IS_TRIUMPH(unit)
   5778         || SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit)
   5779         || SOC_IS_VALKYRIE(unit) || SOC_IS_VALKYRIE2(unit)
   5780         || SOC_IS_HURRICANE(unit) || SOC_IS_HURRICANE2(unit)) {
   5781 
   5782         entry_mem_size = sizeof(mpls_station_tcam_entry_t);
   5783 
   5784     } else {
   5785         entry_mem_size = 0;
   5786     }
   5787 
   5788     if (0 == entry_mem_size) {
   5789         return (BCM_E_INTERNAL);
   5790     }
   5791 
   5792     BCM_IF_ERROR_RETURN(_bcm_l2_station_control_get(unit, &sc));
   5793 
   5794     SC_LOCK(sc);
   5795 
   5796     rv = _bcm_l2_station_tcam_mem_get(unit, overlay, &tcam_mem);
   5797     if (BCM_FAILURE(rv)) {
   5798         SC_UNLOCK(sc);
   5799         return (rv);
   5800     }
   5801 
   5802     /* Allocate buffer to store the DMAed table entries. */
   5803     tcam_buf = soc_cm_salloc(unit, entry_mem_size * sc->entries_total,
   5804                               "STATION TCAM buffer");
   5805     if (NULL == tcam_buf) {
   5806         SC_UNLOCK(sc);
   5807         return (BCM_E_MEMORY);
   5808     }
   5809     /* Initialize the entry buffer. */
   5810     sal_memset(tcam_buf, 0, sizeof(entry_mem_size) * sc->entries_total);
   5811 
   5812     if (!SOC_MEM_IS_VALID(unit, tcam_mem)) {
   5813         /* Added in for low latency mode since tcam_mem is not valid */
   5814         goto cleanup;
   5815     } 
   5816 
   5817     /* Read the table entries into the buffer. */
   5818     rv = soc_mem_read_range(unit, tcam_mem, MEM_BLOCK_ALL,
   5819                             0, (sc->entries_total - 1), tcam_buf);
   5820     if (BCM_FAILURE(rv)) {
   5821         goto cleanup;
   5822     }
   5823 
   5824     /* Iterate over the table entries. */
   5825     for (index = 0; index < sc->entries_total; index++) {
   5826 #ifdef BCM_RIOT_SUPPORT
   5827         if (overlay == _BCM_L2_STATION_ENTRY_OVERLAY) {
   5828             my_station_ent = soc_mem_table_idx_to_pointer(unit,
   5829                                  tcam_mem, my_station_tcam_entry_t *,
   5830                                  tcam_buf, index);
   5831             if (0 == soc_MY_STATION_TCAM_2m_field32_get
   5832                         (unit, my_station_ent, VALIDf)) {
   5833                 continue;
   5834             }
   5835         } else
   5836 #endif /* BCM_RIOT_SUPPORT */
   5837 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_GREYHOUND2_SUPPORT)
   5838         if (SOC_IS_KATANAX(unit)
   5839             || SOC_IS_TRIDENT(unit)
   5840             || SOC_IS_TRIUMPH3(unit)
   5841             || SOC_IS_TD2_TT2(unit)
   5842             || soc_feature(unit, soc_feature_gh2_my_station)) {
   5843 
   5844             my_station_ent
   5845                 = soc_mem_table_idx_to_pointer
   5846                     (unit, tcam_mem, my_station_tcam_entry_t *,
   5847                      tcam_buf, index);
   5848 
   5849             if (0 == soc_MY_STATION_TCAMm_field32_get
   5850                         (unit, my_station_ent, VALIDf)) {
   5851                 continue;
   5852             }
   5853 
   5854         } else
   5855 #endif
   5856         if (SOC_IS_ENDURO(unit) || SOC_IS_TRIUMPH(unit)
   5857             || SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit)
   5858             || SOC_IS_VALKYRIE(unit) || SOC_IS_VALKYRIE2(unit)
   5859             || SOC_IS_HURRICANE(unit) || SOC_IS_HURRICANE2(unit)) {
   5860 
   5861             mpls_station_ent
   5862                 = soc_mem_table_idx_to_pointer
   5863                     (unit, tcam_mem, mpls_station_tcam_entry_t *,
   5864                      tcam_buf, index);
   5865 
   5866             if (0 == soc_MPLS_STATION_TCAMm_field32_get
   5867                         (unit, mpls_station_ent, VALIDf)) {
   5868                 continue;
   5869             }
   5870         }
   5871 
   5872         s_ent_p
   5873             = (_bcm_l2_station_entry_t *)
   5874                 sal_alloc(sizeof(_bcm_l2_station_entry_t),
   5875                           "Sw L2 station entry");
   5876         if (NULL == s_ent_p) {
   5877             rv = BCM_E_MEMORY;
   5878             goto cleanup;
   5879         }
   5880 
   5881         sal_memset(s_ent_p, 0, sizeof(_bcm_l2_station_entry_t));
   5882 
   5883 #ifdef BCM_RIOT_SUPPORT
   5884         if (overlay == _BCM_L2_STATION_ENTRY_OVERLAY) {
   5885             s_ent_p->sid = ++sc->last_allocated_sid_2;
   5886             s_ent_p->prio = (sc->entries_total_2 - index);
   5887             sc->entries_free_2--;
   5888             sc->entry_count_2++;
   5889             sc->entry_arr_2[index] = s_ent_p;
   5890         } else
   5891 #endif /* BCM_RIOT_SUPPORT */
   5892         {
   5893             s_ent_p->sid = ++sc->last_allocated_sid;
   5894             s_ent_p->prio = (sc->entries_total - index);
   5895             sc->entries_free--;
   5896             sc->entry_count++;
   5897             sc->entry_arr[index] = s_ent_p;
   5898         }
   5899         s_ent_p->hw_index = index;
   5900         s_ent_p->flags |= _BCM_L2_STATION_ENTRY_INSTALLED;
   5901     }
   5902 #if defined(BCM_KATANA2_SUPPORT) || defined(BCM_TRIDENT2PLUS_SUPPORT)
   5903     if (SOC_IS_KATANA2(unit) || 
   5904             soc_feature(unit, soc_feature_fp_based_oam)) {
   5905 
   5906         /* 
   5907          * In case of KT2,SB2 and TD2+ NONTCAM STATION related to OAM, OLP, XGS can be programmed
   5908          * by either of bcm_l2_station_xxx API or  bcm_switch_olp_l2_addr_xxx
   5909          *
   5910          * Do not process NONTCAM entry if these were not programmed by bcm_l2_station_xxx
   5911          */
   5912 
   5913         if (_BCM_SWITCH_OLP_APIV(unit) == _BCM_SWITCH_OLP_TRUE_API) {
   5914             LOG_DEBUG(BSL_LS_BCM_L2,
   5915                     (BSL_META_U(unit,
   5916                                 "bcm_switch_olp_l2_addr_xxx are used already,DO NOT recover NONTCAM ENTRY\n")));
   5917             /* Fall thru */
   5918         } else {
   5919             /* Go ahead to recover NON TCAM entry */
   5920             rv = _bcm_l2_station_non_tcam_reload(unit, sc); 
   5921         }
   5922     }
   5923 #endif 
   5924 
   5925 cleanup:
   5926 
   5927     SC_UNLOCK(sc);
   5928 
   5929     if (tcam_buf) {
   5930         soc_cm_sfree(unit, tcam_buf);
   5931     }
   5932 
   5933     return (rv);
   5934 }
   5935 
   5936 /*
   5937  * Function:
   5938  *     _bcm_tr_l2_station_reload
   5939  * Purpose:
   5940  *     Re-construct L2 station control structure software state
   5941  *     from installed hardware entries
   5942  * Parameters:
   5943  *     unit       - (IN) BCM device number
   5944  * Returns:
   5945  *     BCM_E_XXX
   5946  */
   5947 int
   5948 _bcm_tr_l2_station_reload(int unit)
   5949 {
   5950     int rv;
   5951 
   5952     rv = _bcm_tr_l2_station_entry_reload(unit,
   5953              _BCM_L2_STATION_ENTRY_UNDERLAY);
   5954     BCM_IF_ERROR_RETURN(rv);
   5955 
   5956 #ifdef BCM_RIOT_SUPPORT
   5957     if (soc_feature(unit, soc_feature_riot)) {
   5958         rv = _bcm_tr_l2_station_entry_reload(unit,
   5959                  _BCM_L2_STATION_ENTRY_OVERLAY);
   5960         BCM_IF_ERROR_RETURN(rv);
   5961     }
   5962 #endif /* BCM_RIOT_SUPPORT */
   5963 
   5964    return BCM_E_NONE;
   5965 }
   5966 
   5967 
   5968 #endif /* !BCM_TRIUMPH_SUPPORT */
   5969 #endif /* BCM_WARM_BOOT_SUPPORT */
   5970 
   5971 
   5972 
   5973 /*
   5974  * Function:
   5975  *      _tr_l2x_delete_all
   5976  * Purpose:
   5977  *      Clear the L2 table by invalidating entries.
   5978  * Parameters:
   5979  *      unit - StrataSwitch unit #
   5980  *      static_too - if TRUE, delete static and non-static entries;
   5981  *                   if FALSE, delete only non-static entries
   5982  * Returns:
   5983  *      SOC_E_XXX
   5984  */
   5985 
   5986 static int
   5987 _tr_l2x_delete_all(int unit)
   5988 {
   5989     soc_control_t *soc = SOC_CONTROL(unit);
   5990     int copyno;
   5991     int index_min, index_max, index, mem_max;
   5992     l2_entry_only_entry_t *l2x_entry;
   5993     int rv = SOC_E_NONE;
   5994     int *buffer = NULL;
   5995     int mem_size, idx;
   5996     int modified;
   5997     uint32 key_type;
   5998 
   5999 #if defined(BCM_TRIUMPH_SUPPORT)
   6000     _soc_tr_l2e_ppa_info_t    *ppa_info = NULL;
   6001 #endif
   6002 
   6003 #ifdef BCM_TRIDENT_SUPPORT
   6004     if (soc_feature(unit, soc_feature_l2_bulk_control)) {
   6005 #ifdef BCM_TOMAHAWK_SUPPORT
   6006         if (soc_feature(unit, soc_feature_l2_bulk_unified_table)) {
   6007             l2_bulk_entry_t match_mask;
   6008             l2_bulk_entry_t match_data;
   6009             int field_len;
   6010     
   6011             sal_memset(&match_mask, 0, sizeof(match_mask));
   6012             sal_memset(&match_data, 0, sizeof(match_data));
   6013     
   6014             if (soc_feature(unit, soc_feature_base_valid)) {
   6015                 soc_mem_field32_set(unit, L2_BULKm, &match_mask, BASE_VALIDf, 1);
   6016                 soc_mem_field32_set(unit, L2_BULKm, &match_data, BASE_VALIDf, 1);
   6017             } else {
   6018             soc_mem_field32_set(unit, L2_BULKm, &match_mask, VALIDf, 1);
   6019             soc_mem_field32_set(unit, L2_BULKm, &match_data, VALIDf, 1);
   6020             }
   6021     
   6022             field_len = soc_mem_field_length(unit, L2_BULKm, KEY_TYPEf);
   6023             soc_mem_field32_set(unit, L2_BULKm, &match_mask, KEY_TYPEf,
   6024                                 (1 << field_len) - 1);
   6025     
   6026             soc_mem_lock(unit, L2Xm);
   6027             rv = soc_reg_field32_modify(unit, L2_BULK_CONTROLr, REG_PORT_ANY,
   6028                                         ACTIONf, 1);
   6029             if (BCM_FAILURE(rv)) {
   6030                 soc_mem_unlock(unit, L2Xm);
   6031                 return rv;
   6032             }
   6033             rv = soc_reg_field32_modify(unit, L2_BULK_CONTROLr, REG_PORT_ANY,
   6034                                NUM_ENTRIESf, soc_mem_index_count(unit, L2Xm));
   6035             if (BCM_FAILURE(rv)) {
   6036                 soc_mem_unlock(unit, L2Xm);
   6037                 return rv;
   6038             }
   6039             if (BCM_SUCCESS(rv)) {
   6040                 rv = WRITE_L2_BULKm(unit, MEM_BLOCK_ALL,
   6041                          _BCM_L2_BULK_MATCH_MASK_INX, &match_mask);
   6042             }
   6043     
   6044             /* Remove all KEY_TYPE 0 entries */
   6045             if (BCM_SUCCESS(rv)) {
   6046                 rv = WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 
   6047                       _BCM_L2_BULK_MATCH_DATA_INX, &match_data);
   6048                 if (BCM_SUCCESS(rv)) {
   6049                     rv = soc_l2x_port_age(unit, L2_BULK_CONTROLr, INVALIDr);
   6050                 }
   6051             }
   6052     
   6053             /* Remove all KEY_TYPE 3 entries */
   6054             if (BCM_SUCCESS(rv)) {
   6055                 soc_mem_field32_set(unit, L2_BULKm, &match_data,
   6056                                     KEY_TYPEf, 3);
   6057                 rv = WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, 
   6058                       _BCM_L2_BULK_MATCH_DATA_INX, &match_data);
   6059                 if (BCM_SUCCESS(rv)) {
   6060                     rv = soc_l2x_port_age(unit, L2_BULK_CONTROLr, INVALIDr);
   6061                 }
   6062             }
   6063         } else
   6064 #endif /* BCM_TOMAHAWK_SUPPORT */
   6065         {
   6066             l2_bulk_match_mask_entry_t match_mask;
   6067             l2_bulk_match_data_entry_t match_data;
   6068             int field_len;
   6069     
   6070             sal_memset(&match_mask, 0, sizeof(match_mask));
   6071             sal_memset(&match_data, 0, sizeof(match_data));
   6072     
   6073             soc_mem_field32_set(unit, L2_BULK_MATCH_MASKm, 
   6074                                 &match_mask, VALIDf, 1);
   6075             soc_mem_field32_set(unit, L2_BULK_MATCH_DATAm, 
   6076                                 &match_data, VALIDf, 1);
   6077     
   6078             field_len = soc_mem_field_length(unit, L2_BULK_MATCH_MASKm, 
   6079                             KEY_TYPEf);
   6080             soc_mem_field32_set(unit, L2_BULK_MATCH_MASKm, &match_mask, 
   6081                                 KEY_TYPEf, (1 << field_len) - 1);
   6082     
   6083             soc_mem_lock(unit, L2Xm);
   6084             rv = soc_reg_field32_modify(unit, L2_BULK_CONTROLr, REG_PORT_ANY,
   6085                                         ACTIONf, 1);
   6086             if (BCM_SUCCESS(rv)) {
   6087                 rv = WRITE_L2_BULK_MATCH_MASKm(unit, MEM_BLOCK_ALL, 0,
   6088                                                &match_mask);
   6089             }
   6090     
   6091             /* Remove all KEY_TYPE 0 entries */
   6092             if (BCM_SUCCESS(rv)) {
   6093                 rv = WRITE_L2_BULK_MATCH_DATAm(unit, MEM_BLOCK_ALL, 0,
   6094                                                &match_data);
   6095                 if (BCM_SUCCESS(rv)) {
   6096                     rv = soc_l2x_port_age(unit, L2_BULK_CONTROLr, INVALIDr);
   6097                 }
   6098             }
   6099     
   6100             /* Remove all KEY_TYPE 3 entries */
   6101             if (BCM_SUCCESS(rv)) {
   6102                 soc_mem_field32_set(unit, L2_BULK_MATCH_DATAm, &match_data,
   6103                                     KEY_TYPEf, 3);
   6104                 rv = WRITE_L2_BULK_MATCH_DATAm(unit, MEM_BLOCK_ALL, 0,
   6105                                                &match_data);
   6106                 if (BCM_SUCCESS(rv)) {
   6107                     rv = soc_l2x_port_age(unit, L2_BULK_CONTROLr, INVALIDr);
   6108                 }
   6109             }
   6110         }
   6111     } else
   6112 #endif /* BCM_TRIDENT_SUPPORT */
   6113     {
   6114         index_min = soc_mem_index_min(unit, L2_ENTRY_ONLYm);
   6115         mem_max = soc_mem_index_max(unit, L2_ENTRY_ONLYm);
   6116         mem_size =  DEFAULT_L2DELETE_CHUNKS * sizeof(l2_entry_only_entry_t);
   6117     
   6118         buffer = soc_cm_salloc(unit, mem_size, "L2_ENTRY_ONLY_delete");
   6119         if (NULL == buffer) {
   6120             return SOC_E_MEMORY;
   6121         }
   6122 
   6123         soc_mem_lock(unit, L2Xm);
   6124         for (idx = index_min; idx < mem_max; idx += DEFAULT_L2DELETE_CHUNKS) {
   6125             index_max = idx + DEFAULT_L2DELETE_CHUNKS - 1;
   6126             if ( index_max > mem_max) {
   6127                 index_max = mem_max;
   6128             }
   6129             if ((rv = soc_mem_read_range(unit, L2_ENTRY_ONLYm, MEM_BLOCK_ALL,
   6130                                          idx, index_max, buffer)) < 0 ) {
   6131                 soc_cm_sfree(unit, buffer);
   6132                 soc_mem_unlock(unit, L2Xm);
   6133                 return rv;
   6134             }
   6135             modified = FALSE;
   6136             for (index = 0; index < DEFAULT_L2DELETE_CHUNKS; index++) {
   6137                 l2x_entry =
   6138                     soc_mem_table_idx_to_pointer(unit, L2_ENTRY_ONLYm,
   6139                                                  l2_entry_only_entry_t *,
   6140                                                  buffer, index);
   6141                 if (!soc_L2_ENTRY_ONLYm_field32_get(unit, l2x_entry, VALIDf)) {
   6142                     continue;
   6143                 }
   6144                 key_type = soc_L2_ENTRY_ONLYm_field32_get(unit, l2x_entry,
   6145                                                           KEY_TYPEf);
   6146                 if (key_type ==  TR_L2_HASH_KEY_TYPE_BRIDGE ||
   6147                     key_type == TR_L2_HASH_KEY_TYPE_VFI) {
   6148                     sal_memcpy(l2x_entry,
   6149                                soc_mem_entry_null(unit, L2_ENTRY_ONLYm),
   6150                                sizeof(l2_entry_only_entry_t));
   6151                     modified = TRUE;
   6152                 }
   6153             }
   6154             if (!modified) {
   6155                 continue;
   6156             }
   6157             if ((rv = soc_mem_write_range(unit, L2_ENTRY_ONLYm, MEM_BLOCK_ALL, 
   6158                                           idx, index_max, buffer)) < 0) {
   6159                 soc_cm_sfree(unit, buffer);
   6160                 soc_mem_unlock(unit, L2Xm);
   6161                 return rv;
   6162             }
   6163         }
   6164         soc_cm_sfree(unit, buffer);
   6165     }
   6166 
   6167     if (soc->arlShadow != NULL) {
   6168         sal_mutex_take(soc->arlShadowMutex, sal_mutex_FOREVER);
   6169         (void) shr_avl_delete_all(soc->arlShadow);
   6170         sal_mutex_give(soc->arlShadowMutex);
   6171     }
   6172 
   6173     copyno = SOC_MEM_BLOCK_ANY(unit, L2Xm);
   6174     if (SOC_MEM_BLOCK_VALID(unit, L2Xm, copyno)) {
   6175         SOP_MEM_STATE(unit, L2Xm).count[copyno] = 0;
   6176     }
   6177 
   6178     /* Clear external L2 table if it exists */
   6179     if (soc_mem_is_valid(unit, EXT_L2_ENTRYm) &&
   6180         soc_mem_index_count(unit, EXT_L2_ENTRYm)) {
   6181         rv = soc_mem_clear(unit, EXT_L2_ENTRY_TCAMm,
   6182                                           MEM_BLOCK_ALL, TRUE);
   6183         if (SOC_FAILURE(rv)) {
   6184             soc_mem_unlock(unit, L2Xm);
   6185             return (rv);
   6186         }
   6187         rv = soc_mem_clear(unit, EXT_L2_ENTRY_DATAm,
   6188                                           MEM_BLOCK_ALL, TRUE);
   6189         if (SOC_FAILURE(rv)) {
   6190             soc_mem_unlock(unit, L2Xm);
   6191             return (rv);
   6192         }
   6193 
   6194 #if defined(BCM_TRIUMPH_SUPPORT)
   6195         ppa_info = SOC_CONTROL(unit)->ext_l2_ppa_info;
   6196         if (NULL != ppa_info) {
   6197             rv = _soc_tr_l2e_ppa_init(unit);
   6198             if (SOC_FAILURE(rv)) {
   6199                 soc_mem_unlock(unit, L2Xm);
   6200                 return (rv);
   6201             }
   6202         }
   6203 #endif
   6204     }
   6205 #if defined(BCM_HURRICANE3_SUPPORT)
   6206     /* Clear L2 overflow table if it exists */
   6207     if (soc_mem_is_valid(unit, L2_ENTRY_OVERFLOWm) &&
   6208         soc_mem_index_count(unit, L2_ENTRY_OVERFLOWm)) {
   6209         rv = soc_mem_clear(unit, L2_ENTRY_OVERFLOWm,
   6210                                           MEM_BLOCK_ALL, TRUE);
   6211         if (SOC_FAILURE(rv)) {
   6212             soc_mem_unlock(unit, L2Xm);
   6213             return (rv);
   6214         }
   6215     }
   6216 #endif /* BCM_HURRICANE3_SUPPORT */
   6217 
   6218     soc_mem_unlock(unit, L2Xm);
   6219 
   6220     return rv;
   6221 }
   6222 
   6223 #if defined(BCM_TRIDENT3_SUPPORT)
   6224 /*
   6225  * Function:
   6226  *      _bcm_td3_lport_cml_config
   6227  * Description:
   6228  *      save/restore the fields in the LPORT Profile Table
   6229  * Parameters:
   6230  *      unit          - (IN) Device number
   6231  *      port          - (IN) Port number (NON gport)
   6232  *      save          - (IN) True for save and false for resetore purpose
   6233  *      save_cml      - (IN/OUT) CML_FLAGS_NEW
   6234  *      save_cml_move - (IN/OUT) CML_FLAGS_MOVE
   6235  */
   6236  int
   6237 _bcm_td3_lport_cml_config(int unit, bcm_port_t port, int save,
   6238                            int *save_cml, int *save_cml_move)
   6239 {
   6240     int rv;
   6241     int src_index;
   6242     uint32 src_ent[SOC_MAX_MEM_FIELD_WORDS];
   6243     lport_tab_entry_t lport_entry;
   6244     uint32 lport_index, old_lport_index;
   6245     soc_mem_t mem = LPORT_TABm;
   6246     void *entries[2], *entry;
   6247     soc_mem_t src_mem = ING_DEVICE_PORTm;
   6248 
   6249     /* Make sure port module is initialized. */
   6250     soc_mem_lock(unit, src_mem);
   6251     src_index = port;
   6252 
   6253     rv = soc_mem_read(unit, src_mem, MEM_BLOCK_ANY, src_index, src_ent);
   6254     if(BCM_FAILURE(rv)) {
   6255         soc_mem_unlock(unit, src_mem);
   6256         return rv;
   6257     }
   6258 
   6259     old_lport_index =
   6260         soc_mem_field32_get(unit, src_mem, src_ent, LPORT_PROFILE_IDXf);
   6261 
   6262     entries[0] = &lport_entry;
   6263     rv = _bcm_lport_ind_profile_entry_get(unit, old_lport_index, 1, entries);
   6264     if(BCM_FAILURE(rv)) {
   6265         soc_mem_unlock(unit, src_mem);
   6266         return rv;
   6267     }
   6268 
   6269     /* Update fields */
   6270     entry = entries[0];
   6271     if(save) {
   6272         *save_cml=
   6273             soc_mem_field32_get(unit, mem, entry, CML_FLAGS_NEWf);
   6274         *save_cml_move=
   6275             soc_mem_field32_get(unit, mem, entry, CML_FLAGS_MOVEf);
   6276         soc_mem_field32_set(unit, mem, entry, CML_FLAGS_NEWf, *save_cml &0x03);
   6277         soc_mem_field32_set(unit, mem, entry, CML_FLAGS_MOVEf, *save_cml_move & 0x03);
   6278     } else { /*restore*/
   6279         soc_mem_field32_set(unit, mem, entry, CML_FLAGS_NEWf, *save_cml);
   6280         soc_mem_field32_set(unit, mem, entry, CML_FLAGS_MOVEf, *save_cml_move);
   6281     }
   6282 
   6283     rv = _bcm_lport_ind_profile_entry_add(unit, entries, 1, &lport_index);
   6284     if(BCM_FAILURE(rv)) {
   6285         soc_mem_unlock(unit, src_mem);
   6286         return rv;
   6287     }
   6288 
   6289     /* Update Source Table LPORT profile index  */
   6290     soc_mem_field32_set(unit, src_mem, src_ent, LPORT_PROFILE_IDXf,lport_index);
   6291     rv = soc_mem_write(unit, src_mem, MEM_BLOCK_ALL, src_index, src_ent);
   6292     soc_mem_unlock(unit, src_mem);
   6293     if(BCM_FAILURE(rv)) {
   6294         return rv;
   6295     }
   6296 
   6297     /*
   6298      * Entry must be 'deleted' because the mem profile 'add' routine
   6299      * always increments count even though the same entry is used.
   6300      */
   6301     rv = _bcm_lport_ind_profile_entry_delete(unit, old_lport_index);
   6302 
   6303     return rv;
   6304 }
   6305 #endif /*BCM_TRIDENT3_SUPPORT*/
   6306 /*
   6307  * Function:
   6308  *      bcm_tr_l2_init
   6309  * Description:
   6310  *      Initialize chip-dependent parts of L2 module
   6311  * Parameters:
   6312  *      unit - StrataSwitch unit number.
   6313  */
   6314 
   6315 int
   6316 bcm_tr_l2_init(int unit)
   6317 {
   6318     int         was_running = FALSE;
   6319     int         rv = BCM_E_NONE;
   6320     uint32      flags;
   6321     sal_usecs_t interval;
   6322 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   6323     uint64      regval64;
   6324     int         my_station_config = 0;
   6325 #endif
   6326 
   6327 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   6328     COMPILER_64_ZERO(regval64);
   6329     /* Enable L2 entry used as my station hit */
   6330     my_station_config = soc_property_get(unit,
   6331                                    spn_L2_ENTRY_USED_AS_MY_STATION, 0);
   6332     if (soc_feature(unit, soc_feature_l2_entry_used_as_my_station)) {
   6333         SOC_IF_ERROR_RETURN(READ_ING_CONFIG_64r(unit, &regval64));
   6334         if (my_station_config != soc_reg64_field32_get(unit, ING_CONFIG_64r,
   6335             regval64, L2_ENTRY_USED_AS_MY_STATIONf)) {
   6336                 BCM_IF_ERROR_RETURN
   6337                     (soc_reg_field32_modify(unit, ING_CONFIG_64r, REG_PORT_ANY,
   6338                              L2_ENTRY_USED_AS_MY_STATIONf, my_station_config));
   6339         }
   6340     }
   6341 #endif
   6342 
   6343     if (soc_l2x_running(unit, &flags, &interval)) { 	 
   6344         was_running = TRUE; 	 
   6345         BCM_IF_ERROR_RETURN(soc_l2x_stop(unit)); 	 
   6346     }
   6347 
   6348     if (!SOC_WARM_BOOT(unit) && !SOC_IS_RCPU_ONLY(unit) &&
   6349         !SOC_HW_RESET(unit)) {
   6350         if (!(SAL_BOOT_QUICKTURN || 
   6351               ((SAL_BOOT_SIMULATION || SAL_BOOT_BCMSIM || SAL_BOOT_XGSSIM) 
   6352                && !SOC_IS_TOMAHAWKX(unit) && !SOC_IS_TRIDENT3X(unit))
   6353              )) {
   6354             _tr_l2x_delete_all(unit);
   6355         }
   6356     }
   6357 
   6358     if (_mbi_entries[unit] != NULL) {
   6359         sal_free(_mbi_entries[unit]);
   6360         _mbi_entries[unit] = NULL;
   6361     }
   6362 
   6363     _mbi_num[unit] = (SOC_MEM_INFO(unit, MAC_BLOCKm).index_max -
   6364                       SOC_MEM_INFO(unit, MAC_BLOCKm).index_min + 1);
   6365     _mbi_entries[unit] = sal_alloc(_mbi_num[unit] *
   6366                                    sizeof(_bcm_mac_block_info_t),
   6367                                    "BCM L2X MAC blocking info");
   6368     if (!_mbi_entries[unit]) {
   6369         return BCM_E_MEMORY;
   6370     }
   6371     sal_memset(_mbi_entries[unit], 0, _mbi_num[unit] * sizeof(_bcm_mac_block_info_t));
   6372 
   6373 #if defined(BCM_TRIUMPH_SUPPORT)
   6374     if (SOC_IS_TR_VL(unit)
   6375         && !SOC_IS_HURRICANEX(unit) && !SOC_IS_GREYHOUND(unit)) {
   6376         BCM_IF_ERROR_RETURN(_bcm_tr_l2_station_control_init(unit));
   6377     }
   6378 #endif
   6379 
   6380 #if defined(BCM_TRIUMPH_SUPPORT)
   6381     if (soc_feature(unit, soc_feature_mysta_profile)) {
   6382         BCM_IF_ERROR_RETURN(_bcm_l2_mysta_profile_init(unit));
   6383     }
   6384 #endif
   6385 
   6386 #ifdef BCM_WARM_BOOT_SUPPORT
   6387     if (SOC_WARM_BOOT(unit)) {
   6388         BCM_IF_ERROR_RETURN(_bcm_tr_l2_reload_mbi(unit));
   6389 
   6390 #if defined(BCM_TRIUMPH_SUPPORT)
   6391         if (SOC_IS_TR_VL(unit)
   6392             && !SOC_IS_HURRICANEX(unit) && !SOC_IS_GREYHOUND(unit)) {
   6393             BCM_IF_ERROR_RETURN(_bcm_tr_l2_station_reload(unit));
   6394         }
   6395 #endif
   6396     }
   6397 #endif
   6398 
   6399      /* Control structure for L2_BULK matched traverse */
   6400     if (soc_feature(unit, soc_feature_l2_bulk_control)) {
   6401         sal_sem_t sem;
   6402         if (_bcm_l2_match_ctrl[unit] == NULL) {
   6403             _bcm_l2_match_ctrl[unit] = sal_alloc(sizeof(_bcm_l2_match_ctrl_t),
   6404                                                  "matched_traverse control");
   6405             if (_bcm_l2_match_ctrl[unit] == NULL) {
   6406                 return BCM_E_MEMORY;
   6407             }
   6408             sem = sal_sem_create("L2_matched", sal_sem_BINARY, 0);
   6409             if (sem == NULL) {
   6410                 sal_free(_bcm_l2_match_ctrl[unit]);
   6411                 _bcm_l2_match_ctrl[unit] = NULL;
   6412                 return BCM_E_MEMORY;
   6413             }
   6414         } else {
   6415             sem = _bcm_l2_match_ctrl[unit]->sem;
   6416         }
   6417 
   6418         sal_memset(_bcm_l2_match_ctrl[unit], 0, sizeof(_bcm_l2_match_ctrl_t));
   6419         _bcm_l2_match_ctrl[unit]->sem = sem;
   6420     }
   6421 
   6422     rv = _bcm_tr_l2_memacc_init(unit);
   6423     if (BCM_FAILURE(rv)) {
   6424         if (soc_feature(unit, soc_feature_l2_bulk_control)) {
   6425             if (_bcm_l2_match_ctrl[unit] != NULL) {
   6426                 if (_bcm_l2_match_ctrl[unit]->sem != NULL) {
   6427                     sal_sem_destroy(_bcm_l2_match_ctrl[unit]->sem);
   6428                 }
   6429                 sal_free(_bcm_l2_match_ctrl[unit]);
   6430                 _bcm_l2_match_ctrl[unit] = NULL;
   6431             }
   6432         }
   6433         return rv;
   6434     }
   6435 
   6436     /* bcm_l2_register clients */
   6437     
   6438     soc_l2x_register(unit, _bcm_l2_register_callback, NULL);
   6439 #ifdef BCM_TRIDENT3_SUPPORT
   6440     if (SOC_IS_TRIDENT3X(unit)) {
   6441         soc_l2x_cml_register(unit, _bcm_td3_lport_cml_config);
   6442     }
   6443 #endif /*BCM_TRIDENT3_SUPPORT*/
   6444     if (was_running) {
   6445         interval = (SAL_BOOT_BCMSIM && !SOC_IS_TRIDENT3X(unit)) ? \
   6446                     BCMSIM_L2XMSG_INTERVAL : interval;
   6447         soc_l2x_start(unit, flags, interval);
   6448     }
   6449 
   6450     return BCM_E_NONE;
   6451 }
   6452 
   6453 /*
   6454  * Function:
   6455  *      bcm_tr_l2_term
   6456  * Description:
   6457  *      Finalize chip-dependent parts of L2 module
   6458  * Parameters:
   6459  *      unit - StrataSwitch unit number.
   6460  */
   6461 
   6462 int
   6463 bcm_tr_l2_term(int unit)
   6464 {
   6465     if (_mbi_entries[unit] != NULL) {
   6466         sal_free(_mbi_entries[unit]);
   6467         _mbi_entries[unit] = NULL;
   6468     }
   6469 
   6470 #if defined(BCM_TRIUMPH_SUPPORT)
   6471     if (SOC_IS_TR_VL(unit)) {
   6472         BCM_IF_ERROR_RETURN(_bcm_tr_l2_station_control_deinit(unit));
   6473     }
   6474 
   6475     if (soc_feature(unit, soc_feature_mysta_profile)) {
   6476         BCM_IF_ERROR_RETURN(_bcm_l2_mysta_profile_detach(unit));
   6477     }
   6478 #endif
   6479 
   6480     if (_bcm_l2_match_ctrl[unit] != NULL) {
   6481        if (_bcm_l2_match_ctrl[unit]->sem != NULL) {
   6482           sal_sem_destroy(_bcm_l2_match_ctrl[unit]->sem);
   6483        }
   6484        sal_free(_bcm_l2_match_ctrl[unit]);
   6485       _bcm_l2_match_ctrl[unit] = NULL;
   6486     }
   6487 
   6488     BCM_IF_ERROR_RETURN(_bcm_tr_l2_memacc_deinit(unit));
   6489 
   6490     return BCM_E_NONE;
   6491 }
   6492 
   6493 STATIC int
   6494 _bcm_tr_dual_l2_conflict_get(int unit, bcm_l2_addr_t *addr,
   6495                              bcm_l2_addr_t *cf_array, int cf_max,
   6496                              int *cf_count)
   6497 {
   6498     l2x_entry_t     match_entry, entry;
   6499     uint32          fval;
   6500     int             bank, bucket, slot, index;
   6501     int             num_banks;
   6502     int             entries_per_bank, entries_per_row, entries_per_bucket;
   6503     int             bank_base, bucket_offset;
   6504 
   6505 #ifdef BCM_APACHE_SUPPORT
   6506     if (SOC_IS_APACHE(unit)) {
   6507         BCM_IF_ERROR_RETURN
   6508             (soc_apache_hash_bank_count_get(unit, L2Xm, &num_banks));
   6509     } else
   6510 #endif
   6511 #ifdef BCM_HELIX5_SUPPORT
   6512     if (SOC_IS_HELIX5(unit)) {
   6513         BCM_IF_ERROR_RETURN
   6514             (soc_helix5_hash_bank_count_get(unit, L2Xm, &num_banks));
   6515     } else
   6516 #endif /* BCM_HELIX5_SUPPORT */
   6517 #ifdef BCM_TRIDENT3_SUPPORT
   6518     if (SOC_IS_TRIDENT3X(unit)) {
   6519         BCM_IF_ERROR_RETURN
   6520             (soc_trident3_hash_bank_count_get(unit, L2Xm, &num_banks));
   6521     } else
   6522 #endif
   6523 #ifdef BCM_TRIDENT2_SUPPORT
   6524     if (!SOC_IS_TOMAHAWKX(unit) && SOC_IS_TD2_TT2(unit)) {
   6525         BCM_IF_ERROR_RETURN
   6526             (soc_trident2_hash_bank_count_get(unit, L2Xm, &num_banks));
   6527     } else
   6528 #endif
   6529 #ifdef BCM_TOMAHAWK_SUPPORT
   6530     if (SOC_IS_TOMAHAWKX(unit)) {
   6531         BCM_IF_ERROR_RETURN
   6532             (soc_tomahawk_hash_bank_count_get(unit, L2Xm, &num_banks));
   6533     } else
   6534 #endif
   6535     {
   6536         num_banks = 2;
   6537     }
   6538 
   6539     *cf_count = 0;
   6540     BCM_IF_ERROR_RETURN(_bcm_tr_l2_to_l2x(unit, &match_entry, addr, TRUE));
   6541     for (bank = 0; bank < num_banks; bank++) {
   6542 #ifdef BCM_APACHE_SUPPORT
   6543         if (SOC_IS_APACHE(unit)) {
   6544             int phy_bank;
   6545             BCM_IF_ERROR_RETURN
   6546                 (soc_apache_hash_bank_number_get(unit, L2Xm, bank, &phy_bank));
   6547 
   6548             BCM_IF_ERROR_RETURN
   6549                 (soc_apache_hash_bank_info_get(unit, L2Xm, phy_bank,
   6550                                                  &entries_per_bank,
   6551                                                  &entries_per_row,
   6552                                                  &entries_per_bucket,
   6553                                                  &bank_base, &bucket_offset));
   6554             bucket = soc_ap_l2x_bank_entry_hash(unit, phy_bank,
   6555                                                  (uint32 *)&match_entry);
   6556         } else
   6557 #endif
   6558 #ifdef BCM_HELIX5_SUPPORT
   6559         if (SOC_IS_HELIX5(unit)) {
   6560             int phy_bank;
   6561             BCM_IF_ERROR_RETURN
   6562                 (soc_hx5_hash_bank_number_get(unit, L2Xm, bank, &phy_bank));
   6563             BCM_IF_ERROR_RETURN
   6564                 (soc_hx5_hash_bank_info_get(unit, L2Xm, phy_bank,
   6565                                             &entries_per_bank,
   6566                                             &entries_per_row,
   6567                                             &entries_per_bucket,
   6568                                             &bank_base, &bucket_offset));
   6569             bucket = soc_hx5_l2x_bank_entry_hash(unit, phy_bank,
   6570                                                  (uint32 *)&match_entry);
   6571         } else
   6572 #endif
   6573 #ifdef BCM_TRIDENT3_SUPPORT
   6574         if (SOC_IS_TRIDENT3X(unit)) {
   6575             int phy_bank;
   6576             BCM_IF_ERROR_RETURN
   6577                 (soc_td3_hash_bank_number_get(unit, L2Xm, bank, &phy_bank));
   6578             BCM_IF_ERROR_RETURN
   6579                 (soc_td3_hash_bank_info_get(unit, L2Xm, phy_bank,
   6580                                             &entries_per_bank,
   6581                                             &entries_per_row,
   6582                                             &entries_per_bucket,
   6583                                             &bank_base, &bucket_offset));
   6584             bucket = soc_td3_l2x_bank_entry_hash(unit, phy_bank,
   6585                                                  (uint32 *)&match_entry);
   6586         } else
   6587 #endif
   6588 #ifdef BCM_TRIDENT2_SUPPORT
   6589         if (!SOC_IS_TOMAHAWKX(unit) && SOC_IS_TD2_TT2(unit)) {
   6590             int phy_bank;
   6591             BCM_IF_ERROR_RETURN
   6592                 (soc_trident2_hash_bank_number_get(unit, L2Xm, bank, &phy_bank));
   6593             BCM_IF_ERROR_RETURN
   6594                 (soc_trident2_hash_bank_info_get(unit, L2Xm, phy_bank,
   6595                                                  &entries_per_bank,
   6596                                                  &entries_per_row,
   6597                                                  &entries_per_bucket,
   6598                                                  &bank_base, &bucket_offset));
   6599             bucket = soc_td2_l2x_bank_entry_hash(unit, phy_bank,
   6600                                                  (uint32 *)&match_entry);
   6601         } else
   6602 #endif
   6603 #ifdef BCM_TOMAHAWK_SUPPORT
   6604         if (SOC_IS_TOMAHAWKX(unit)) {
   6605             int phy_bank;
   6606             BCM_IF_ERROR_RETURN
   6607                 (soc_tomahawk_hash_bank_number_get(unit, L2Xm, bank, &phy_bank));
   6608             BCM_IF_ERROR_RETURN
   6609                 (soc_tomahawk_hash_bank_info_get(unit, L2Xm, phy_bank,
   6610                                                  &entries_per_bank,
   6611                                                  &entries_per_row,
   6612                                                  &entries_per_bucket,
   6613                                                  &bank_base, &bucket_offset));
   6614             bucket = soc_th_l2x_bank_entry_hash(unit, phy_bank,
   6615                                                  (uint32 *)&match_entry);
   6616         } else
   6617 #endif
   6618         {
   6619             entries_per_bank = soc_mem_index_count(unit, L2Xm) / 2;
   6620             entries_per_row = 8;
   6621             entries_per_bucket = entries_per_row / 2;
   6622             bank_base = 0;
   6623             bucket_offset = bank * entries_per_bucket;
   6624             bucket = soc_tr_l2x_bank_entry_hash(unit, bank,
   6625                                                 (uint32 *)&match_entry);
   6626         }
   6627 
   6628         for (slot = 0; slot < entries_per_bucket; slot++) {
   6629             index = bank_base + bucket * entries_per_row + bucket_offset +
   6630                 slot;
   6631             SOC_IF_ERROR_RETURN
   6632                 (soc_mem_read(unit, L2Xm, MEM_BLOCK_ANY, index, &entry));
   6633             if (soc_feature(unit, soc_feature_base_valid)) {
   6634                 if (!soc_L2Xm_field32_get(unit, &entry, BASE_VALIDf)) {
   6635                     continue;
   6636                 }
   6637             } else {
   6638             if (!soc_L2Xm_field32_get(unit, &entry, VALIDf)) {
   6639                 continue;
   6640             }
   6641             }
   6642 
   6643             fval = soc_mem_field32_get(unit, L2Xm, &entry, KEY_TYPEf);
   6644 #ifdef BCM_TRIDENT2_SUPPORT
   6645             if (SOC_IS_TD2_TT2(unit)) {
   6646                 if (fval != TD2_L2_HASH_KEY_TYPE_BRIDGE &&
   6647                     fval != TD2_L2_HASH_KEY_TYPE_VFI) {
   6648                     continue;
   6649                 }
   6650             } else
   6651 #endif /* BCM_TRIDENT2_SUPPORT */
   6652             if (fval != TR_L2_HASH_KEY_TYPE_BRIDGE &&
   6653                 fval != TR_L2_HASH_KEY_TYPE_VFI) {
   6654                 continue;
   6655             }
   6656 
   6657             /* Retrieve the hit bit for TD2/TT2 */
   6658 #ifdef BCM_TRIDENT2_SUPPORT
   6659             /* Apache is a single pipe device - L2X memory will have hit bit info */
   6660             if (!SOC_IS_TOMAHAWKX(unit) && !SOC_IS_APACHE(unit) &&
   6661                 SOC_IS_TD2_TT2(unit) && !SOC_IS_TRIDENT3X(unit)) {
   6662                 BCM_IF_ERROR_RETURN
   6663                     (_bcm_td2_l2_hit_retrieve(unit, &entry, index));
   6664             }
   6665 #endif /* BCM_TRIDENT2_SUPPORT */   
   6666             BCM_IF_ERROR_RETURN
   6667                 (_bcm_tr_l2_from_l2x(unit, &cf_array[*cf_count], &entry));
   6668 
   6669             *cf_count += 1;
   6670             if (*cf_count >= cf_max) {
   6671                 return BCM_E_NONE;
   6672             }
   6673         }
   6674     }
   6675 
   6676     COMPILER_REFERENCE(entries_per_bank);
   6677 
   6678     return BCM_E_NONE;
   6679 }
   6680 
   6681 int
   6682 bcm_tr_l2_conflict_get(int unit, bcm_l2_addr_t *addr,
   6683                           bcm_l2_addr_t *cf_array, int cf_max,
   6684                           int *cf_count)
   6685 {
   6686     l2x_entry_t         l2ent;
   6687     uint8               key[XGS_HASH_KEY_SIZE];
   6688     int                 hash_sel, bucket, slot, num_bits;
   6689     uint32              hash_control;
   6690 
   6691     if (soc_feature(unit, soc_feature_dual_hash)) {
   6692         return _bcm_tr_dual_l2_conflict_get(unit, addr, cf_array,
   6693                                             cf_max, cf_count);
   6694     }
   6695 
   6696     *cf_count = 0;
   6697 
   6698     BCM_IF_ERROR_RETURN(_bcm_tr_l2_to_l2x(unit, &l2ent, addr, TRUE));
   6699 
   6700     /* Get L2 hash select */
   6701     SOC_IF_ERROR_RETURN(READ_HASH_CONTROLr(unit, &hash_control));
   6702     hash_sel = soc_reg_field_get(unit, HASH_CONTROLr, hash_control,
   6703                                     L2_AND_VLAN_MAC_HASH_SELECTf);
   6704     num_bits = soc_tr_l2x_base_entry_to_key(unit, &l2ent, key);
   6705     bucket = soc_tr_l2x_hash(unit, hash_sel, num_bits, &l2ent, key);
   6706 
   6707     for (slot = 0;
   6708          slot < SOC_L2X_BUCKET_SIZE && *cf_count < cf_max;
   6709          slot++) {
   6710         SOC_IF_ERROR_RETURN
   6711             (soc_mem_read(unit, L2Xm, MEM_BLOCK_ANY,
   6712                           bucket * SOC_L2X_BUCKET_SIZE + slot,
   6713                           &l2ent));
   6714         if (soc_feature(unit, soc_feature_base_valid)) {
   6715             if (!soc_L2Xm_field32_get(unit, &l2ent, BASE_VALIDf)) {
   6716                 continue;
   6717             }
   6718         } else {
   6719         if (!soc_L2Xm_field32_get(unit, &l2ent, VALIDf)) {
   6720             continue;
   6721         }
   6722         }
   6723 
   6724         if ((soc_L2Xm_field32_get(unit, &l2ent, KEY_TYPEf) == 
   6725                                   TR_L2_HASH_KEY_TYPE_BRIDGE) ||
   6726             (soc_L2Xm_field32_get(unit, &l2ent, KEY_TYPEf) ==
   6727                                   TR_L2_HASH_KEY_TYPE_VFI)) {
   6728             BCM_IF_ERROR_RETURN
   6729                 (_bcm_tr_l2_from_l2x(unit, &cf_array[*cf_count], &l2ent));
   6730             *cf_count += 1;
   6731         }
   6732     }
   6733     return BCM_E_NONE;
   6734 }
   6735 
   6736 /*
   6737  * Function:
   6738  *      bcm_vlan_cross_connect_add
   6739  * Purpose:
   6740  *      Add a VLAN cross connect entry
   6741  * Parameters:
   6742  *      unit       - Device unit number
   6743  *      outer_vlan - Outer vlan ID
   6744  *      inner_vlan - Inner vlan ID
   6745  *      port_1     - First port in the cross-connect
   6746  *      port_2     - Second port in the cross-connect
   6747  * Returns:
   6748  *      BCM_E_NONE - Success.
   6749  *      BCM_E_XXX
   6750  */
   6751 int 
   6752 bcm_tr_l2_cross_connect_add(int unit, bcm_vlan_t outer_vlan, 
   6753                             bcm_vlan_t inner_vlan, bcm_gport_t port_1, 
   6754                             bcm_gport_t port_2)
   6755 {
   6756     l2x_entry_t  l2x_entry, l2x_lookup;
   6757     int rv, gport_id, l2_index;
   6758     bcm_port_t port_out;
   6759     bcm_module_t mod_out;
   6760     bcm_trunk_t trunk_id;
   6761     soc_field_t vlan_ivid = IVIDf;
   6762 
   6763     /* Just a safety Check */
   6764     if (!SOC_MEM_IS_VALID(unit,L2Xm)) {
   6765         /* Control should not reach ! */
   6766         return (BCM_E_INTERNAL);
   6767     }
   6768     sal_memset(&l2x_entry, 0, sizeof (l2x_entry));
   6769     if ((outer_vlan < BCM_VLAN_DEFAULT) || (outer_vlan > BCM_VLAN_MAX)) {
   6770         return BCM_E_PARAM;
   6771     } else if (inner_vlan == BCM_VLAN_INVALID) {
   6772         /* Single cross-connect (use only outer_vid) */
   6773         soc_L2Xm_field32_set(unit, &l2x_entry, KEY_TYPEf,
   6774                              TR_L2_HASH_KEY_TYPE_SINGLE_CROSS_CONNECT);
   6775     } else {
   6776         if ((inner_vlan < BCM_VLAN_DEFAULT) || (inner_vlan > BCM_VLAN_MAX)) {
   6777             return BCM_E_PARAM;
   6778         }
   6779         /* Double cross-connect (use both outer_vid and inner_vid) */
   6780         soc_L2Xm_field32_set(unit, &l2x_entry, KEY_TYPEf,
   6781                              TR_L2_HASH_KEY_TYPE_DOUBLE_CROSS_CONNECT);
   6782         if (SOC_IS_TRIDENT3X(unit)) {
   6783             vlan_ivid = VLAN__IVIDf;
   6784         }
   6785 
   6786         soc_L2Xm_field32_set(unit, &l2x_entry, vlan_ivid, inner_vlan);
   6787     }
   6788     soc_L2Xm_field32_set(unit, &l2x_entry, STATIC_BITf, 1);
   6789     if (soc_feature(unit, soc_feature_base_valid)) {
   6790         soc_L2Xm_field32_set(unit, &l2x_entry, BASE_VALIDf, 1);
   6791     } else {
   6792     soc_L2Xm_field32_set(unit, &l2x_entry, VALIDf, 1);
   6793     }
   6794     soc_L2Xm_field32_set(unit, &l2x_entry, VLAN_IDf, outer_vlan);
   6795 
   6796     /* See if the entry already exists */
   6797     rv = soc_mem_generic_lookup(unit, L2Xm, MEM_BLOCK_ANY, 0, &l2x_entry,
   6798                                 &l2x_lookup, &l2_index);
   6799                 
   6800     if ((rv < 0) && (rv != BCM_E_NOT_FOUND)) {
   6801          return rv;
   6802     } 
   6803 
   6804     /* Resolve first port */
   6805     BCM_IF_ERROR_RETURN
   6806         (_bcm_esw_gport_resolve(unit, port_1, &mod_out, &port_out, &trunk_id,
   6807                                 &gport_id));
   6808     if (BCM_GPORT_IS_TRUNK(port_1)) {
   6809         if (soc_feature(unit, soc_feature_generic_dest)) {
   6810             soc_mem_field32_dest_set(unit, L2Xm, &l2x_entry,
   6811                 DESTINATIONf, SOC_MEM_FIF_DEST_LAG,
   6812                 trunk_id);
   6813         } else {
   6814         soc_L2Xm_field32_set(unit, &l2x_entry, Tf, 1);
   6815         soc_L2Xm_field32_set(unit, &l2x_entry, TGIDf, trunk_id);
   6816         }
   6817     } else if (BCM_GPORT_IS_SUBPORT_GROUP(port_1)
   6818                || BCM_GPORT_IS_VLAN_PORT(port_1)) {
   6819         if (soc_feature(unit, soc_feature_generic_dest)) {
   6820             soc_mem_field32_dest_set(unit, L2Xm, &l2x_entry,
   6821                 DESTINATIONf, SOC_MEM_FIF_DEST_DVP,
   6822                 gport_id);
   6823         } else {
   6824         soc_L2Xm_field32_set(unit, &l2x_entry, VPG_TYPEf, 1);
   6825 #if defined(BCM_SCORPION_SUPPORT) && defined(INCLUDE_L3)
   6826         if (SOC_IS_SC_CQ(unit) && BCM_GPORT_IS_SUBPORT_GROUP(port_1)) {
   6827             /* Map the gport_id to index to L3_NEXT_HOP */
   6828             gport_id = (int) _sc_subport_group_index[unit][gport_id/8];
   6829         }
   6830 #endif /* BCM_SCORPION_SUPPORT && INCLUDE_L3 */
   6831         soc_L2Xm_field32_set(unit, &l2x_entry, VPGf, gport_id);
   6832         }
   6833     } else {
   6834         if ((mod_out == -1) ||(port_out == -1)) {
   6835             return BCM_E_PORT;
   6836         }
   6837         if (soc_feature(unit, soc_feature_generic_dest)) {
   6838             soc_mem_field32_dest_set(unit, L2Xm, &l2x_entry,
   6839                 DESTINATIONf, SOC_MEM_FIF_DEST_DGPP,
   6840                 mod_out << SOC_MEM_FIF_DGPP_MOD_ID_SHIFT_BITS | port_out);
   6841         } else {
   6842         soc_L2Xm_field32_set(unit, &l2x_entry, MODULE_IDf, mod_out);
   6843         soc_L2Xm_field32_set(unit, &l2x_entry, PORT_NUMf, port_out);
   6844     }
   6845     }
   6846 
   6847     /* Resolve second port */
   6848     BCM_IF_ERROR_RETURN 
   6849         (_bcm_esw_gport_resolve(unit, port_2, &mod_out, &port_out, &trunk_id,
   6850                                 &gport_id));
   6851     if (BCM_GPORT_IS_TRUNK(port_2)) {
   6852         if (soc_feature(unit, soc_feature_generic_dest)) {
   6853             soc_mem_field32_dest_set(unit, L2Xm, &l2x_entry,
   6854                 VLAN__DESTINATION_1f, SOC_MEM_FIF_DEST_LAG,
   6855                 trunk_id);
   6856         } else {
   6857         soc_L2Xm_field32_set(unit, &l2x_entry, T_1f, 1);
   6858         soc_L2Xm_field32_set(unit, &l2x_entry, TGID_1f, trunk_id);
   6859         }
   6860     } else if (BCM_GPORT_IS_SUBPORT_GROUP(port_2)
   6861                || BCM_GPORT_IS_VLAN_PORT(port_2)) {
   6862         if (soc_feature(unit, soc_feature_generic_dest)) {
   6863             soc_mem_field32_dest_set(unit, L2Xm, &l2x_entry,
   6864                 VLAN__DESTINATION_1f, SOC_MEM_FIF_DEST_DVP,
   6865                 gport_id);
   6866         } else {
   6867         soc_L2Xm_field32_set(unit, &l2x_entry, VPG_TYPE_1f, 1);
   6868 #if defined(BCM_SCORPION_SUPPORT) && defined(INCLUDE_L3)
   6869         if (SOC_IS_SC_CQ(unit) && BCM_GPORT_IS_SUBPORT_GROUP(port_2)) {
   6870             /* Map the gport_id to index to L3_NEXT_HOP */
   6871             gport_id = (int) _sc_subport_group_index[unit][gport_id/8];
   6872         }
   6873 #endif /* BCM_SCORPION_SUPPORT && INCLUDE_L3 */
   6874         soc_L2Xm_field32_set(unit, &l2x_entry, VPG_1f, gport_id);
   6875         }
   6876     } else {
   6877         if ((mod_out == -1) ||(port_out == -1)) {
   6878             return BCM_E_PORT;
   6879         }
   6880         if (soc_feature(unit, soc_feature_generic_dest)) {
   6881             soc_mem_field32_dest_set(unit, L2Xm, &l2x_entry,
   6882                 VLAN__DESTINATION_1f, SOC_MEM_FIF_DEST_DGPP,
   6883                 mod_out << SOC_MEM_FIF_DGPP_MOD_ID_SHIFT_BITS | port_out);
   6884         } else {
   6885         soc_L2Xm_field32_set(unit, &l2x_entry, MODULE_ID_1f, mod_out);
   6886         soc_L2Xm_field32_set(unit, &l2x_entry, PORT_NUM_1f, port_out);
   6887     }
   6888     }
   6889 
   6890     rv = soc_mem_insert_return_old(unit, L2Xm, MEM_BLOCK_ANY, 
   6891                                    (void *)&l2x_entry, (void *)&l2x_entry);
   6892     if (rv == BCM_E_FULL) {
   6893         rv = _bcm_l2_hash_dynamic_replace( unit, &l2x_entry);
   6894     } 
   6895     if (BCM_SUCCESS(rv)) {
   6896         if (soc_feature(unit, soc_feature_ppa_bypass)) {
   6897             SOC_CONTROL(unit)->l2x_ppa_bypass = TRUE;
   6898         }
   6899     }
   6900 
   6901     return rv;
   6902 }
   6903 
   6904 /*
   6905  * Function:
   6906  *      bcm_vlan_cross_connect_delete
   6907  * Purpose:
   6908  *      Delete a VLAN cross connect entry
   6909  * Parameters:
   6910  *      unit       - Device unit number
   6911  *      outer_vlan - Outer vlan ID
   6912  *      inner_vlan - Inner vlan ID
   6913  * Returns:
   6914  *      BCM_E_NONE - Success.
   6915  *      BCM_E_XXX
   6916  */
   6917 int 
   6918 bcm_tr_l2_cross_connect_delete(int unit, bcm_vlan_t outer_vlan, 
   6919                                bcm_vlan_t inner_vlan)
   6920 {
   6921     l2x_entry_t  l2x_entry, l2x_lookup;
   6922     int rv, l2_index;
   6923     soc_field_t vlan_ividf = IVIDf;
   6924 
   6925     sal_memset(&l2x_entry, 0, sizeof (l2x_entry));
   6926     if ((outer_vlan < BCM_VLAN_DEFAULT) || (outer_vlan > BCM_VLAN_MAX)) {
   6927         return BCM_E_PARAM;
   6928     } else if (inner_vlan == BCM_VLAN_INVALID) {
   6929         /* Single cross-connect (use only outer_vid) */
   6930         soc_L2Xm_field32_set(unit, &l2x_entry, KEY_TYPEf,
   6931                              TR_L2_HASH_KEY_TYPE_SINGLE_CROSS_CONNECT);
   6932     } else {
   6933         if ((inner_vlan < BCM_VLAN_DEFAULT) || (inner_vlan > BCM_VLAN_MAX)) {
   6934             return BCM_E_PARAM;
   6935         }
   6936         /* Double cross-connect (use both outer_vid and inner_vid) */
   6937         soc_L2Xm_field32_set(unit, &l2x_entry, KEY_TYPEf,
   6938                              TR_L2_HASH_KEY_TYPE_DOUBLE_CROSS_CONNECT);
   6939         if (SOC_IS_TRIDENT3X(unit)) {
   6940             vlan_ividf = VLAN__IVIDf;
   6941         }
   6942         soc_L2Xm_field32_set(unit, &l2x_entry, vlan_ividf, inner_vlan);
   6943     }
   6944     soc_L2Xm_field32_set(unit, &l2x_entry, STATIC_BITf, 1);
   6945     if (soc_feature(unit, soc_feature_base_valid)) {
   6946         soc_L2Xm_field32_set(unit, &l2x_entry, BASE_VALIDf, 1);
   6947     } else {
   6948     soc_L2Xm_field32_set(unit, &l2x_entry, VALIDf, 1);
   6949     }
   6950     soc_L2Xm_field32_set(unit, &l2x_entry, VLAN_IDf, outer_vlan);
   6951 
   6952     rv = soc_mem_search(unit, L2Xm, MEM_BLOCK_ANY, &l2_index, 
   6953                         (void *)&l2x_entry, (void *)&l2x_lookup, 0);
   6954                  
   6955     if ((rv < 0) && (rv != BCM_E_NOT_FOUND)) {
   6956          return rv;
   6957     } 
   6958 
   6959     rv = soc_mem_delete(unit, L2Xm, MEM_BLOCK_ANY, (void *)&l2x_entry);
   6960     return rv;
   6961 }
   6962 
   6963 /*
   6964  * Function:
   6965  *      bcm_vlan_cross_connect_delete_all
   6966  * Purpose:
   6967  *      Delete all VLAN cross connect entries
   6968  * Parameters:
   6969  *      unit       - Device unit number
   6970  * Returns:
   6971  *      BCM_E_NONE - Success.
   6972  *      BCM_E_XXX
   6973  */
   6974 int
   6975 bcm_tr_l2_cross_connect_delete_all(int unit)
   6976 {
   6977     soc_control_t  *soc = SOC_CONTROL(unit);
   6978     int index_min, index_max, index, mem_max;
   6979     l2x_entry_t *l2x_entry;
   6980     int rv = SOC_E_NONE;
   6981     int *buffer = NULL;
   6982     int mem_size, idx;
   6983     soc_mem_t mem = L2_ENTRY_ONLYm;
   6984     int valid = 0;
   6985     int l2delete_chunks = DEFAULT_L2DELETE_CHUNKS;
   6986 
   6987 #if defined(BCM_TRIDENT3_SUPPORT)
   6988     if (SOC_IS_TRIDENT3X(unit)) {
   6989         l2delete_chunks = soc_property_get(unit, spn_L2DELETE_CHUNKS,
   6990                                            l2delete_chunks);
   6991     }
   6992 #endif
   6993 
   6994 #ifdef BCM_KATANA_SUPPORT
   6995     if (SOC_IS_KATANAX(unit)) {
   6996         mem = L2Xm;
   6997     }
   6998 #endif
   6999 
   7000 #ifdef BCM_HURRICANE2_SUPPORT
   7001     if (SOC_IS_HURRICANE2(unit) || SOC_IS_GREYHOUND(unit) ||
   7002         SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) {
   7003        mem = L2Xm;
   7004     }
   7005 #endif 
   7006     if (SOC_IS_TOMAHAWKX(unit) || SOC_IS_TRIDENT3X(unit)) {
   7007        mem = L2Xm;
   7008     }
   7009 
   7010     index_min = soc_mem_index_min(unit, mem);
   7011     mem_max = soc_mem_index_max(unit, mem);
   7012     mem_size =  l2delete_chunks * sizeof(l2x_entry_t);
   7013     
   7014     buffer = soc_cm_salloc(unit, mem_size, "L2X_delete");
   7015     if (NULL == buffer) {
   7016         return SOC_E_MEMORY;
   7017     }
   7018 
   7019     soc_mem_lock(unit, L2Xm);
   7020     for (idx = index_min; idx < mem_max; idx += l2delete_chunks) {
   7021         index_max = idx + l2delete_chunks - 1;
   7022         if ( index_max > mem_max) {
   7023             index_max = mem_max;
   7024         }
   7025         if ((rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ALL,
   7026                                      idx, index_max, buffer)) < 0 ) {
   7027             soc_cm_sfree(unit, buffer);
   7028             soc_mem_unlock(unit, L2Xm);
   7029             return rv;
   7030         }
   7031         for (index = 0; index < l2delete_chunks; index++) {
   7032             l2x_entry =
   7033                 soc_mem_table_idx_to_pointer(unit, mem,
   7034                                              l2x_entry_t *, buffer, index);
   7035             if (soc_feature(unit, soc_feature_base_valid)) {
   7036                 valid = soc_L2Xm_field32_get(unit, l2x_entry, BASE_VALIDf);
   7037             } else {
   7038                 valid = soc_L2Xm_field32_get(unit, l2x_entry, VALIDf);
   7039             }
   7040             if (valid &&
   7041                 ((soc_L2Xm_field32_get(unit, l2x_entry, KEY_TYPEf) ==
   7042                                       TR_L2_HASH_KEY_TYPE_SINGLE_CROSS_CONNECT) ||
   7043                  (soc_L2Xm_field32_get(unit, l2x_entry, KEY_TYPEf) ==
   7044                                       TR_L2_HASH_KEY_TYPE_DOUBLE_CROSS_CONNECT))) {
   7045                 sal_memcpy(l2x_entry, soc_mem_entry_null(unit, mem),
   7046                            sizeof(l2x_entry_t));
   7047             }
   7048         }
   7049         if ((rv = soc_mem_write_range(unit, mem, MEM_BLOCK_ALL,
   7050                                      idx, index_max, buffer)) < 0) {
   7051             soc_cm_sfree(unit, buffer);
   7052             soc_mem_unlock(unit, L2Xm);
   7053             return rv;
   7054         }
   7055     }
   7056 
   7057     if (soc->arlShadow != NULL) {
   7058         sal_mutex_take(soc->arlShadowMutex, sal_mutex_FOREVER);
   7059         (void) shr_avl_delete_all(soc->arlShadow);
   7060         sal_mutex_give(soc->arlShadowMutex);
   7061     }
   7062     soc_cm_sfree(unit, buffer);
   7063     soc_mem_unlock(unit, L2Xm);
   7064 
   7065     return rv;
   7066 }
   7067 
   7068 /*
   7069  * Function:
   7070  *      bcm_vlan_cross_connect_traverse
   7071  * Purpose:
   7072  *      Walks through the valid cross connect entries and calls
   7073  *      the user supplied callback function for each entry.
   7074  * Parameters:
   7075  *      unit       - (IN) bcm device.
   7076  *      trav_fn    - (IN) Callback function.
   7077  *      user_data  - (IN) User data to be passed to callback function.
   7078  * Returns:
   7079  *      BCM_E_NONE - Success.
   7080  *      BCM_E_XXX
   7081  */
   7082 int
   7083 bcm_tr_l2_cross_connect_traverse(int unit,
   7084                                  bcm_vlan_cross_connect_traverse_cb cb,
   7085                                  void *user_data)
   7086 {
   7087     int index_min, index_max, index, mem_max;
   7088     l2x_entry_t *l2x_entry;
   7089     int rv = SOC_E_NONE;
   7090     int *buffer = NULL;
   7091     int mem_size, idx;
   7092     bcm_gport_t port_1, port_2;
   7093     bcm_vlan_t outer_vlan, inner_vlan;
   7094     bcm_port_t port_in = 0, port_out;
   7095     bcm_module_t mod_in = 0, mod_out;
   7096     soc_mem_t mem = L2Xm;
   7097     soc_field_t vlan_ividf = IVIDf;
   7098     uint32 destv = 0;
   7099     uint32 destt = SOC_MEM_FIF_DEST_INVALID;
   7100     int valid = 0;
   7101     int l2delete_chunks = DEFAULT_L2DELETE_CHUNKS;
   7102 
   7103 #if defined(BCM_TRIDENT3_SUPPORT)
   7104     if (SOC_IS_TRIDENT3X(unit)) {
   7105         l2delete_chunks = soc_property_get(unit, spn_L2DELETE_CHUNKS,
   7106                                            l2delete_chunks);
   7107     }
   7108 #endif
   7109 
   7110 #ifdef BCM_GREYHOUND_SUPPORT
   7111     if (SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANE3(unit) ||
   7112         SOC_IS_GREYHOUND2(unit)){
   7113        mem = L2Xm;
   7114     }
   7115 #endif
   7116     index_min = soc_mem_index_min(unit, mem);
   7117     mem_max = soc_mem_index_max(unit, mem);
   7118     mem_size =  l2delete_chunks * sizeof(l2x_entry_t);
   7119     
   7120     buffer = soc_cm_salloc(unit, mem_size, "cross connect traverse");
   7121     if (NULL == buffer) {
   7122         return SOC_E_MEMORY;
   7123     }
   7124     
   7125     soc_mem_lock(unit, L2Xm);
   7126     for (idx = index_min; idx < mem_max; idx += l2delete_chunks) {
   7127         index_max = idx + l2delete_chunks - 1;
   7128         if ( index_max > mem_max) {
   7129             index_max = mem_max;
   7130         }
   7131         if ((rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ALL,
   7132                                      idx, index_max, buffer)) < 0 ) {
   7133             soc_cm_sfree(unit, buffer);
   7134             soc_mem_unlock(unit, L2Xm);
   7135             return rv;
   7136         }
   7137         for (index = 0; index < l2delete_chunks; index++) {
   7138             l2x_entry = 
   7139                 soc_mem_table_idx_to_pointer(unit, mem,
   7140                                              l2x_entry_t *, buffer, index);
   7141             if (soc_feature(unit, soc_feature_base_valid)) {
   7142                 valid = soc_L2Xm_field32_get(unit, l2x_entry, BASE_VALIDf);
   7143             } else {
   7144                 valid = soc_L2Xm_field32_get(unit, l2x_entry, VALIDf);
   7145             }
   7146             if (valid) {
   7147                 if (soc_L2Xm_field32_get(unit, l2x_entry, KEY_TYPEf) ==
   7148                                      TR_L2_HASH_KEY_TYPE_DOUBLE_CROSS_CONNECT) {
   7149                     /* Double cross-connect entry */
   7150                     if (SOC_IS_TRIDENT3X(unit)) {
   7151                         vlan_ividf = VLAN__IVIDf;
   7152                     }
   7153                     inner_vlan = soc_L2Xm_field32_get(unit, l2x_entry, vlan_ividf);
   7154                 } else if (soc_L2Xm_field32_get(unit, l2x_entry, KEY_TYPEf) ==
   7155                                      TR_L2_HASH_KEY_TYPE_SINGLE_CROSS_CONNECT) {
   7156                     /* Single cross-connect entry */
   7157                     inner_vlan = BCM_VLAN_INVALID;
   7158                 } else {
   7159                     /* Not a cross-connect entry, ignore */
   7160                     continue;
   7161                 }
   7162                 if (SOC_IS_TRIDENT3X(unit)) {
   7163                     outer_vlan = soc_L2Xm_field32_get(unit, l2x_entry, 
   7164                                                       VLAN__OVIDf);
   7165                 } else {
   7166                 outer_vlan = soc_L2Xm_field32_get(unit, l2x_entry, OVIDf);
   7167                 }
   7168                 if (soc_feature(unit, soc_feature_generic_dest)) {
   7169                     destv = soc_mem_field32_dest_get(unit, L2Xm, l2x_entry, 
   7170                                 DESTINATIONf, &destt);
   7171                     if (destt == SOC_MEM_FIF_DEST_DGPP) {
   7172                         port_in = destv & SOC_MEM_FIF_DGPP_PORT_MASK;
   7173                         mod_in = (destv & SOC_MEM_FIF_DGPP_MOD_ID_MASK) >> 
   7174                                  SOC_MEM_FIF_DGPP_MOD_ID_SHIFT_BITS;
   7175                     } else {
   7176                         port_in = 0;
   7177                         mod_in = 0;
   7178                         destv = destv & SOC_MEM_FIF_DGPP_TGID_MASK;
   7179                     }
   7180                 } else if (soc_L2Xm_field32_get(unit, l2x_entry, Tf)) {
   7181                     destt = SOC_MEM_FIF_DEST_LAG;
   7182                     destv = soc_L2Xm_field32_get(unit, l2x_entry, TGIDf);
   7183                 } else {
   7184                     port_in = soc_L2Xm_field32_get(unit, l2x_entry, PORT_NUMf);
   7185                     mod_in = soc_L2Xm_field32_get(unit, l2x_entry, MODULE_IDf);
   7186                 }
   7187 
   7188                 /* Get first port params */
   7189                 if (SOC_MEM_FIELD_VALID(unit, mem, VPG_TYPEf) && 
   7190                     soc_L2Xm_field32_get(unit, l2x_entry, VPG_TYPEf)) {
   7191                     int vpg;
   7192                     vpg = soc_L2Xm_field32_get(unit, l2x_entry, VPGf);
   7193 #if defined(BCM_SCORPION_SUPPORT) && defined(INCLUDE_L3)
   7194                 /* Scorpion uses index to L3_NEXT_HOP as VPG */
   7195                     if (SOC_IS_SC_CQ(unit)) {
   7196                         int grp;
   7197                         _SC_SUBPORT_VPG_FIND(unit, vpg, grp);
   7198                         if ((vpg = grp) == -1) {
   7199                             LOG_ERROR(BSL_LS_BCM_L2,
   7200                                       (BSL_META_U(unit,
   7201                                                   "Can not find entry for VPG\n")));
   7202                         }
   7203                     }             
   7204 #endif  /* BCM_SCORPION_SUPPORT && INCLUDE_L3 */     
   7205                     BCM_GPORT_SUBPORT_GROUP_SET(port_1, vpg);
   7206                 } else if (destt == SOC_MEM_FIF_DEST_DVP) {
   7207                     BCM_GPORT_SUBPORT_GROUP_SET(port_1, destv);
   7208                 } else if (destt == SOC_MEM_FIF_DEST_LAG) {
   7209                     BCM_GPORT_TRUNK_SET(port_1, destv);
   7210                 } else {
   7211                     rv = _bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET,
   7212                                                 mod_in, port_in, &mod_out, &port_out);
   7213                     if (BCM_FAILURE(rv)) {
   7214                         soc_cm_sfree(unit, buffer);
   7215                         soc_mem_unlock(unit, L2Xm);
   7216                         return (rv);
   7217                     }
   7218                     BCM_GPORT_MODPORT_SET(port_1, mod_out, port_out);
   7219                 }
   7220 
   7221                 if (soc_feature(unit, soc_feature_generic_dest)) {
   7222                     destv = soc_mem_field32_dest_get(unit, L2Xm, l2x_entry, 
   7223                                 VLAN__DESTINATION_1f, &destt);
   7224                     if (destt == SOC_MEM_FIF_DEST_DGPP) {
   7225                         port_in = destv & SOC_MEM_FIF_DGPP_PORT_MASK;
   7226                         mod_in = (destv & SOC_MEM_FIF_DGPP_MOD_ID_MASK) >> 
   7227                                  SOC_MEM_FIF_DGPP_MOD_ID_SHIFT_BITS;
   7228                     } else {
   7229                         port_in = 0;
   7230                         mod_in = 0;
   7231                         destv = destv & SOC_MEM_FIF_DGPP_TGID_MASK;
   7232                     }
   7233                 } else if (soc_L2Xm_field32_get(unit, l2x_entry, T_1f)) {
   7234                     destt = SOC_MEM_FIF_DEST_LAG;
   7235                     destv = soc_L2Xm_field32_get(unit, l2x_entry, TGID_1f);
   7236                 } else {
   7237                     port_in = soc_L2Xm_field32_get(unit, l2x_entry, PORT_NUM_1f);
   7238                     mod_in = soc_L2Xm_field32_get(unit, l2x_entry, MODULE_ID_1f);
   7239                 }
   7240 
   7241                 /* Get second port params */
   7242                 if (SOC_MEM_FIELD_VALID(unit, mem, VPG_TYPE_1f) && 
   7243                     soc_L2Xm_field32_get(unit, l2x_entry, VPG_TYPE_1f)) {
   7244                     int vpg;
   7245                     vpg = soc_L2Xm_field32_get(unit, l2x_entry, VPG_1f);
   7246 #if defined(BCM_SCORPION_SUPPORT) && defined(INCLUDE_L3)
   7247                     if (SOC_IS_SC_CQ(unit)) {
   7248                         int grp;
   7249                         _SC_SUBPORT_VPG_FIND(unit, vpg, grp);
   7250                         if ((vpg = grp) == -1) {
   7251                             LOG_ERROR(BSL_LS_BCM_L2,
   7252                                       (BSL_META_U(unit,
   7253                                                   "Can not find entry for VPG\n")));
   7254                         }
   7255                     }             
   7256 #endif  /* BCM_SCORPION_SUPPORT && INCLUDE_L3 */     
   7257                     BCM_GPORT_SUBPORT_GROUP_SET(port_2, vpg);
   7258                 } else if (destt == SOC_MEM_FIF_DEST_DVP) {
   7259                     BCM_GPORT_SUBPORT_GROUP_SET(port_2, destv);
   7260                 } else if (destt == SOC_MEM_FIF_DEST_LAG) {
   7261                     BCM_GPORT_TRUNK_SET(port_2, destv);
   7262                 } else {
   7263                     rv = _bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET,
   7264                                                 mod_in, port_in, &mod_out, &port_out);
   7265                     if (BCM_FAILURE(rv)) {
   7266                         soc_cm_sfree(unit, buffer);
   7267                         soc_mem_unlock(unit, L2Xm);
   7268                         return (rv);
   7269                     }
   7270                     BCM_GPORT_MODPORT_SET(port_2, mod_out, port_out);
   7271                 }
   7272 
   7273                 /* Call application call-back */
   7274                 rv = cb(unit, outer_vlan, inner_vlan, port_1, port_2, user_data);
   7275 #ifdef BCM_CB_ABORT_ON_ERR
   7276                 if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) {
   7277                     soc_cm_sfree(unit, buffer);
   7278                     soc_mem_unlock(unit, L2Xm);
   7279                     return rv;
   7280                 }
   7281 #endif
   7282             }
   7283         }
   7284     }
   7285     soc_cm_sfree(unit, buffer);
   7286     soc_mem_unlock(unit, L2Xm);
   7287 
   7288     return BCM_E_NONE;
   7289 }
   7290 
   7291 
   7292 #if defined(BCM_TRIUMPH_SUPPORT) /* BCM_TRIUMPH_SUPPORT */
   7293 STATIC int
   7294 _l2_port_mask_gport_resolve(int unit, bcm_gport_t gport,
   7295                             bcm_module_t *modid, bcm_port_t *port,
   7296                             bcm_trunk_t *trunk_id, int *id)
   7297 {
   7298     int rv = SOC_E_NONE;
   7299 
   7300     *modid = -1;
   7301     *port = -1;
   7302     *trunk_id = BCM_TRUNK_INVALID;
   7303     *id = -1;
   7304 
   7305     if (SOC_GPORT_IS_TRUNK(gport)) {
   7306         *trunk_id = SOC_GPORT_TRUNK_GET(gport);
   7307     } else if (SOC_GPORT_IS_LOCAL(gport)) {
   7308         BCM_IF_ERROR_RETURN
   7309             (bcm_esw_stk_my_modid_get(unit, modid));
   7310         *port = SOC_GPORT_LOCAL_GET(gport);
   7311     } else if (SOC_GPORT_IS_MODPORT(gport)) {
   7312         *modid = SOC_GPORT_MODPORT_MODID_GET(gport);
   7313         *port = SOC_GPORT_MODPORT_PORT_GET(gport);
   7314     } else if (SOC_GPORT_IS_SUBPORT_PORT(gport)) {
   7315 
   7316 #if defined(BCM_HGPROXY_COE_SUPPORT)
   7317         if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) &&
   7318             _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, gport)) {
   7319             *modid = _BCM_SUBPORT_COE_PORT_ID_MOD_GET(gport);
   7320             *port  = _BCM_SUBPORT_COE_PORT_ID_PORT_GET(gport);
   7321         } else
   7322 #endif
   7323 #if defined(BCM_KATANA2_SUPPORT)
   7324         if (_BCM_KT2_GPORT_IS_LINKPHY_OR_SUBTAG_SUBPORT_GPORT(unit, gport)) {
   7325             BCM_IF_ERROR_RETURN(_bcm_kt2_pp_port_to_modport_get(
   7326                                     unit, gport, modid, port));
   7327         } else
   7328 #endif
   7329         {
   7330             rv =SOC_E_PORT;
   7331         }
   7332     }
   7333 #if defined(BCM_RIOT_SUPPORT) && defined(INCLUDE_L3)
   7334 #ifdef BCM_MPLS_SUPPORT
   7335     else if (SOC_IS_TR_VL(unit) && BCM_GPORT_IS_MPLS_PORT(gport)) {
   7336         *id = BCM_GPORT_MPLS_PORT_ID_GET(gport);
   7337     }
   7338 #endif /* BCM_MPLS_SUPPORT */
   7339 #ifdef BCM_TRIUMPH2_SUPPORT
   7340     else if (BCM_GPORT_IS_MIM_PORT(gport)) {
   7341         *id = BCM_GPORT_MIM_PORT_ID_GET(gport);
   7342     }
   7343 #endif /* BCM_TRIUMPH2_SUPPORT */
   7344 #ifdef BCM_TRIUMPH3_SUPPORT
   7345     else if (BCM_GPORT_IS_L2GRE_PORT(gport)) {
   7346         *id = BCM_GPORT_L2GRE_PORT_ID_GET(gport);
   7347     }
   7348 #endif /* BCM_TRIUMPH3_SUPPORT */
   7349 #ifdef BCM_TRIDENT2_SUPPORT
   7350     else if (BCM_GPORT_IS_VXLAN_PORT(gport)) {
   7351         *id = BCM_GPORT_VXLAN_PORT_ID_GET(gport);
   7352     }
   7353 #endif /* BCM_TRIDENT2_SUPPORT */
   7354 #ifdef BCM_TRIDENT_SUPPORT
   7355     else if (BCM_GPORT_IS_TRILL_PORT(gport)) {
   7356         *id = BCM_GPORT_TRILL_PORT_ID_GET(gport);
   7357     }
   7358 #endif /* BCM_TRIDENT_SUPPORT */
   7359 #endif /* BCM_RIOT_SUPPORT && INCLUDE_L3 */
   7360     else {
   7361         rv = SOC_E_PORT;
   7362     }
   7363     return rv;
   7364 }
   7365 
   7366 /*
   7367  * Function:
   7368  *     _bcm_l2_station_entry_set
   7369  * Purpose:
   7370  *     Set a station entrie's parameters to entry buffer for hardware table
   7371  *     write operation.
   7372  * Parameters:
   7373  *     unit       - (IN) BCM device number
   7374  *     tcam_mem   - (IN) Hardware memory name.
   7375  *     station    - (IN) Station parameters to be set in hardware.
   7376  *     ent_p      - (IN) Software station entry pointer.
   7377  * Returns:
   7378  *     BCM_E_XXX
   7379  */
   7380 STATIC int
   7381 _bcm_l2_station_entry_set(int unit,
   7382                           soc_mem_t tcam_mem,
   7383                           bcm_l2_station_t *station,
   7384                           _bcm_l2_station_entry_t *ent_p)
   7385 {
   7386 
   7387 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_GREYHOUND2_SUPPORT)
   7388     soc_mem_t mysp_mem = MY_STATION_PROFILE_1m;
   7389     int mem_no = 0;
   7390 
   7391 #ifdef BCM_TRIDENT3_SUPPORT
   7392     if (SOC_IS_TRIDENT3X(unit) && (station->flags & BCM_L2_STATION_FCOE)) {
   7393         mysp_mem = MY_STATION_PROFILE_2m;
   7394         mem_no = 1;
   7395     }
   7396 
   7397     if (soc_feature(unit, soc_feature_mysta_profile) && (tcam_mem == MY_STATION_TCAM_2m)) {
   7398         mysp_mem = MY_STATION_PROFILE_2m;
   7399         mem_no = 1;
   7400     }
   7401 #endif /* BCM_TRIDENT3_SUPPORT */
   7402 #endif
   7403 
   7404     soc_mem_field32_set(unit, tcam_mem, ent_p->tcam_ent, VALIDf,
   7405         (1 << soc_mem_field_length(unit, tcam_mem, VALIDf)) - 1);
   7406 
   7407     soc_mem_mac_addr_set(unit, tcam_mem, ent_p->tcam_ent,
   7408                          MAC_ADDRf, station->dst_mac);
   7409 
   7410     soc_mem_mac_addr_set(unit, tcam_mem, ent_p->tcam_ent,
   7411                          MAC_ADDR_MASKf, station->dst_mac_mask);
   7412 
   7413 #ifdef BCM_RIOT_SUPPORT
   7414     if (_BCM_L2_STATION_OVERLAY(station) &&
   7415         _BCM_VPN_VFI_IS_SET(station->vlan)) {
   7416         int vfi = 0, vfi_mask = 0;
   7417 
   7418         if (station->vlan != 0) {
   7419             _BCM_VPN_GET(vfi, _BCM_VPN_TYPE_VFI, station->vlan);
   7420         }
   7421         if (station->vlan_mask != 0) {
   7422             _BCM_VPN_GET(vfi_mask, _BCM_VPN_TYPE_VFI, station->vlan_mask);
   7423         }
   7424 
   7425         soc_mem_field32_set(unit, tcam_mem, ent_p->tcam_ent,
   7426                             VFI_IDf, vfi);
   7427         soc_mem_field32_set(unit, tcam_mem, ent_p->tcam_ent,
   7428                             VFI_ID_MASKf,vfi_mask);
   7429         soc_mem_field32_set(unit, tcam_mem, ent_p->tcam_ent,
   7430                             FORWARDING_FIELD_TYPEf, 1);
   7431         soc_mem_field32_set(unit, tcam_mem, ent_p->tcam_ent,
   7432                             FORWARDING_FIELD_TYPE_MASKf, 1);
   7433     } else
   7434 #endif /* BCM_RIOT_SUPPORT */
   7435     {
   7436         soc_mem_field32_set(unit, tcam_mem, ent_p->tcam_ent,
   7437                             VLAN_IDf, station->vlan);
   7438 
   7439         soc_mem_field32_set(unit, tcam_mem, ent_p->tcam_ent,
   7440                             VLAN_ID_MASKf, station->vlan_mask);
   7441         if (soc_feature(unit, soc_feature_my_station_2)) {
   7442             soc_mem_field32_set(unit, tcam_mem, ent_p->tcam_ent,
   7443                                 FORWARDING_FIELD_TYPEf, 0);
   7444             soc_mem_field32_set(unit, tcam_mem, ent_p->tcam_ent,
   7445                                 FORWARDING_FIELD_TYPE_MASKf, 1);
   7446         }
   7447     }
   7448 
   7449 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_GREYHOUND2_SUPPORT)
   7450     if (SOC_IS_KATANAX(unit)
   7451         || SOC_IS_TRIDENT(unit)
   7452         || SOC_IS_TD2_TT2(unit)
   7453         || SOC_IS_TRIUMPH3(unit)
   7454         || soc_feature(unit, soc_feature_gh2_my_station)) {
   7455         int gport_id = -1;
   7456         bcm_port_t port_out = 0;
   7457         bcm_module_t mod_out = 0;
   7458         bcm_trunk_t trunk_id = BCM_TRUNK_INVALID;
   7459         uint32 mod_port_data = 0; /* concatenated modid and port */
   7460         bcm_port_t port_out_mask;
   7461         bcm_module_t mod_out_mask;
   7462         bcm_trunk_t trunk_id_mask = -1;  
   7463         int gport_id_mask = -1;
   7464         uint32 mod_port_mask = 0; /* concatenated modid and port */
   7465         int rv=0;
   7466 
   7467         /* validate both src_port and src_port_mask has the same type */
   7468         if (GPORT_TYPE(station->src_port) != 
   7469                                    GPORT_TYPE(station->src_port_mask)) {
   7470             return BCM_E_PARAM;
   7471         }
   7472  
   7473         if (BCM_GPORT_IS_SET(station->src_port)) {
   7474             rv = _bcm_esw_gport_resolve(unit, station->src_port, 
   7475                           &mod_out, 
   7476                           &port_out, &trunk_id,
   7477                           &gport_id);
   7478             BCM_IF_ERROR_RETURN(rv);
   7479 
   7480             if (BCM_GPORT_IS_TRUNK(station->src_port)) {
   7481                 if (BCM_TRUNK_INVALID == trunk_id) {
   7482                     return BCM_E_PORT;
   7483                 }
   7484 
   7485             } else {
   7486                 if ((-1 == mod_out) || (-1 == port_out)) {
   7487                     return BCM_E_PORT;
   7488                 }
   7489 #ifdef BCM_RIOT_SUPPORT
   7490                 if (!_BCM_L2_STATION_OVERLAY(station)) {
   7491                     if (-1 != gport_id) {
   7492                         return BCM_E_PORT;
   7493                     }
   7494                 }
   7495 #endif /* BCM_RIOT_SUPPORT */
   7496             }
   7497 
   7498             /* retrieve the port mask */
   7499             rv = _l2_port_mask_gport_resolve(unit,station->src_port_mask,
   7500                                              &mod_out_mask, &port_out_mask,
   7501                                              &trunk_id_mask, &gport_id_mask);
   7502             BCM_IF_ERROR_RETURN(rv);
   7503         } else {
   7504             port_out = station->src_port;
   7505             port_out_mask = station->src_port_mask;
   7506             mod_out = 0;
   7507             mod_out_mask = 0;
   7508         }
   7509 
   7510         if (trunk_id != BCM_TRUNK_INVALID) {
   7511             /* require hardware with valid SOURCE_FIELDf */
   7512             if (!SOC_MEM_FIELD_VALID(unit, tcam_mem, SOURCE_FIELDf)) {
   7513                 return BCM_E_PORT;
   7514             }
   7515             if (SOC_IS_KATANAX(unit)) {
   7516                 SOC_IF_ERROR_RETURN(soc_mem_field32_fit(unit, tcam_mem, 
   7517                             SOURCE_FIELD_MASKf, 
   7518                             1 << (SOC_TRUNK_BIT_POS(unit) - 1 )));
   7519                 mod_port_data = trunk_id;
   7520                 mod_port_mask = trunk_id_mask & 
   7521                     ((1 << SOC_TRUNK_BIT_POS(unit)) - 1);
   7522                 if (SOC_MEM_FIELD_VALID(unit, tcam_mem, SOURCE_TYPEf)) {
   7523                     /* If src_port_mask has been reset by caller it means that
   7524                      * the caller does not care about matching against
   7525                      * SOURCE_FIELD at all, in such case it does not really
   7526                      * mater whether the packet is coming from a real port or
   7527                      * a trunk, so it is best to keep the SOURCE_TYPE_MASK
   7528                      * reset also */
   7529                     soc_mem_field32_set(unit, tcam_mem, ent_p->tcam_ent,
   7530                             SOURCE_TYPEf, 1);
   7531                     if (station->src_port_mask) {
   7532                         soc_mem_field32_set(unit, tcam_mem, ent_p->tcam_ent,
   7533                                 SOURCE_TYPE_MASKf, 1);
   7534                     } else {
   7535                         soc_mem_field32_set(unit, tcam_mem, ent_p->tcam_ent,
   7536                                 SOURCE_TYPE_MASKf, 0);
   7537                     }
   7538                 }
   7539             } else if (soc_feature(unit, soc_feature_gh2_my_station)) {
   7540                 soc_mem_field32_set(unit, tcam_mem, ent_p->tcam_ent,
   7541                             SOURCE_TYPEf, 1);
   7542                 soc_mem_field32_set(unit, tcam_mem, ent_p->tcam_ent,
   7543                             SOURCE_TYPE_MASKf, 1);
   7544                 mod_port_data = trunk_id;
   7545                 mod_port_mask = trunk_id_mask; 
   7546             } else {
   7547                 /* and the SOURCE_FIELDf supports the trunk operation */
   7548                 SOC_IF_ERROR_RETURN(soc_mem_field32_fit(unit, tcam_mem, 
   7549                             SOURCE_FIELD_MASKf, 
   7550                             1 << SOC_TRUNK_BIT_POS(unit)));
   7551 
   7552                 mod_port_data = ((1 << SOC_TRUNK_BIT_POS(unit)) | trunk_id);
   7553                 mod_port_mask = trunk_id_mask & 
   7554                     ((1 << SOC_TRUNK_BIT_POS(unit)) - 1);
   7555                 mod_port_mask |= (1 << SOC_TRUNK_BIT_POS(unit));
   7556             }
   7557             soc_mem_field32_set(unit, tcam_mem, ent_p->tcam_ent,
   7558                        SOURCE_FIELDf, mod_port_data);
   7559             soc_mem_field32_set(unit, tcam_mem, ent_p->tcam_ent,
   7560                        SOURCE_FIELD_MASKf, mod_port_mask);
   7561 #ifdef BCM_RIOT_SUPPORT
   7562         } else if((gport_id != BCM_GPORT_INVALID) &&
   7563                   (_BCM_L2_STATION_OVERLAY(station))) {
   7564 
   7565             soc_mem_field32_set(unit, tcam_mem, ent_p->tcam_ent,
   7566                                 SOURCE_TYPEf, 1);
   7567             soc_mem_field32_set(unit, tcam_mem, ent_p->tcam_ent,
   7568                                 SOURCE_TYPE_MASKf, 1);
   7569             mod_port_data = gport_id;
   7570             mod_port_mask = gport_id_mask;
   7571             soc_mem_field32_set(unit, tcam_mem, ent_p->tcam_ent,
   7572                                 SOURCE_FIELDf, mod_port_data);
   7573             soc_mem_field32_set(unit, tcam_mem, ent_p->tcam_ent,
   7574                                 SOURCE_FIELD_MASKf, mod_port_mask);
   7575 #endif /* BCM_RIOT_SUPPORT */
   7576         } else {
   7577             if (SOC_MEM_FIELD_VALID(unit, tcam_mem, SOURCE_FIELDf)) {
   7578                 int num_bits_for_port;
   7579                 num_bits_for_port = _shr_popcount(
   7580                                  (unsigned int)SOC_PORT_ADDR_MAX(unit));
   7581 
   7582                 mod_port_data = (mod_out << num_bits_for_port) | port_out;
   7583                 mod_port_mask = mod_out_mask & SOC_MODID_MAX(unit);
   7584                 mod_port_mask <<= num_bits_for_port;
   7585                 mod_port_mask |= (port_out_mask & SOC_PORT_ADDR_MAX(unit));
   7586 
   7587                 if (soc_feature(unit, soc_feature_gh2_my_station)) {
   7588                     soc_mem_field32_set(unit, tcam_mem, ent_p->tcam_ent,
   7589                             SOURCE_TYPEf, 0);
   7590                     soc_mem_field32_set(unit, tcam_mem, ent_p->tcam_ent,
   7591                             SOURCE_TYPE_MASKf, 1);
   7592                 } else {
   7593                 if (!SOC_IS_KATANAX(unit)) {
   7594                     /* Clear the trunk ID bit. */
   7595                     mod_port_data &= ~(1 << SOC_TRUNK_BIT_POS(unit));
   7596 
   7597                     /* Must match on the T bit (which should be 0) for the devices
   7598                      * supporting the trunk operation with this field
   7599                      */
   7600                     if (BCM_GPORT_IS_SET(station->src_port)) {
   7601                         if (soc_mem_field32_fit(unit, tcam_mem, 
   7602                                     SOURCE_FIELD_MASKf, 
   7603                                     1 << SOC_TRUNK_BIT_POS(unit)) == SOC_E_NONE) {
   7604                             mod_port_mask |= (1 << SOC_TRUNK_BIT_POS(unit));
   7605                         }
   7606                     }
   7607                 }
   7608                 if (SOC_IS_KATANAX(unit)) {
   7609                     if (SOC_MEM_FIELD_VALID(unit, tcam_mem, SOURCE_TYPEf)) {
   7610                         /* If src_port_mask has been reset by caller it means
   7611                          * that the caller does not care about matching against
   7612                          * SOURCE_FIELD at all, in such case it does not really
   7613                          * mater whether the packet is coming from a real port
   7614                          * or a trunk, so it is best to keep the
   7615                          * SOURCE_TYPE_MASK * reset also */
   7616                         soc_mem_field32_set(unit, tcam_mem, ent_p->tcam_ent,
   7617                                 SOURCE_TYPEf, 0);
   7618                         if (station->src_port_mask) {
   7619                             soc_mem_field32_set(unit, tcam_mem, ent_p->tcam_ent,
   7620                                     SOURCE_TYPE_MASKf, 1);
   7621                         } else {
   7622                             soc_mem_field32_set(unit, tcam_mem, ent_p->tcam_ent,
   7623                                     SOURCE_TYPE_MASKf, 0);
   7624                         }
   7625                     }
   7626                 }
   7627                 }
   7628                 soc_mem_field32_set(unit, tcam_mem, ent_p->tcam_ent,
   7629                                     SOURCE_FIELDf, mod_port_data);
   7630 
   7631                 soc_mem_field32_set(unit, tcam_mem, ent_p->tcam_ent,
   7632                                     SOURCE_FIELD_MASKf, mod_port_mask);
   7633             } else {
   7634                 soc_mem_field32_set(unit, tcam_mem, ent_p->tcam_ent,
   7635                                     ING_PORT_NUMf, port_out);
   7636 
   7637                 soc_mem_field32_set(unit, tcam_mem, ent_p->tcam_ent,
   7638                             ING_PORT_NUM_MASKf, 
   7639                             port_out_mask & SOC_PORT_ADDR_MAX(unit));
   7640             }
   7641         } 
   7642 
   7643         if (soc_feature(unit, soc_feature_mysta_profile)) {
   7644             uint32 mysta_profile_id;
   7645             my_station_profile_1_entry_t entry;
   7646             sal_memset(&entry, 0, sizeof(entry));
   7647             _bcm_l2_mysta_station_to_entry(unit, station, mysp_mem, &entry);
   7648             rv = _bcm_l2_mysta_profile_entry_add(unit, &entry, mem_no,
   7649                                                  &mysta_profile_id);
   7650             BCM_IF_ERROR_RETURN(rv);
   7651 #ifdef BCM_TRIDENT3_SUPPORT
   7652             if (!soc_feature(unit, soc_feature_riot)) {
   7653                 if (mem_no == 0) {
   7654                     mem_no = 1;
   7655                     rv = _bcm_l2_mysta_profile_entry_add(unit, &entry, mem_no,
   7656                                                      &mysta_profile_id);
   7657                     BCM_IF_ERROR_RETURN(rv);
   7658                 }
   7659             }
   7660 #endif
   7661             soc_mem_field32_dest_set(unit, tcam_mem, ent_p->tcam_ent,
   7662                 DESTINATIONf, SOC_MEM_FIF_DEST_MYSTA, mysta_profile_id);
   7663         } else {
   7664 
   7665         if (!soc_feature(unit, soc_feature_gh2_my_station)) {
   7666         soc_mem_field32_set(unit, tcam_mem, ent_p->tcam_ent,
   7667                             MIM_TERMINATION_ALLOWEDf,
   7668                             ((station->flags & BCM_L2_STATION_MIM) ? 1 : 0));
   7669 
   7670         soc_mem_field32_set(unit, tcam_mem, ent_p->tcam_ent,
   7671                             MPLS_TERMINATION_ALLOWEDf,
   7672                             ((station->flags & BCM_L2_STATION_MPLS) ? 1 : 0));
   7673         }
   7674         
   7675         soc_mem_field32_set(unit, tcam_mem, ent_p->tcam_ent,
   7676                             IPV4_TERMINATION_ALLOWEDf,
   7677                             ((station->flags & BCM_L2_STATION_IPV4) ? 1 : 0));
   7678 
   7679         soc_mem_field32_set(unit, tcam_mem, ent_p->tcam_ent,
   7680                             IPV6_TERMINATION_ALLOWEDf,
   7681                             ((station->flags & BCM_L2_STATION_IPV6) ? 1 : 0));
   7682         
   7683         soc_mem_field32_set(unit, tcam_mem, ent_p->tcam_ent,
   7684                             ARP_RARP_TERMINATION_ALLOWEDf,
   7685                             ((station->flags & BCM_L2_STATION_ARP_RARP) ? 1 : 0));
   7686         }
   7687         soc_mem_field32_set(unit, tcam_mem, ent_p->tcam_ent,
   7688                             COPY_TO_CPUf,
   7689                             ((station->flags & BCM_L2_STATION_COPY_TO_CPU)
   7690                             ? 1 : 0));
   7691     }
   7692 #endif
   7693 
   7694 #if defined(BCM_TRIDENT_SUPPORT)
   7695     if (SOC_IS_TRIDENT(unit) || SOC_IS_TD2_TT2(unit)) {
   7696         if (!soc_feature(unit, soc_feature_mysta_profile)) {
   7697         soc_mem_field32_set(unit, tcam_mem, ent_p->tcam_ent,
   7698                             TRILL_TERMINATION_ALLOWEDf,
   7699                             ((station->flags & BCM_L2_STATION_TRILL) ? 1 : 0));
   7700 
   7701         soc_mem_field32_set(unit, tcam_mem, ent_p->tcam_ent,
   7702                             FCOE_TERMINATION_ALLOWEDf,
   7703                             ((station->flags & BCM_L2_STATION_FCOE) ? 1 : 0));
   7704     }
   7705     }
   7706 #endif
   7707 
   7708 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || \
   7709     defined(BCM_GREYHOUND2_SUPPORT) || defined(BCM_HELIX5_SUPPORT)
   7710     if ((SOC_IS_KATANAX(unit) || SOC_IS_TRIUMPH3(unit) ||
   7711         soc_feature(unit, soc_feature_gh2_my_station)) ||
   7712         soc_feature(unit, soc_feature_hx5_oam_support)) {
   7713 
   7714         if (soc_mem_field_valid(unit, tcam_mem, OAM_TERMINATION_ALLOWEDf)) { 
   7715             soc_mem_field32_set(unit, tcam_mem, ent_p->tcam_ent,
   7716                                 OAM_TERMINATION_ALLOWEDf,
   7717                                 ((station->flags & BCM_L2_STATION_OAM) ? 1 :0));
   7718         }
   7719     }
   7720 #endif
   7721 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || \
   7722     defined(BCM_TRIDENT_SUPPORT) || defined(BCM_GREYHOUND2_SUPPORT)
   7723 
   7724     if (SOC_IS_KATANAX(unit) || SOC_IS_TRIDENT(unit) ||
   7725         SOC_IS_TD2_TT2(unit) || SOC_IS_TRIUMPH3(unit) ||
   7726         soc_feature(unit, soc_feature_gh2_my_station)) {
   7727         
   7728         if (soc_mem_field_valid(unit, tcam_mem, DISCARDf)) { 
   7729             soc_mem_field32_set(unit, tcam_mem, ent_p->tcam_ent,
   7730                                 DISCARDf,
   7731                                 ((station->flags & BCM_L2_STATION_DISCARD) ? 1 : 0));
   7732         }
   7733     }
   7734 #endif
   7735 #if defined(BCM_TSN_SUPPORT)
   7736     if (soc_feature(unit, soc_feature_tsn_taf)) {
   7737         if (soc_mem_field_valid(unit, tcam_mem, TAF_GATE_ID_PROFILEf)) {
   7738             if (BCM_TSN_PRI_MAP_INVALID != station->taf_gate_primap) {
   7739                 uint32 hw_index;
   7740                 bcm_tsn_pri_map_type_t map;
   7741 
   7742                 BCM_IF_ERROR_RETURN(
   7743                     bcmi_esw_tsn_pri_map_hw_index_get(
   7744                         unit, station->taf_gate_primap, &map, &hw_index));
   7745 
   7746                 if (map != bcmTsnPriMapTypeTafGate) {
   7747                     return BCM_E_PARAM;
   7748                 }
   7749                 soc_mem_field32_set(
   7750                     unit, tcam_mem, ent_p->tcam_ent,
   7751                     TAF_GATE_ID_PROFILEf, hw_index);
   7752             } else {
   7753                 soc_mem_field32_set(
   7754                     unit, tcam_mem, ent_p->tcam_ent,
   7755                     TAF_GATE_ID_PROFILEf, 0);
   7756             }
   7757         }
   7758     }
   7759 #endif /* BCM_TSN_SUPPORT */
   7760     return BCM_E_NONE;
   7761 }
   7762 
   7763 #if defined(BCM_KATANA2_SUPPORT)
   7764 
   7765 /* Obsolete now, check _bcm_kt2_port_mac_set() */
   7766 STATIC int
   7767 _bcm_kt2_l2_port_mac_set(int unit, int index, bcm_mac_t port_mac) 
   7768 {
   7769     port_tab_entry_t          ptab;        
   7770     egr_port_entry_t          egr_port_entry;
   7771     /* Set MAC address in Port table */
   7772     SOC_IF_ERROR_RETURN(
   7773                 READ_PORT_TABm(unit, MEM_BLOCK_ANY, index, &ptab));
   7774 
   7775     soc_mem_mac_addr_set(unit, PORT_TABm, &ptab, MAC_ADDRESSf, port_mac);
   7776 
   7777     SOC_IF_ERROR_RETURN( WRITE_PORT_TABm(unit,MEM_BLOCK_ALL, index, &ptab));
   7778 
   7779     SOC_IF_ERROR_RETURN(READ_EGR_PORTm(unit, MEM_BLOCK_ANY, index,
   7780                                            &egr_port_entry));
   7781 
   7782     soc_mem_mac_addr_set(unit, EGR_PORTm, &egr_port_entry, 
   7783                                    MAC_ADDRESSf, port_mac);
   7784     SOC_IF_ERROR_RETURN(
   7785             WRITE_EGR_PORTm(unit, MEM_BLOCK_ALL, index, &egr_port_entry));
   7786 
   7787     return BCM_E_NONE; 
   7788 }
   7789 #endif
   7790 
   7791 #if defined(BCM_KATANA2_SUPPORT) || defined(BCM_TRIDENT2PLUS_SUPPORT)
   7792 /* Obsolete */
   7793 STATIC int
   7794 _bcm_check_olp_dglp(int unit, int dglp, bcm_mac_t *mac)
   7795 {
   7796     _bcm_l2_station_control_t *sc;           /* Station control structure. */
   7797     egr_olp_dgpp_config_entry_t eolp_dgpp_cfg;
   7798     int        index = 0;
   7799     int        max_entries = 0;
   7800     soc_field_t field;
   7801 
   7802     BCM_IF_ERROR_RETURN(_bcm_l2_station_control_get(unit, &sc));
   7803 
   7804     max_entries = soc_mem_index_count(unit, EGR_OLP_DGPP_CONFIGm);
   7805 
   7806     for (; index < max_entries; index++) {
   7807         SOC_IF_ERROR_RETURN(
   7808               READ_EGR_OLP_DGPP_CONFIGm(unit, MEM_BLOCK_ANY, 
   7809                                            index, &eolp_dgpp_cfg));
   7810         if (SOC_MEM_FIELD_VALID(unit, EGR_OLP_DGPP_CONFIGm, VALIDf)) {
   7811             field = soc_mem_field32_get(unit, EGR_OLP_DGPP_CONFIGm, 
   7812                     &eolp_dgpp_cfg, VALIDf);
   7813             if(!field) {
   7814                 continue;
   7815             }
   7816         }
   7817         field = soc_mem_field32_get(unit, EGR_OLP_DGPP_CONFIGm, 
   7818                                   &eolp_dgpp_cfg, DGLPf);
   7819         if (field == dglp) {
   7820             soc_mem_mac_addr_get(unit, EGR_OLP_DGPP_CONFIGm, &eolp_dgpp_cfg, 
   7821                                                     MACDAf, *mac);
   7822             if (dglp == 0) {
   7823                 /* CPU port
   7824                    Check if its a zero mac. If yes, dont return BCM_E_EXISTS*/
   7825                     if (!BCM_MAC_IS_ZERO(*mac)) {
   7826                         return BCM_E_EXISTS;
   7827                     }
   7828             } else {
   7829                 return BCM_E_EXISTS;
   7830             }
   7831         }
   7832     } /* end of for */
   7833     return BCM_E_NOT_FOUND;
   7834 }
   7835 
   7836 /* Soon to become Obsolete, check bcm_switch_olp_l2_addr_xxx */
   7837 int
   7838 _bcm_l2_olp_mac_set(int unit, int index, bcm_port_t port, bcm_mac_t olp_mac, int action)
   7839 {
   7840     egr_olp_dgpp_config_entry_t eolp_dgpp_cfg;
   7841     ing_en_efilter_bitmap_entry_t efilter_entry;
   7842     bcm_module_t module_id = 0;
   7843     bcm_module_t my_modid;
   7844     bcm_port_t port_id;
   7845     bcm_trunk_t trunk_id = BCM_TRUNK_INVALID;
   7846     int         local_id;
   7847     int         dglp = 0;
   7848     uint32      olp_enable = 1;
   7849     pbmp_t      pbmp;
   7850     bcm_l2_addr_t l2addr;
   7851     bcm_vlan_t  vlan;
   7852     uint32      rval;
   7853     bcm_mac_t   zero_mac = { 0, 0, 0, 0, 0, 0};
   7854     bcm_mac_t   old_mac = { 0, 0, 0, 0, 0, 0};
   7855     _bcm_l2_station_control_t *sc;           /* Station control structure. */
   7856 
   7857     BCM_IF_ERROR_RETURN(_bcm_l2_station_control_get(unit, &sc));
   7858     BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_modid));
   7859 
   7860     /* Add/delete static MAC entry with OLP MAC and EGR_OLP_VLAN */
   7861     SOC_IF_ERROR_RETURN(READ_EGR_OLP_VLANr(unit, &rval));
   7862     vlan = soc_reg_field_get(unit, EGR_OLP_VLANr, rval, VLAN_TAGf);
   7863 
   7864     if ((vlan == 0) && (action != OLP_ACTION_DELETE)) {
   7865         LOG_ERROR(BSL_LS_BCM_L2,
   7866                   (BSL_META_U(unit,
   7867                               "_bcm_l2_olp_mac_set: OLP vlan tag is not configured. \
   7868                               So can't add static MAC entry for OLP mac\n")));
   7869         return BCM_E_PARAM;
   7870     }
   7871 
   7872     /* Set MAC address and DGLP in EGR_OLP_DGLP_CONFIG */
   7873     SOC_IF_ERROR_RETURN(
   7874               READ_EGR_OLP_DGPP_CONFIGm(unit, MEM_BLOCK_ANY, 
   7875                                            index, &eolp_dgpp_cfg));
   7876     if (port == 0) {
   7877         port = soc_mem_field32_get(unit, EGR_OLP_DGPP_CONFIGm, 
   7878                                   &eolp_dgpp_cfg, DGLPf);
   7879         module_id = (port & DGLP_MODULE_ID_MASK) >> DGLP_MODULE_ID_SHIFT_BITS;
   7880         port_id = port & DGLP_PORT_NO_MASK;
   7881         dglp = 0;
   7882         olp_enable = 0;
   7883         soc_mem_mac_addr_get(unit, EGR_OLP_DGPP_CONFIGm, &eolp_dgpp_cfg, 
   7884                                                     MACDAf, olp_mac);
   7885     } else {
   7886         if (BCM_GPORT_IS_SET(port)) {
   7887             SOC_IF_ERROR_RETURN(_bcm_esw_gport_resolve(unit, port, &module_id, 
   7888                                                &port_id, &trunk_id, &local_id));
   7889             if (BCM_GPORT_IS_TRUNK(port) && (trunk_id != BCM_TRUNK_INVALID)) {
   7890                 /* Set LAG ID indicator bit */
   7891                 dglp |= (1 << DGLP_LAG_ID_INDICATOR_SHIFT_BITS);  
   7892                 dglp |= trunk_id;
   7893 #if defined(BCM_KATANA2_SUPPORT) 
   7894             } else if (SOC_IS_KATANA2(unit) && 
   7895                       (BCM_GPORT_IS_SUBPORT_PORT(port)) &&
   7896                   ((_BCM_KT2_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port)) ||
   7897                   (_BCM_KT2_GPORT_IS_LINKPHY_SUBPORT_PORT(unit, port)))) {
   7898                 LOG_ERROR(BSL_LS_BCM_L2,
   7899                           (BSL_META_U(unit,
   7900                                       "_bcm_l2_olp_mac_set: OLP is not allowed on SUBPORT. \
   7901                                       \n")));
   7902                 return BCM_E_PARAM;
   7903 #endif                
   7904             } else {
   7905                 dglp |= ((module_id << DGLP_MODULE_ID_SHIFT_BITS) + port_id); 
   7906             }
   7907         } else {
   7908             port_id = port;
   7909             dglp |= ((my_modid << DGLP_MODULE_ID_SHIFT_BITS) + port); 
   7910         }
   7911         if (!SOC_IS_SABER2(unit) && 
   7912                 !soc_feature(unit, soc_feature_fp_based_oam)) {
   7913             if (IS_CPU_PORT(unit, port_id)) {
   7914                 LOG_ERROR(BSL_LS_BCM_L2,
   7915                         (BSL_META_U(unit,
   7916                                     "_bcm_l2_olp_mac_set: OLP is not allowed on CPU port. \n")));
   7917                 return BCM_E_PARAM;
   7918             }
   7919         }
   7920     }
   7921     /* check if an entry already exists for this dglp */
   7922     if (BCM_E_EXISTS == _bcm_check_olp_dglp(unit, dglp, &old_mac)) {
   7923         if (action == OLP_ACTION_UPDATE) {
   7924             /* delete the static l2 entry added */
   7925             BCM_IF_ERROR_RETURN(bcm_esw_l2_addr_delete(unit, old_mac, vlan)); 
   7926         } else if (action == OLP_ACTION_ADD) {
   7927             LOG_ERROR(BSL_LS_BCM_L2,
   7928                       (BSL_META_U(unit,
   7929                                   "_bcm_l2_olp_mac_set: OLP MAC is already configured. \
   7930                                   for this DGLP\n")));
   7931             return BCM_E_PARAM;
   7932         } 
   7933     }
   7934 
   7935     soc_mem_mac_addr_set(unit, EGR_OLP_DGPP_CONFIGm, &eolp_dgpp_cfg, 
   7936                          MACDAf, (olp_enable ? olp_mac : zero_mac));
   7937 
   7938     soc_mem_field32_set(unit, EGR_OLP_DGPP_CONFIGm, &eolp_dgpp_cfg, DGLPf, dglp);
   7939     if (SOC_MEM_FIELD_VALID(unit, EGR_OLP_DGPP_CONFIGm, VALIDf)) {
   7940         soc_mem_field32_set(unit, EGR_OLP_DGPP_CONFIGm, &eolp_dgpp_cfg, 
   7941                             VALIDf, olp_enable);
   7942     }
   7943     SOC_IF_ERROR_RETURN(WRITE_EGR_OLP_DGPP_CONFIGm(unit, MEM_BLOCK_ALL, 
   7944                                                    index, &eolp_dgpp_cfg));
   7945     if ((module_id == 0) || (module_id == my_modid)) {
   7946         /* Local port - Enable OLP on this port */
   7947 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   7948         if(SOC_IS_TRIDENT2PLUS(unit)) {    
   7949             iarb_ing_port_table_entry_t entry;
   7950             port_tab_entry_t            port_entry;
   7951             uint64                      mac;
   7952             int                         prefix_check = 0;
   7953 
   7954             SOC_IF_ERROR_RETURN(soc_mem_read(unit, IARB_ING_PORT_TABLEm, 
   7955                         MEM_BLOCK_ANY, port_id, &entry));
   7956             soc_IARB_ING_PORT_TABLEm_field32_set(unit, &entry, 
   7957                     OLP_ENABLEf, olp_enable);
   7958             SOC_IF_ERROR_RETURN(soc_mem_write(unit, IARB_ING_PORT_TABLEm, 
   7959                         MEM_BLOCK_ALL, port_id, &entry));
   7960 
   7961             /* Enable/Disable the prefix checking on the OLP port
   7962              * If OLP is being enabled  - Disable prefix checking
   7963              * If OLP is being disabled - Enable prefix checking if it
   7964              *                            is configured.
   7965              */
   7966             prefix_check = 0;
   7967             if (0 == olp_enable) {
   7968                 SOC_IF_ERROR_RETURN(READ_ING_OLP_CONFIG_0_64r(unit, &mac));
   7969                 if (!COMPILER_64_IS_ZERO(mac)) {
   7970                     prefix_check = 1;
   7971                 }
   7972             }
   7973             SOC_IF_ERROR_RETURN(READ_PORT_TABm(unit,
   7974                                                MEM_BLOCK_ANY,
   7975                                                port_id,
   7976                                                &port_entry));
   7977             soc_PORT_TABm_field32_set(unit,
   7978                                       &port_entry,
   7979                                       OLP_MAC_DA_PREFIX_CHECK_ENABLEf,
   7980                                       prefix_check);
   7981 
   7982             SOC_IF_ERROR_RETURN(WRITE_PORT_TABm(unit,
   7983                                                 MEM_BLOCK_ALL,
   7984                                                 port_id,
   7985                                                 &port_entry));
   7986         } else 
   7987 #endif
   7988         {
   7989             iarb_ing_physical_port_entry_t  entry;
   7990             ing_physical_port_table_entry_t port_entry;
   7991             uint64                          mac;
   7992             int                             prefix_check = 0;
   7993 
   7994             SOC_IF_ERROR_RETURN(soc_mem_read(unit, IARB_ING_PHYSICAL_PORTm, 
   7995                         MEM_BLOCK_ANY, port_id, &entry));
   7996             soc_IARB_ING_PHYSICAL_PORTm_field32_set(unit, &entry, 
   7997                     OLP_ENABLEf, olp_enable);
   7998             SOC_IF_ERROR_RETURN(soc_mem_write(unit, IARB_ING_PHYSICAL_PORTm, 
   7999                         MEM_BLOCK_ALL, port_id, &entry));
   8000 
   8001             /* Enable/Disable the prefix checking on the OLP port
   8002              * If OLP is being enabled  - Disable prefix checking
   8003              * If OLP is being disabled - Enable prefix checking if it
   8004              *                            is configured.
   8005              */
   8006             prefix_check = 0;
   8007             if (0 == olp_enable) {
   8008                 SOC_IF_ERROR_RETURN(READ_ING_OLP_CONFIG_0_64r(unit, &mac));
   8009                 if (!COMPILER_64_IS_ZERO(mac)) {
   8010                     prefix_check = 1;
   8011                 }
   8012             }
   8013             SOC_IF_ERROR_RETURN(
   8014                                 READ_ING_PHYSICAL_PORT_TABLEm(unit,
   8015                                                               MEM_BLOCK_ANY,
   8016                                                               port_id,
   8017                                                               &port_entry));
   8018 
   8019             soc_ING_PHYSICAL_PORT_TABLEm_field32_set(unit,
   8020                                                      &port_entry,
   8021                                                      OLP_MAC_DA_PREFIX_CHECK_ENABLEf,
   8022                                                      prefix_check);
   8023             SOC_IF_ERROR_RETURN(
   8024                                 WRITE_ING_PHYSICAL_PORT_TABLEm(unit,
   8025                                                                MEM_BLOCK_ALL,
   8026                                                                port_id,
   8027                                                                &port_entry));
   8028 
   8029         }
   8030         /* Disable EFILTER */
   8031         SOC_IF_ERROR_RETURN(soc_mem_read(unit, ING_EN_EFILTER_BITMAPm, 
   8032                     MEM_BLOCK_ANY, 0, &efilter_entry));
   8033         soc_mem_pbmp_field_get(unit, ING_EN_EFILTER_BITMAPm,
   8034                 &efilter_entry, BITMAPf, &pbmp);
   8035         if (olp_enable) {
   8036             SOC_PBMP_PORT_REMOVE(pbmp, port_id);
   8037         } else {
   8038             SOC_PBMP_PORT_ADD(pbmp, port_id);
   8039         }
   8040         soc_mem_pbmp_field_set(unit, ING_EN_EFILTER_BITMAPm,
   8041                                           &efilter_entry, BITMAPf, &pbmp);
   8042         SOC_IF_ERROR_RETURN(soc_mem_write(unit, ING_EN_EFILTER_BITMAPm, 
   8043                                               MEM_BLOCK_ALL, 0, &efilter_entry));
   8044     }
   8045 
   8046     if(BCM_VLAN_VALID(vlan) && !BCM_MAC_IS_ZERO(olp_mac)) {
   8047         /* Set l2 address info. */
   8048         bcm_l2_addr_t_init(&l2addr, olp_mac, vlan);
   8049 
   8050         if (olp_enable) {
   8051             /* Set l2 entry flags. */
   8052             l2addr.flags = BCM_L2_STATIC;
   8053             /* Set l2 entry port dglp*/
   8054             l2addr.port = port;
   8055             bcm_esw_l2_addr_add(unit, &l2addr); 
   8056         } else {
   8057             BCM_IF_ERROR_RETURN(bcm_esw_l2_addr_delete(unit, olp_mac, vlan)); 
   8058         }
   8059     }
   8060     return BCM_E_NONE; 
   8061 }
   8062 
   8063 /* Obsolete, check bcmSwitchOamOlpStationMacOui */
   8064 STATIC int
   8065 _bcm_l2_xgs_mac_set(int unit, int index, bcm_mac_t xgs_mac)
   8066 {
   8067     egr_olp_config_entry_t    eolp_cfg;
   8068     uint64                    iarb_olp_cfg;
   8069     uint64                    mac_field;
   8070     uint64                    mask_field;
   8071     int                       set;
   8072     bcm_port_t                port;
   8073     bcm_pbmp_t                ports;
   8074     int                       olp_port;
   8075 
   8076     /* Set MAC address in IARB_OLP_CONFIG */
   8077     SAL_MAC_ADDR_TO_UINT64(xgs_mac, mac_field);
   8078 
   8079     COMPILER_64_ZERO(iarb_olp_cfg); 
   8080 
   8081     SOC_IF_ERROR_RETURN(READ_IARB_OLP_CONFIGr(unit, &iarb_olp_cfg));
   8082 
   8083     soc_reg64_field_set(unit, IARB_OLP_CONFIGr, &iarb_olp_cfg, MACDAf, mac_field);
   8084 
   8085     SOC_IF_ERROR_RETURN(WRITE_IARB_OLP_CONFIGr(unit, iarb_olp_cfg));
   8086   
   8087     /* Set MAC address in EGR_OLP_CONFIG */
   8088     SOC_IF_ERROR_RETURN(
   8089               READ_EGR_OLP_CONFIGm(unit, MEM_BLOCK_ANY, index, &eolp_cfg));
   8090 
   8091     soc_mem_mac_addr_set(unit, EGR_OLP_CONFIGm, &eolp_cfg, 
   8092                                    MACSAf, xgs_mac);
   8093     SOC_IF_ERROR_RETURN(
   8094                 WRITE_EGR_OLP_CONFIGm(unit, MEM_BLOCK_ALL, 
   8095                                            index, &eolp_cfg));
   8096 
   8097     /* Set mask and data values in ING_OLP_CONFIG_ register */
   8098     if (COMPILER_64_IS_ZERO(mac_field)) {
   8099         set = FALSE;
   8100         COMPILER_64_SET(mask_field, 0x0, 0x0);
   8101     } else {
   8102         set = TRUE;
   8103         COMPILER_64_SET(mask_field, 0XFFFF, 0xFFFFFFFF);
   8104     }
   8105 
   8106     SOC_IF_ERROR_RETURN(WRITE_ING_OLP_CONFIG_0_64r(unit, mac_field));
   8107 
   8108     SOC_IF_ERROR_RETURN(WRITE_ING_OLP_CONFIG_1_64r(unit, mask_field));
   8109 
   8110     /* Enable/Disable the OLP MACDA prefix checking for front panel ports */
   8111     BCM_PBMP_ASSIGN(ports, PBMP_PORT_ALL(unit));
   8112 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   8113     if(SOC_IS_TRIDENT2PLUS(unit)) {
   8114         port_tab_entry_t            port_entry;
   8115         iarb_ing_port_table_entry_t iarb_ing_port_entry;
   8116 
   8117         PBMP_ITER(ports, port) {
   8118             SOC_IF_ERROR_RETURN(soc_mem_read(unit, PORT_TABm,
   8119                                              MEM_BLOCK_ANY, port, &port_entry));
   8120 
   8121             SOC_IF_ERROR_RETURN(soc_mem_read(unit, IARB_ING_PORT_TABLEm, 
   8122                                     MEM_BLOCK_ANY, port, &iarb_ing_port_entry));
   8123             if (soc_IARB_ING_PORT_TABLEm_field32_get(unit, &iarb_ing_port_entry,
   8124                                                      OLP_ENABLEf)) {
   8125                 olp_port = TRUE;
   8126             } else {
   8127                 olp_port = FALSE;
   8128             }
   8129 
   8130             if (!IS_HG_PORT(unit, port) && (TRUE == set) && (FALSE == olp_port)) {
   8131                 soc_PORT_TABm_field32_set(unit, &port_entry,
   8132                                           OLP_MAC_DA_PREFIX_CHECK_ENABLEf, 1);
   8133             } else {
   8134                 soc_PORT_TABm_field32_set(unit, &port_entry,
   8135                                           OLP_MAC_DA_PREFIX_CHECK_ENABLEf, 0);
   8136             }
   8137             SOC_IF_ERROR_RETURN(soc_mem_write(unit, PORT_TABm,
   8138                                              MEM_BLOCK_ALL, port, &port_entry));
   8139         }
   8140 
   8141     } else
   8142 #endif
   8143     {
   8144         ing_physical_port_table_entry_t port_entry;
   8145         iarb_ing_physical_port_entry_t iarb_entry;
   8146 
   8147         PBMP_ITER(ports, port) {
   8148             SOC_IF_ERROR_RETURN(soc_mem_read(unit, ING_PHYSICAL_PORT_TABLEm,
   8149                                              MEM_BLOCK_ANY, port, &port_entry));
   8150 
   8151             SOC_IF_ERROR_RETURN(soc_mem_read(unit, IARB_ING_PHYSICAL_PORTm, 
   8152                                    MEM_BLOCK_ANY, port, &iarb_entry));
   8153 
   8154             if (soc_IARB_ING_PHYSICAL_PORTm_field32_get(unit, &iarb_entry,
   8155                                                         OLP_ENABLEf)) {
   8156                 olp_port = TRUE;
   8157             } else {
   8158                 olp_port = FALSE;
   8159             }
   8160             if (!IS_HG_PORT(unit, port) && (TRUE == set) && (FALSE == olp_port)) {
   8161                 soc_ING_PHYSICAL_PORT_TABLEm_field32_set(unit, &port_entry,
   8162                                             OLP_MAC_DA_PREFIX_CHECK_ENABLEf, 1);
   8163             } else {
   8164                 soc_ING_PHYSICAL_PORT_TABLEm_field32_set(unit, &port_entry,
   8165                                             OLP_MAC_DA_PREFIX_CHECK_ENABLEf, 0);
   8166             }
   8167             SOC_IF_ERROR_RETURN(soc_mem_write(unit, ING_PHYSICAL_PORT_TABLEm,
   8168                                              MEM_BLOCK_ALL, port, &port_entry));
   8169         }
   8170     }
   8171     return BCM_E_NONE; 
   8172 }
   8173 /* Soon to become Obsolete, check bcm_switch_olp_l2_addr_xxx */
   8174 STATIC int
   8175 _bcm_l2_station_non_tcam_entry_delete(int unit, 
   8176                                  _bcm_l2_station_control_t *sc, 
   8177                                  _bcm_l2_station_entry_t *s_ent,
   8178                                  int station_id) 
   8179 {
   8180     int                         rv = BCM_E_NONE;  /* Operation return status. */
   8181     int                         port_entries_total=0;
   8182     bcm_mac_t                   mac_addr = {0,0,0,0,0,0};
   8183 
   8184 #if defined(BCM_KATANA2_SUPPORT) 
   8185     if (SOC_IS_KATANA2(unit)) {
   8186         port_entries_total = sc->port_entries_total;
   8187     }
   8188 #endif
   8189 #if defined(BCM_KATANA2_SUPPORT)
   8190     if (s_ent->flags & _BCM_L2_STATION_ENTRY_TYPE_OAM_MAC) {
   8191         rv = _bcm_kt2_l2_port_mac_set(unit, s_ent->hw_index, mac_addr);
   8192         sc->port_entries_free++;
   8193         /* Remove the entry pointer from the list. */
   8194         sc->entry_arr[s_ent->hw_index + sc->entries_total] = NULL;
   8195     } else 
   8196 #endif    
   8197     if (s_ent->flags & _BCM_L2_STATION_ENTRY_TYPE_OLP_MAC) {
   8198         rv = _bcm_l2_olp_mac_set(unit, s_ent->hw_index, 0, 
   8199                                      mac_addr, OLP_ACTION_DELETE);
   8200         sc->entry_arr[s_ent->hw_index + 
   8201                       sc->entries_total + port_entries_total] = NULL;
   8202         sc->olp_entries_free++;
   8203     } else if (s_ent->flags & _BCM_L2_STATION_ENTRY_TYPE_XGS_MAC) {
   8204         rv = _bcm_l2_xgs_mac_set(unit, 0, mac_addr);
   8205         sc->entry_arr[s_ent->hw_index + sc->entries_total + 
   8206                       port_entries_total + sc->olp_entries_total] = NULL;
   8207     }
   8208     LOG_DEBUG(BSL_LS_BCM_L2,
   8209             (BSL_META_U(unit,
   8210                         "rv %d, flag 0x%x, station %d\n"), 
   8211              rv, s_ent->flags, station_id));
   8212     return (rv);
   8213 }
   8214 /* Soon to become Obsolete, check bcm_switch_olp_l2_addr_xxx */
   8215 STATIC int
   8216 _bcm_l2_station_non_tcam_entry_get(int unit, _bcm_l2_station_control_t *sc, 
   8217                               _bcm_l2_station_entry_t *s_ent,
   8218                               int station_id, bcm_l2_station_t *station) 
   8219 {
   8220     int         rv = BCM_E_NONE;  /* Operation return status. */
   8221     egr_olp_config_entry_t    eolp_cfg;
   8222     egr_olp_dgpp_config_entry_t eolp_dgpp_cfg;
   8223 
   8224 #if defined(BCM_KATANA2_SUPPORT)
   8225     if (s_ent->flags & _BCM_L2_STATION_ENTRY_TYPE_OAM_MAC) {
   8226         port_tab_entry_t          ptab;        
   8227         SOC_IF_ERROR_RETURN(
   8228                 READ_PORT_TABm(unit, MEM_BLOCK_ANY, s_ent->hw_index, &ptab));
   8229         station->src_port = s_ent->hw_index;
   8230         soc_mem_mac_addr_get(unit, PORT_TABm, &ptab, 
   8231                              MAC_ADDRESSf, station->dst_mac);
   8232         station->flags = BCM_L2_STATION_OAM; 
   8233     } else 
   8234 #endif    
   8235     if (s_ent->flags & _BCM_L2_STATION_ENTRY_TYPE_OLP_MAC) {
   8236         SOC_IF_ERROR_RETURN(
   8237               READ_EGR_OLP_DGPP_CONFIGm(unit, MEM_BLOCK_ANY, 
   8238                                          s_ent->hw_index, &eolp_dgpp_cfg));
   8239         station->src_port = soc_mem_field32_get(unit, EGR_OLP_DGPP_CONFIGm, 
   8240                                   &eolp_dgpp_cfg, DGLPf);
   8241         soc_mem_mac_addr_get(unit, EGR_OLP_DGPP_CONFIGm, &eolp_dgpp_cfg, 
   8242                              MACDAf, station->dst_mac);
   8243         station->flags = BCM_L2_STATION_OLP; 
   8244     } else if (s_ent->flags & _BCM_L2_STATION_ENTRY_TYPE_XGS_MAC) {
   8245         SOC_IF_ERROR_RETURN(
   8246               READ_EGR_OLP_CONFIGm(unit, MEM_BLOCK_ANY, 0, &eolp_cfg));
   8247          soc_mem_mac_addr_get(unit, EGR_OLP_CONFIGm, &eolp_cfg, 
   8248                                             MACSAf, station->dst_mac);
   8249         station->flags = BCM_L2_STATION_XGS_MAC; 
   8250     }
   8251     return rv;
   8252 }
   8253 
   8254 #endif /* BCM_KATANA2_SUPPORT OR TD2+*/
   8255 
   8256 #if defined(BCM_KATANA2_SUPPORT)
   8257 
   8258 /*
   8259  * Function:
   8260  *     _bcm_kt2_l2_station_entry_create
   8261  * Purpose:
   8262  *     Allocate an entry buffer and setup entry parameters for hardware write
   8263  *     operation.
   8264  * Parameters:
   8265  *     unit       - (IN) BCM device number
   8266  *     sid        - (IN) Station ID.
   8267  *     station    - (IN) Station parameters to be set in hardware.
   8268  *     ent_p      - (OUT) Pointer to Station entry type data.
   8269  * Returns:
   8270  *     BCM_E_XXX
   8271  */
   8272 STATIC int
   8273 _bcm_kt2_l2_station_entry_create(int unit,
   8274                              int sid,
   8275                              bcm_l2_station_t *station,
   8276                              _bcm_l2_station_entry_t **ent_pp)
   8277 {
   8278     _bcm_l2_station_control_t *sc;           /* Station control structure. */
   8279     int                       index;         /* Entry index.               */
   8280     _bcm_l2_station_entry_t   *ent_p = NULL; /* L2 station entry pointer.  */
   8281     soc_mem_t                 tcam_mem;      /* TCAM memory name.          */ 
   8282     int                       mem_size = 0;  /* Entry buffer size.         */
   8283     int                       rv;            /* Operation return status.   */
   8284     int                       index_max;     /* Max Entry index.           */
   8285     bcm_module_t       module_id;            /* Module ID           */
   8286     bcm_port_t         port_id;              /* Port ID.            */
   8287     bcm_trunk_t        trunk_id;             /* Trunk ID.           */
   8288     int                local_id;             /* Hardware ID.        */
   8289     BCM_IF_ERROR_RETURN(_bcm_l2_station_control_get(unit, &sc));
   8290 
   8291     if (station->flags & BCM_L2_STATION_OAM) {
   8292         if (0 == sc->port_entries_free) {
   8293             return (BCM_E_RESOURCE);
   8294         }
   8295     } else if (station->flags & BCM_L2_STATION_OLP) { 
   8296         if (0 == sc->olp_entries_free) {
   8297             return (BCM_E_RESOURCE);
   8298         }
   8299     } else if (station->flags & BCM_L2_STATION_XGS_MAC) { 
   8300         /* do nothing */
   8301     } else if (0 == sc->entries_free)  {
   8302         return (BCM_E_RESOURCE);
   8303     }
   8304 
   8305     ent_p = (_bcm_l2_station_entry_t *)
   8306             sal_alloc(sizeof(_bcm_l2_station_entry_t), "Sw L2 station entry");
   8307     if (NULL == ent_p) {
   8308         return (BCM_E_MEMORY);
   8309     }
   8310 
   8311     sal_memset(ent_p, 0, sizeof(_bcm_l2_station_entry_t));
   8312 
   8313 
   8314     ent_p->sid = sid;
   8315 
   8316     ent_p->prio = station->priority;
   8317 
   8318     if (station->flags & BCM_L2_STATION_OAM) {
   8319         /* Get index to PORT table from source port */ 
   8320         if (BCM_GPORT_IS_SET(station->src_port)) {
   8321             rv = _bcm_esw_gport_resolve(unit, station->src_port,  &module_id,
   8322                                         &port_id, &trunk_id, &local_id);
   8323             if (BCM_FAILURE(rv)) {
   8324                 sal_free(ent_p);
   8325                 return (rv);
   8326             }
   8327             rv = _bcm_kt2_modport_to_pp_port_get(unit, module_id, port_id,
   8328                                                 &index);
   8329             if (BCM_FAILURE(rv)) {
   8330                 sal_free(ent_p);
   8331                 return (rv);
   8332             }
   8333         } else {
   8334             index = station->src_port;
   8335         }
   8336         if (NULL == sc->entry_arr[index + sc->entries_total]) {
   8337             ent_p->hw_index = index;
   8338         } else if (!(station->flags & BCM_L2_STATION_REPLACE)) {
   8339             sal_free(ent_p);
   8340             return BCM_E_PARAM;
   8341         }
   8342         ent_p->flags |= _BCM_L2_STATION_ENTRY_TYPE_NON_TCAM;
   8343         ent_p->flags |= _BCM_L2_STATION_ENTRY_TYPE_OAM_MAC;
   8344         /* Set MAC address in Port table */
   8345         rv = _bcm_kt2_l2_port_mac_set(unit, index, station->dst_mac);
   8346         if (BCM_FAILURE(rv)) {
   8347             sal_free(ent_p);
   8348             return (rv);
   8349         }
   8350         index += sc->entries_total;
   8351         sc->port_entries_free--;
   8352     } else if (station->flags & BCM_L2_STATION_OLP) {
   8353         /* Get the first free slot. */
   8354         index = sc->entries_total + sc->port_entries_total;
   8355         index_max = index + sc->olp_entries_total;
   8356         for (; index < index_max; index++) {
   8357             if (NULL == sc->entry_arr[index]) {
   8358                 ent_p->hw_index = index - 
   8359                                  (sc->entries_total + sc->port_entries_total);
   8360                 break;
   8361             }
   8362         }
   8363         ent_p->flags |= _BCM_L2_STATION_ENTRY_TYPE_NON_TCAM;
   8364         ent_p->flags |= _BCM_L2_STATION_ENTRY_TYPE_OLP_MAC;
   8365         sc->olp_entries_free--;
   8366         /* Set MAC address and DGLP in EGR_OLP_DGLP_CONFIG */
   8367         rv = _bcm_l2_olp_mac_set(unit, ent_p->hw_index, station->src_port,
   8368                                      station->dst_mac, OLP_ACTION_ADD);
   8369         if (BCM_FAILURE(rv)) {
   8370             sal_free(ent_p);
   8371             sc->olp_entries_free++;
   8372             return (rv);
   8373         }
   8374     } else if (station->flags & BCM_L2_STATION_XGS_MAC) {
   8375         index = sc->entries_total + sc->port_entries_total + 
   8376                                     sc->olp_entries_total;
   8377         ent_p->hw_index = 0;
   8378         ent_p->flags |= _BCM_L2_STATION_ENTRY_TYPE_NON_TCAM;
   8379         ent_p->flags |= _BCM_L2_STATION_ENTRY_TYPE_XGS_MAC;
   8380         /* Set MAC address in IARB_OLP_CONFIG and EGR_OLP_CONFIG */
   8381         rv = _bcm_l2_xgs_mac_set(unit, 0, station->dst_mac);
   8382         if (BCM_FAILURE(rv)) {
   8383             sal_free(ent_p);
   8384             return (rv);
   8385         }
   8386     } else {
   8387 
   8388         /* Get the first free slot. */
   8389         for (index = 0; index < sc->entries_total; index++) {
   8390             if (NULL == sc->entry_arr[index]) {
   8391                 ent_p->hw_index = index;
   8392                 break;
   8393             }
   8394         }
   8395 
   8396         rv = _bcm_l2_station_tcam_mem_get(unit,
   8397              _BCM_L2_STATION_ENTRY_UNDERLAY, &tcam_mem);
   8398         if (BCM_FAILURE(rv)) {
   8399             sal_free(ent_p);
   8400             return (rv);
   8401         }
   8402 
   8403         mem_size = sizeof(my_station_tcam_entry_t);
   8404 
   8405         ent_p->tcam_ent = sal_alloc(mem_size, "L2 station entry buffer");
   8406         if (NULL == ent_p->tcam_ent) {
   8407             sal_free(ent_p);
   8408             return (BCM_E_MEMORY);
   8409         }
   8410 
   8411         sal_memset(ent_p->tcam_ent, 0, mem_size);
   8412 
   8413         rv = _bcm_l2_station_entry_set(unit, tcam_mem, station, ent_p);
   8414         if (BCM_FAILURE(rv)) {
   8415             sal_free(ent_p);
   8416             return (rv);
   8417         }
   8418 
   8419         sc->entries_free--;
   8420         sc->entry_count++;
   8421     }
   8422     sc->entry_arr[index] = ent_p;
   8423     *ent_pp = ent_p;
   8424 
   8425     return (BCM_E_NONE);
   8426 }
   8427 
   8428 /*
   8429  * Function:
   8430  *     _bcm_kt2_l2_station_entry_update
   8431  * Purpose:
   8432  *     Allocate an entry buffer and setup entry parameters for hardware write
   8433  *     operation.
   8434  * Parameters:
   8435  *     unit       - (IN) BCM device number
   8436  *     sid        - (IN) Station ID.
   8437  *     station    - (IN) Station parameters to be set in hardware.
   8438  *     ent_p      - (OUT) Pointer to Station entry type data.
   8439  * Returns:
   8440  *     BCM_E_XXX
   8441  */
   8442 STATIC int
   8443 _bcm_kt2_l2_station_entry_update(int unit,
   8444                              int sid,
   8445                              bcm_l2_station_t *station,
   8446                              _bcm_l2_station_entry_t *ent_p)
   8447 {
   8448     soc_mem_t   tcam_mem;    /* TCAM memory name.         */
   8449     int         rv;           /* Operation return status. */
   8450     int         mem_size = 0; /* Entry buffer size.       */
   8451 
   8452     if (station->flags & BCM_L2_STATION_OAM) {
   8453         if (ent_p->flags & _BCM_L2_STATION_ENTRY_TYPE_OAM_MAC) {
   8454             rv = _bcm_kt2_l2_port_mac_set(unit, ent_p->hw_index, 
   8455                                           station->dst_mac);
   8456         } else {
   8457             rv = BCM_E_PARAM; 
   8458         }
   8459         return rv;
   8460     } else if (station->flags & BCM_L2_STATION_OLP) {
   8461         if (ent_p->flags & _BCM_L2_STATION_ENTRY_TYPE_OLP_MAC) {
   8462             rv = _bcm_l2_olp_mac_set(unit, ent_p->hw_index, 
   8463                                          station->src_port, 
   8464                                          station->dst_mac, OLP_ACTION_UPDATE);
   8465         } else {
   8466             rv = BCM_E_PARAM; 
   8467         }
   8468         return rv;
   8469     } else if (station->flags & BCM_L2_STATION_XGS_MAC) {
   8470         if (ent_p->flags & _BCM_L2_STATION_ENTRY_TYPE_XGS_MAC) {
   8471             rv = _bcm_l2_xgs_mac_set(unit, 0, station->dst_mac);
   8472         } else {
   8473             rv = BCM_E_PARAM; 
   8474         }
   8475         return rv;
   8476     } else {
   8477         rv = _bcm_l2_station_tcam_mem_get(unit,
   8478                                           _BCM_L2_STATION_ENTRY_LEGACY,
   8479                                           &tcam_mem);
   8480         if (BCM_FAILURE(rv)) {
   8481             return (rv);
   8482         }
   8483 
   8484         mem_size = sizeof(my_station_tcam_entry_t);
   8485 
   8486         ent_p->tcam_ent = sal_alloc(mem_size, "L2 station entry buffer");
   8487         if (NULL == ent_p->tcam_ent) {
   8488             return (BCM_E_MEMORY);
   8489         }
   8490 
   8491         sal_memset(ent_p->tcam_ent, 0, mem_size);
   8492     
   8493         BCM_IF_ERROR_RETURN(_bcm_l2_station_entry_set(unit, tcam_mem, 
   8494                                station, ent_p));
   8495     }
   8496     return (BCM_E_NONE);
   8497 }
   8498 
   8499 
   8500 #endif
   8501 
   8502 /*
   8503  * Function:
   8504  *     _bcm_l2_station_entry_update
   8505  * Purpose:
   8506  *     Allocate an entry buffer and setup entry parameters for hardware write
   8507  *     operation.
   8508  * Parameters:
   8509  *     unit       - (IN) BCM device number
   8510  *     sid        - (IN) Station ID.
   8511  *     station    - (IN) Station parameters to be set in hardware.
   8512  *     ent_p      - (OUT) Pointer to Station entry type data.
   8513  * Returns:
   8514  *     BCM_E_XXX
   8515  */
   8516 STATIC int
   8517 _bcm_l2_station_entry_update(int unit,
   8518                              int sid,
   8519                              bcm_l2_station_t *station,
   8520                              _bcm_l2_station_entry_t *ent_p)
   8521 {
   8522     soc_mem_t   tcam_mem;    /* TCAM memory name.         */
   8523     int         rv;           /* Operation return status. */
   8524     int         mem_size = 0; /* Entry buffer size.       */
   8525 
   8526     /* Input parameter check. */
   8527     if (NULL == ent_p || NULL == station) {
   8528         return (BCM_E_PARAM);
   8529     }
   8530 
   8531     LOG_DEBUG(BSL_LS_BCM_L2,
   8532               (BSL_META_U(unit,
   8533                           "L2(unit %d) Info: (SID=%d) (idx=%d) (prio: o=%d n=%d) "
   8534                            "- update.\n"), unit, sid, ent_p->hw_index, ent_p->prio,
   8535                station->priority));
   8536 
   8537     if (ent_p->prio == station->priority) {
   8538         ent_p->flags |= _BCM_L2_STATION_ENTRY_PRIO_NO_CHANGE;
   8539     } else {
   8540         ent_p->prio = station->priority;
   8541     }
   8542 
   8543 #if defined(BCM_KATANA2_SUPPORT) 
   8544     if (SOC_IS_KATANA2(unit)) {
   8545         rv = _bcm_kt2_l2_station_entry_update(unit, sid, station, ent_p);
   8546         return (rv);
   8547     }
   8548 #endif /* BCM_KATANA2_SUPPORT */
   8549 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   8550     if (soc_feature(unit, soc_feature_fp_based_oam) &&
   8551             ((station->flags & BCM_L2_STATION_OLP) ||
   8552              (station->flags & BCM_L2_STATION_XGS_MAC))) {
   8553         
   8554         if (station->flags & BCM_L2_STATION_OLP) {
   8555             if (ent_p->flags & _BCM_L2_STATION_ENTRY_TYPE_OLP_MAC) {
   8556                 rv = _bcm_l2_olp_mac_set(unit, ent_p->hw_index, 
   8557                         station->src_port, 
   8558                         station->dst_mac, OLP_ACTION_UPDATE);
   8559             } else {
   8560                 rv = BCM_E_PARAM; 
   8561             }
   8562         } else {
   8563             /* BCM_L2_STATION_XGS_MAC */
   8564             if (ent_p->flags & _BCM_L2_STATION_ENTRY_TYPE_XGS_MAC) {
   8565                 rv = _bcm_l2_xgs_mac_set(unit, 0, station->dst_mac);
   8566             } else {
   8567                 rv = BCM_E_PARAM; 
   8568             }
   8569         } 
   8570         return rv;
   8571     }
   8572 #endif                             
   8573 
   8574     rv = _bcm_l2_station_tcam_mem_get(unit, _BCM_L2_STATION_OVERLAY(station),
   8575                                        &tcam_mem);
   8576     if (BCM_FAILURE(rv)) {
   8577         return (rv);
   8578     }
   8579 
   8580 #ifdef BCM_RIOT_SUPPORT
   8581     if (_BCM_L2_STATION_OVERLAY(station)) {
   8582         mem_size = sizeof(my_station_tcam_2_entry_t);
   8583     } else
   8584 #endif /* BCM_RIOT_SUPPORT */
   8585     if (SOC_IS_ENDURO(unit) || SOC_IS_TRIUMPH(unit)
   8586         || SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit)
   8587         || SOC_IS_VALKYRIE(unit) || SOC_IS_VALKYRIE2(unit)
   8588         || SOC_IS_HURRICANE(unit) || SOC_IS_HURRICANE2(unit)) {
   8589 
   8590         mem_size = sizeof(mpls_station_tcam_entry_t);
   8591 
   8592     } else if (SOC_IS_KATANAX(unit) || SOC_IS_TRIDENT(unit)
   8593                || SOC_IS_TD2_TT2(unit) || SOC_IS_TRIUMPH3(unit)
   8594                || soc_feature(unit, soc_feature_gh2_my_station)) {
   8595 
   8596         mem_size = sizeof(my_station_tcam_entry_t);
   8597 
   8598     }
   8599 
   8600     if (0 == mem_size) {
   8601         /* Must be a valid mem_size value. */
   8602         return (BCM_E_INTERNAL);
   8603     }
   8604 
   8605     ent_p->tcam_ent = sal_alloc(mem_size, "L2 station entry buffer");
   8606     if (NULL == ent_p->tcam_ent) {
   8607         return (BCM_E_MEMORY);
   8608     }
   8609 
   8610     sal_memset(ent_p->tcam_ent, 0, mem_size);
   8611     
   8612     BCM_IF_ERROR_RETURN(_bcm_l2_station_entry_set(unit, tcam_mem, 
   8613                            station, ent_p));
   8614 
   8615     return (BCM_E_NONE);
   8616 }
   8617 
   8618 /*
   8619  * Function:
   8620  *     _bcm_l2_station_entry_create
   8621  * Purpose:
   8622  *     Allocate an entry buffer and setup entry parameters for hardware write
   8623  *     operation.
   8624  * Parameters:
   8625  *     unit       - (IN) BCM device number
   8626  *     sid        - (IN) Station ID.
   8627  *     station    - (IN) Station parameters to be set in hardware.
   8628  *     ent_p      - (OUT) Pointer to Station entry type data.
   8629  * Returns:
   8630  *     BCM_E_XXX
   8631  */
   8632 STATIC int
   8633 _bcm_l2_station_entry_create(int unit,
   8634                              int sid,
   8635                              bcm_l2_station_t *station,
   8636                              _bcm_l2_station_entry_t **ent_pp)
   8637 {
   8638     _bcm_l2_station_control_t *sc;           /* Station control structure. */
   8639     int                       index;         /* Entry index.               */
   8640     _bcm_l2_station_entry_t   *ent_p = NULL; /* L2 station entry pointer.  */
   8641     soc_mem_t                 tcam_mem;      /* TCAM memory name.          */ 
   8642     int                       mem_size = 0;  /* Entry buffer size.         */
   8643     int                       rv;            /* Operation return status.   */
   8644     int                       entries_total;
   8645     int                       overlay;
   8646     _bcm_l2_station_entry_t   **entry_arr;
   8647 
   8648     /* Input parameter check. */
   8649     if (NULL == station || NULL == ent_pp) {
   8650         return (BCM_E_PARAM);
   8651     }
   8652 #ifdef BCM_KATANA2_SUPPORT
   8653     if (SOC_IS_KATANA2(unit)) {
   8654         rv = _bcm_kt2_l2_station_entry_create(unit, sid, station, ent_pp);
   8655         return rv;
   8656     } 
   8657 #endif    
   8658     
   8659     BCM_IF_ERROR_RETURN(_bcm_l2_station_control_get(unit, &sc));
   8660 
   8661 #ifdef BCM_RIOT_SUPPORT
   8662     if (_BCM_L2_STATION_ID_OVERLAY(sid)) {
   8663         if (0 == sc->entries_free_2) {
   8664             return (BCM_E_RESOURCE);
   8665         }
   8666         overlay = _BCM_L2_STATION_ENTRY_OVERLAY;
   8667         entry_arr = (sc->entry_arr_2);
   8668         entries_total = sc->entries_total_2;
   8669     } else
   8670 #endif /* BCM_RIOT_SUPPORT */
   8671     {
   8672         if (0 == sc->entries_free) {
   8673             return (BCM_E_RESOURCE);
   8674         }
   8675         overlay = _BCM_L2_STATION_ENTRY_UNDERLAY;
   8676         entry_arr = (sc->entry_arr);
   8677         entries_total = sc->entries_total;
   8678     }
   8679 
   8680     ent_p = (_bcm_l2_station_entry_t *)
   8681         sal_alloc(sizeof(_bcm_l2_station_entry_t), "Sw L2 station entry");
   8682     if (NULL == ent_p) {
   8683         return (BCM_E_MEMORY);
   8684     }
   8685 
   8686     sal_memset(ent_p, 0, sizeof(_bcm_l2_station_entry_t));
   8687     ent_p->sid = sid;
   8688     ent_p->prio = station->priority;
   8689 
   8690 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   8691     if (soc_feature(unit, soc_feature_fp_based_oam) &&
   8692             ((station->flags & BCM_L2_STATION_OLP) || 
   8693              (station->flags & BCM_L2_STATION_XGS_MAC)) &&
   8694              (overlay == _BCM_L2_STATION_ENTRY_UNDERLAY)) {
   8695         int index_max;
   8696 
   8697         if ((station->flags & BCM_L2_STATION_OLP) &&  
   8698                 (0 == sc->olp_entries_free)) {
   8699             sal_free(ent_p);
   8700             return (BCM_E_RESOURCE);
   8701         }
   8702         if (station->flags & BCM_L2_STATION_OLP) {
   8703             index = sc->entries_total;
   8704             index_max = index + sc->olp_entries_total;
   8705             for (; index < index_max; index++) {
   8706                 if (NULL == sc->entry_arr[index]) {
   8707                     ent_p->hw_index = index - sc->entries_total; 
   8708                     break;
   8709                 }
   8710             }
   8711             ent_p->flags |= _BCM_L2_STATION_ENTRY_TYPE_NON_TCAM;
   8712             ent_p->flags |= _BCM_L2_STATION_ENTRY_TYPE_OLP_MAC;
   8713             sc->olp_entries_free--;
   8714             /* Set MAC address and DGLP in EGR_OLP_DGLP_CONFIG */
   8715             rv = _bcm_l2_olp_mac_set(unit, ent_p->hw_index, station->src_port,
   8716                     station->dst_mac, OLP_ACTION_ADD);
   8717             if (BCM_FAILURE(rv)) {
   8718                 sal_free(ent_p);
   8719                 sc->olp_entries_free++;
   8720                 return (rv);
   8721             }
   8722         } else {
   8723             /* BCM_L2_STATION_XGS_MAC */
   8724             index = sc->entries_total + sc->olp_entries_total;
   8725             ent_p->hw_index = 0;
   8726             ent_p->flags |= _BCM_L2_STATION_ENTRY_TYPE_NON_TCAM;
   8727             ent_p->flags |= _BCM_L2_STATION_ENTRY_TYPE_XGS_MAC;
   8728             /* Set MAC address in IARB_OLP_CONFIG and EGR_OLP_CONFIG */
   8729             rv = _bcm_l2_xgs_mac_set(unit, 0, station->dst_mac);
   8730             if (BCM_FAILURE(rv)) {
   8731                 sal_free(ent_p);
   8732                 return (rv);
   8733             }
   8734         }
   8735         sc->entry_arr[index] = ent_p;
   8736         *ent_pp = ent_p;
   8737         return (BCM_E_NONE);
   8738     }
   8739 #endif
   8740 
   8741     if (0 == sc->entries_free) {
   8742         sal_free(ent_p);
   8743         return (BCM_E_RESOURCE);
   8744     }
   8745 
   8746     /* Get the first free slot. */
   8747     for (index = 0; index < entries_total; index++) {
   8748         if (NULL == entry_arr[index]) {
   8749             ent_p->hw_index = index;
   8750             break;
   8751         }
   8752     }
   8753 
   8754 #ifdef BCM_TRIDENT3_SUPPORT
   8755     if (SOC_IS_TRIDENT3X(unit) && (station->flags & BCM_L2_STATION_FCOE)) {
   8756         tcam_mem = MY_STATION_TCAM_2m;
   8757     } else 
   8758 #endif /* BCM_TRIDENT3_SUPPORT */
   8759     {
   8760     rv = _bcm_l2_station_tcam_mem_get(unit, overlay, &tcam_mem);
   8761     if (BCM_FAILURE(rv)) {
   8762         sal_free(ent_p);
   8763         return (rv);
   8764     }
   8765     }
   8766 
   8767 #ifdef BCM_RIOT_SUPPORT
   8768     if (_BCM_L2_STATION_OVERLAY(station)) {
   8769         mem_size = sizeof(my_station_tcam_2_entry_t);
   8770     } else
   8771 #endif /* BCM_RIOT_SUPPORT */
   8772     if (SOC_IS_ENDURO(unit) || SOC_IS_TRIUMPH(unit)
   8773         || SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit)
   8774         || SOC_IS_VALKYRIE(unit) || SOC_IS_VALKYRIE2(unit)
   8775         || SOC_IS_HURRICANE(unit) || SOC_IS_HURRICANE2(unit)) {
   8776 
   8777         mem_size = sizeof(mpls_station_tcam_entry_t);
   8778 
   8779     } else if (SOC_IS_KATANAX(unit) || SOC_IS_TRIDENT(unit)
   8780                || SOC_IS_TD2_TT2(unit) || SOC_IS_TRIUMPH3(unit)
   8781                || soc_feature(unit, soc_feature_gh2_my_station)) {
   8782         mem_size = sizeof(my_station_tcam_entry_t);
   8783     }
   8784 
   8785     if (0 == mem_size) {
   8786         /* mem_size must be greater than zero. */
   8787         sal_free(ent_p);
   8788         return (BCM_E_INTERNAL);
   8789     }
   8790 
   8791     ent_p->tcam_ent = sal_alloc(mem_size, "L2 station entry buffer");
   8792     if (NULL == ent_p->tcam_ent) {
   8793         sal_free(ent_p);
   8794         return (BCM_E_MEMORY);
   8795     }
   8796 
   8797     sal_memset(ent_p->tcam_ent, 0, mem_size);
   8798 
   8799     rv = _bcm_l2_station_entry_set(unit, tcam_mem, station, ent_p);
   8800     if (BCM_FAILURE(rv)) {
   8801         sal_free(ent_p);
   8802         return (rv);
   8803     }
   8804 
   8805     /* Decrement free entries count. */
   8806 #ifdef BCM_RIOT_SUPPORT
   8807     if (_BCM_L2_STATION_OVERLAY(station)) {
   8808         sc->entries_free_2--;
   8809         sc->entry_count_2++;
   8810         sc->entry_arr_2[index] = ent_p;
   8811     } else
   8812 #endif /* BCM_RIOT_SUPPORT */
   8813     {
   8814         sc->entries_free--;
   8815         sc->entry_count++;
   8816         sc->entry_arr[index] = ent_p;
   8817     }
   8818 
   8819     *ent_pp = ent_p;
   8820 
   8821     return (BCM_E_NONE);
   8822 
   8823 }
   8824 
   8825 /*
   8826  * Function:
   8827  *     _bcm_l2_station_entry_prio_cmp
   8828  * Purpose:
   8829  *     Compare station entry priority values.
   8830  * Parameters:
   8831  *     prio_first   - (IN) First entry priority value.
   8832  *     prio_second  - (IN) Second entry priority value.
   8833  * Returns:
   8834  *     0    - if both priority values are equal.
   8835  *     -1   - if priority value of first entry is lower than second.
   8836  *     1    - if priority value of first entry is greater than second.
   8837  */
   8838 STATIC int
   8839 _bcm_l2_station_entry_prio_cmp(int prio_first, int prio_second)
   8840 {
   8841     int rv; /* Comparison result. */
   8842 
   8843     if (prio_first == prio_second) {
   8844         rv = 0;
   8845     } else if (prio_first < prio_second) {
   8846         rv = -1;
   8847     } else {
   8848         rv = 1;
   8849     }
   8850     return (rv);
   8851 }
   8852 
   8853 /*
   8854  * Function:
   8855  *     _bcm_l2_station_prio_move_required
   8856  * Purpose:
   8857  *     Check if entry move is required based on priority value.
   8858  * Parameters:
   8859  *     unit   - (IN) BCM device number
   8860  *     ent_p  - (IN) Station entry for priority comparison.
   8861  * Returns:
   8862  *     TRUE   - Entry move is required based on priority comparison.
   8863  *     FALSE  - Entry move is not required based on priority comparison.
   8864  */
   8865 STATIC int
   8866 _bcm_l2_station_prio_move_required(int unit, _bcm_l2_station_entry_t *ent_p)
   8867 {
   8868     _bcm_l2_station_control_t *sc;      /* station control structure.   */
   8869     _bcm_l2_station_entry_t **entry_arr;/* station entry array pointer  */
   8870     uint32                    count;    /* Maximum number of entries.   */
   8871     int                       i;        /* Temporary iterator variable. */
   8872     int                       ent_prio; /* Entry priority.              */
   8873     int                       flag;     /* Flag value denotes if we are */
   8874                                         /* before or after s_ent.       */
   8875 
   8876     /* Input parameter check. */
   8877     if (NULL == ent_p) {
   8878         return (BCM_E_INTERNAL);
   8879     }
   8880 
   8881     BCM_IF_ERROR_RETURN(_bcm_l2_station_control_get(unit, &sc));
   8882 
   8883     /* Get total number for entries supported. */
   8884 #ifdef BCM_RIOT_SUPPORT
   8885     if (_BCM_L2_STATION_ID_OVERLAY(ent_p->sid)) {
   8886         count = sc->entries_total_2;
   8887         entry_arr = (sc->entry_arr_2);
   8888     } else
   8889 #endif /* BCM_RIOT_SUPPORT */
   8890     {
   8891         count = sc->entries_total;
   8892         entry_arr = (sc->entry_arr);
   8893     }
   8894 
   8895     /* Get the entry priority value. */
   8896     ent_prio = ent_p->prio;
   8897 
   8898     /* Init flag value, we are before s_ent. */
   8899     flag = -1;
   8900 
   8901     for (i = 0; i < count; i++) {
   8902 
   8903         if (entry_arr[i] == ent_p) {
   8904             /* Now we are after s_ent. */
   8905             flag = 1;
   8906             continue;
   8907         }
   8908 
   8909         if (NULL == entry_arr[i]) {
   8910             continue;
   8911         }
   8912 
   8913         if (-1 == flag) {
   8914             if (_bcm_l2_station_entry_prio_cmp
   8915                     (entry_arr[i]->prio, ent_prio) < 0) {
   8916 
   8917                 LOG_DEBUG(BSL_LS_BCM_L2,
   8918                           (BSL_META_U(unit,
   8919                                       "L2(unit %d) Info: (SID=%d) found lower prio than "
   8920                                        "(prio=%d).\n"), unit, ent_p->sid, ent_p->prio));
   8921 
   8922                 /*
   8923                  * An entry  before s_ent has lower priority.
   8924                  * So, move is required.
   8925                  */
   8926                 return (TRUE);
   8927             }
   8928         } else {
   8929             if (_bcm_l2_station_entry_prio_cmp
   8930                     (entry_arr[i]->prio, ent_prio) > 0) {
   8931                 LOG_DEBUG(BSL_LS_BCM_L2,
   8932                           (BSL_META_U(unit,
   8933                                       "L2(unit %d) Info: (SID=%d) found higher prio than "
   8934                                        "(prio=%d).\n"), unit, ent_p->sid, ent_p->prio));
   8935                 /*
   8936                  * An entry after s_ent has higher priority than s_ent prio.
   8937                  * So, move is required.
   8938                  */
   8939                 return (TRUE);
   8940             }
   8941         }
   8942     }
   8943 
   8944     LOG_DEBUG(BSL_LS_BCM_L2,
   8945               (BSL_META_U(unit,
   8946                           "L2(unit %d) Info: (SID=%d) (prio=%d) no move.\n"),
   8947                unit, ent_p->sid, ent_p->prio));
   8948     return (FALSE);
   8949 }
   8950 
   8951 /*
   8952  * Function:
   8953  *     _bcm_l2_station_entry_move_check
   8954  * Purpose:
   8955  *     Calculate number of entries that need to be moved for installing the
   8956  *     new station entry.
   8957  * Parameters:
   8958  *     unit                     - (IN) BCM device number
   8959  *     null_index               - (IN) Free null entry hardware index.
   8960  *     target_index             - (IN) Target hardware index for the entry.
   8961  *     direction                - (IN) Direction of Move.
   8962  *     shifted_entries_count    - (OUT) No. of entries to be moved.
   8963  * Returns:
   8964  *     BCM_E_NONE
   8965  */
   8966 STATIC int
   8967 _bcm_l2_station_entry_move_check(int unit, int null_index,
   8968                                  int target_index, int direction,
   8969                                  int *shifted_entries_count)
   8970 {
   8971     *shifted_entries_count += direction * (null_index - target_index);
   8972 
   8973     return (BCM_E_NONE);
   8974 }
   8975 
   8976 /*
   8977  * Function:
   8978  *     _bcm_l2_station_entry_dir_get
   8979  * Purpose:
   8980  *     Find out direction in which entries need to be moved for installing
   8981  *     new station entry in hardware.
   8982  * Parameters:
   8983  *     unit             - (IN) BCM device number
   8984  *     ent_p            - (IN) Station entry pointer.
   8985  *     prev_null_index  - (IN) Location of previous null entry in hardware.
   8986  *     next_null_index  - (IN) Location of next null entry in hardware.
   8987  *     target_index     - (IN) Target index where entry needs to be installed.
   8988  *     dir              - (OUT) Direction in which entries need to be moved.
   8989  * Returns:
   8990  *     BCM_E_XXX
   8991  */
   8992 STATIC int
   8993 _bcm_l2_station_entry_dir_get(int unit,
   8994                               _bcm_l2_station_entry_t *ent_p,
   8995                               int prev_null_index,
   8996                               int next_null_index,
   8997                               int target_index,
   8998                               int *dir)
   8999 {
   9000     _bcm_l2_station_control_t  *sc;                   /* Station control    */
   9001                                                       /* strucutre.         */
   9002     int                        shift_up = FALSE;      /* Shift UP status.   */
   9003     int                        shift_down = FALSE;    /* Shift DOWN status. */
   9004     int                        shift_up_amount = 0;   /* Shift UP amount.   */
   9005     int                        shift_down_amount = 0; /* Shift DOWN amount. */
   9006     int                        rv;                    /* Operation return   */
   9007                                                       /* status.            */
   9008 
   9009     /* Input parameter check. */
   9010     if (NULL == ent_p || NULL == dir) {
   9011         return (BCM_E_PARAM);
   9012     }
   9013 
   9014     BCM_IF_ERROR_RETURN(_bcm_l2_station_control_get(unit, &sc));
   9015 
   9016     if (-1 != prev_null_index) {
   9017         rv = _bcm_l2_station_entry_move_check(unit, prev_null_index,
   9018                                               target_index, -1,
   9019                                               &shift_up_amount);
   9020         shift_up = BCM_SUCCESS(rv);
   9021     } else {
   9022         shift_up = FALSE;
   9023     }
   9024 
   9025     if (-1 != next_null_index) {
   9026         rv = _bcm_l2_station_entry_move_check(unit, next_null_index,
   9027                                               target_index, 1,
   9028                                               &shift_down_amount);
   9029         shift_down = BCM_SUCCESS(rv);
   9030     } else {
   9031         shift_down = FALSE;
   9032     }
   9033 
   9034     if (TRUE == shift_up) {
   9035         if (TRUE == shift_down) {
   9036             if (shift_up_amount < shift_down_amount) {
   9037                 *dir = -1;
   9038             } else {
   9039                 *dir = 1;
   9040             }
   9041         } else {
   9042             *dir = -1;
   9043         }
   9044     } else {
   9045         if (TRUE == shift_down) {
   9046             *dir = 1;
   9047         } else {
   9048             return FALSE;
   9049         }
   9050     }
   9051     return TRUE;
   9052 }
   9053 
   9054 /*
   9055  * Function:
   9056  *     _bcm_l2_station_entry_move
   9057  * Purpose:
   9058  *     Move a station entry by a specified amount.
   9059  * Parameters:
   9060  *     unit     - (IN) BCM device number
   9061  *     s_ent    - (IN) Station entry pointer.
   9062  *     amount   - (IN) Direction in which entries need to be moved.
   9063  * Returns:
   9064  *     BCM_E_XXX
   9065  */
   9066 STATIC int
   9067 _bcm_l2_station_entry_move(int unit,
   9068                            _bcm_l2_station_entry_t *s_ent,
   9069                            int amount)
   9070 {
   9071     _bcm_l2_station_control_t   *sc;          /* Station control structure. */
   9072     _bcm_l2_station_entry_t   **entry_arr;    /* Station entry pointer . */
   9073     int                         tcam_idx_old; /* Original entry TCAM index. */
   9074     int                         tcam_idx_new; /* Entry new TCAM index.      */
   9075     int                         rv;           /* Operation return status.   */
   9076     soc_mem_t                   tcam_mem;     /* TCAM memory name.          */
   9077     uint32                      entry[SOC_MAX_MEM_FIELD_WORDS]; /* Entry    */
   9078                                                                 /* buffer.  */
   9079     int                         count;
   9080     int                         overlay;
   9081     /* Input parameter check. */
   9082     if (NULL == s_ent) {
   9083         return (BCM_E_PARAM);
   9084     }
   9085 
   9086     /* Input parameter check. */
   9087     if (0 == amount) {
   9088         return (BCM_E_NONE);
   9089     }
   9090 
   9091     BCM_IF_ERROR_RETURN(_bcm_l2_station_control_get(unit, &sc));
   9092 
   9093     tcam_idx_old =  s_ent->hw_index;
   9094 
   9095     tcam_idx_new = tcam_idx_old + (amount);
   9096 
   9097     LOG_DEBUG(BSL_LS_BCM_L2,
   9098               (BSL_META_U(unit,
   9099                           "L2(unit %d) Info: (SID=%d) move (oidx=%d nidx=%d) (amt=%d).\n"),
   9100                unit, s_ent->sid, s_ent->hw_index, tcam_idx_new, amount));
   9101 
   9102 #ifdef BCM_RIOT_SUPPORT
   9103     if (_BCM_L2_STATION_ID_OVERLAY(s_ent->sid)) {
   9104         overlay = _BCM_L2_STATION_ENTRY_OVERLAY;
   9105         count = sc->entries_total_2;
   9106         entry_arr = (sc->entry_arr_2);
   9107     } else
   9108 #endif /* BCM_RIOT_SUPPORT */
   9109     {
   9110         overlay = _BCM_L2_STATION_ENTRY_UNDERLAY;
   9111         count = sc->entries_total;
   9112         entry_arr = (sc->entry_arr);
   9113     }
   9114 
   9115     if (tcam_idx_old < 0 || tcam_idx_old >= count) {
   9116         return (BCM_E_PARAM);
   9117     }
   9118 
   9119     rv = _bcm_l2_station_tcam_mem_get(unit, overlay, &tcam_mem);
   9120     if (BCM_FAILURE(rv)) {
   9121         return (rv);
   9122     }
   9123 
   9124     if (s_ent->flags & _BCM_L2_STATION_ENTRY_INSTALLED) {
   9125         /* Clear entry buffer. */
   9126         sal_memset(entry, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32));
   9127 
   9128         rv = soc_mem_read(unit, tcam_mem, MEM_BLOCK_ANY, tcam_idx_old, entry);
   9129         BCM_IF_ERROR_RETURN(rv);
   9130 
   9131         rv = soc_mem_write(unit, tcam_mem, MEM_BLOCK_ALL, tcam_idx_new, entry);
   9132         BCM_IF_ERROR_RETURN(rv);
   9133 
   9134         rv = soc_mem_write(unit, tcam_mem, MEM_BLOCK_ALL, tcam_idx_old,
   9135                            soc_mem_entry_null(unit, tcam_mem));
   9136         BCM_IF_ERROR_RETURN(rv);
   9137 #ifdef BCM_TRIDENT3_SUPPORT
   9138         if (SOC_IS_TRIDENT3X(unit) && (!soc_feature(unit, soc_feature_riot))) {
   9139             if (tcam_mem == MY_STATION_TCAMm) {
   9140                 tcam_mem = MY_STATION_TCAM_2m;
   9141                 rv = soc_mem_write(unit, tcam_mem, MEM_BLOCK_ALL, tcam_idx_new, entry);
   9142                 BCM_IF_ERROR_RETURN(rv);
   9143 
   9144                 rv = soc_mem_write(unit, tcam_mem, MEM_BLOCK_ALL, tcam_idx_old,
   9145                                    soc_mem_entry_null(unit, tcam_mem));
   9146                 BCM_IF_ERROR_RETURN(rv);
   9147             }
   9148         }
   9149 #endif
   9150     }
   9151 
   9152     if (FALSE == prio_with_no_free_entries) {
   9153         entry_arr[s_ent->hw_index] = NULL;
   9154     }
   9155 
   9156     entry_arr[tcam_idx_new] = s_ent;
   9157 
   9158     s_ent->hw_index = tcam_idx_new;
   9159 
   9160     return (BCM_E_NONE);
   9161 }
   9162 
   9163 /*
   9164  * Function:
   9165  *     _bcm_l2_station_entry_shift_down
   9166  * Purpose:
   9167  *     Shift entries down by one index to create a free entry at target
   9168  *     index location.
   9169  * Parameters:
   9170  *     unit             - (IN) BCM device number
   9171  *     target_index     - (IN) Target index for entry install operation.
   9172  *     next_null_index  - (IN) Location of free entry after target index.
   9173  * Returns:
   9174  *     BCM_E_XXX
   9175  */
   9176 STATIC int
   9177 _bcm_l2_station_entry_shift_down(int unit,
   9178                                  int overlay,
   9179                                  int target_index,
   9180                                  int next_null_index)
   9181 {
   9182     uint16                      empty_idx;   /* Empty index.               */
   9183     _bcm_l2_station_control_t   *sc;         /* Station control structure. */
   9184     _bcm_l2_station_entry_t     **entry_arr; /* Station entry pointer */
   9185     int                         tmp_idx1;    /* Temporary index.           */
   9186     int                         tmp_idx2;    /* Temporary index.           */ 
   9187     int                         max_entries; /* Maximum entries supported. */
   9188     int                         rv;          /* Operation return status.   */
   9189 
   9190     LOG_DEBUG(BSL_LS_BCM_L2,
   9191               (BSL_META_U(unit,
   9192                           "L2(unit %d) Info: Shift UP (tidx=%d null-idx=%d).\n"),
   9193                unit, target_index, next_null_index));
   9194 
   9195     BCM_IF_ERROR_RETURN(_bcm_l2_station_control_get(unit, &sc));
   9196 
   9197     empty_idx = next_null_index;
   9198 
   9199 #ifdef BCM_RIOT_SUPPORT
   9200     if (overlay == _BCM_L2_STATION_ENTRY_OVERLAY) {
   9201         max_entries = sc->entries_total_2;
   9202         entry_arr = (sc->entry_arr_2);
   9203     } else
   9204 #endif /* BCM_RIOT_SUPPORT */
   9205     {
   9206         max_entries = sc->entries_total;
   9207         entry_arr = (sc->entry_arr);
   9208     }
   9209 
   9210     /*
   9211      * Move entries one step down
   9212      *     starting from the last entry
   9213      * IDEA: 
   9214      *     Move till empty_idx > target_index  
   9215      */
   9216     while (empty_idx > target_index) {
   9217         if (empty_idx == 0) {
   9218             tmp_idx1 = 0;
   9219             tmp_idx2 = max_entries - 1;
   9220             rv = _bcm_l2_station_entry_move(unit,
   9221                                             entry_arr[max_entries - 1],
   9222                                             (tmp_idx1 - tmp_idx2));
   9223             BCM_IF_ERROR_RETURN(rv);
   9224         } else {
   9225             tmp_idx1 = empty_idx;
   9226             tmp_idx2 = (empty_idx - 1);
   9227             rv = _bcm_l2_station_entry_move(unit,
   9228                                             entry_arr[empty_idx - 1],
   9229                                             (tmp_idx1 - tmp_idx2));
   9230             BCM_IF_ERROR_RETURN(rv);
   9231 
   9232             empty_idx--;
   9233         }
   9234     }
   9235     return (BCM_E_NONE);
   9236 }
   9237 
   9238 /*
   9239  * Function:
   9240  *     _bcm_l2_station_entry_shift_up
   9241  * Purpose:
   9242  *     Shift entries up by one index to create a free entry at target
   9243  *     index location.
   9244  * Parameters:
   9245  *     unit             - (IN) BCM device number
   9246  *     target_index     - (IN) Target index for entry install operation.
   9247  *     prev_null_index  - (IN) Location of free entry before target index.
   9248  * Returns:
   9249  *     BCM_E_XXX
   9250  */
   9251 STATIC int
   9252 _bcm_l2_station_entry_shift_up(int unit,
   9253                                int overlay,
   9254                                int target_index,
   9255                                int prev_null_index)
   9256 {
   9257     uint16                      empty_idx;   /* Empty index.               */
   9258     _bcm_l2_station_control_t   *sc;         /* Station control structure. */
   9259     _bcm_l2_station_entry_t     **entry_arr; /* Station entry pointer */
   9260     int                         tmp_idx1;    /* Temporary index.           */
   9261     int                         tmp_idx2;    /* Temporary index.           */ 
   9262     int                         max_entries; /* Maximum entries supported. */
   9263     int                         rv;          /* Operation return status.   */
   9264 
   9265     BCM_IF_ERROR_RETURN(_bcm_l2_station_control_get(unit, &sc));
   9266 
   9267     LOG_DEBUG(BSL_LS_BCM_L2,
   9268               (BSL_META_U(unit,
   9269                           "L2(unit %d) Info: Shift UP (tidx=%d null-idx=%d).\n"),
   9270                unit, target_index, prev_null_index));
   9271 
   9272     empty_idx = prev_null_index;
   9273 
   9274 #ifdef BCM_RIOT_SUPPORT
   9275     if (overlay == _BCM_L2_STATION_ENTRY_OVERLAY) {
   9276         max_entries = sc->entries_total_2;
   9277         entry_arr = (sc->entry_arr_2);
   9278     } else
   9279 #endif /* BCM_RIOT_SUPPORT */
   9280     {
   9281         max_entries = sc->entries_total;
   9282         entry_arr = (sc->entry_arr);
   9283     }
   9284 
   9285 
   9286     /*
   9287      * Move entries one step up
   9288      *     starting from the first entry
   9289      * IDEA: 
   9290      *     Move till empty_idx < target_index  
   9291      */
   9292     while (empty_idx < target_index) {
   9293         if (empty_idx == (max_entries - 1)) {
   9294             tmp_idx1 = max_entries - 1;
   9295             tmp_idx2 = 0;
   9296             rv = _bcm_l2_station_entry_move(unit,
   9297                                             entry_arr[0],
   9298                                             (tmp_idx1 - tmp_idx2));
   9299             BCM_IF_ERROR_RETURN(rv);
   9300             empty_idx = 0;
   9301         } else {
   9302             tmp_idx1 = empty_idx;
   9303             tmp_idx2 = (empty_idx + 1);
   9304             rv = _bcm_l2_station_entry_move(unit,
   9305                                             entry_arr[empty_idx + 1],
   9306                                             (tmp_idx1 - tmp_idx2));
   9307             BCM_IF_ERROR_RETURN(rv);
   9308 
   9309             empty_idx++;
   9310         }
   9311     }
   9312     return (BCM_E_NONE);
   9313 }
   9314 
   9315 /*
   9316  * Function:
   9317  *     _bcm_l2_station_entry_install
   9318  * Purpose:
   9319  *     Write a station entry to hardware
   9320  * Parameters:
   9321  *     unit     - (IN) BCM device number
   9322  *     ent_p    - (IN) Pointer to station entry.
   9323  * Returns:
   9324  *     BCM_E_XXX
   9325  */
   9326 STATIC int
   9327 _bcm_l2_station_entry_install(int unit, _bcm_l2_station_entry_t *ent_p, uint32 station_flags)
   9328 {
   9329     int     rv;         /* Operation return status. */ 
   9330     soc_mem_t tcam_mem; /* TCAM memory name.        */
   9331 
   9332     if (NULL == ent_p) {
   9333         return (BCM_E_PARAM);
   9334     }
   9335 
   9336 #ifdef BCM_TRIDENT3_SUPPORT
   9337     if (SOC_IS_TRIDENT3X(unit) && (station_flags & BCM_L2_STATION_FCOE)) {
   9338         tcam_mem = MY_STATION_TCAM_2m;
   9339     } else 
   9340 #endif /* BCM_TRIDENT3_SUPPORT */
   9341     {
   9342     rv = _bcm_l2_station_tcam_mem_get(unit,
   9343               _BCM_L2_STATION_ID_OVERLAY(ent_p->sid), &tcam_mem);
   9344     if (BCM_FAILURE(rv)) {
   9345         return (rv);
   9346     }
   9347     }
   9348 
   9349     if (NULL == ent_p->tcam_ent) {
   9350         return (BCM_E_INTERNAL);
   9351     }
   9352 
   9353     LOG_DEBUG(BSL_LS_BCM_L2,
   9354               (BSL_META_U(unit,
   9355                           "L2(unit %d) Info: (SID=%d) - install (idx=%d).\n"),
   9356                unit, ent_p->sid, ent_p->hw_index));
   9357 
   9358     rv = soc_mem_write(unit, tcam_mem, MEM_BLOCK_ALL, ent_p->hw_index,
   9359                        ent_p->tcam_ent);
   9360 #ifdef BCM_TRIDENT3_SUPPORT
   9361     if (SOC_IS_TRIDENT3X(unit) && (!soc_feature(unit, soc_feature_riot))) {
   9362         BCM_IF_ERROR_RETURN(rv);
   9363         if (tcam_mem == MY_STATION_TCAMm) {
   9364             tcam_mem = MY_STATION_TCAM_2m;
   9365             rv = soc_mem_write(unit, tcam_mem, MEM_BLOCK_ALL, ent_p->hw_index,
   9366                        ent_p->tcam_ent);
   9367         }
   9368     }
   9369 #endif
   9370     sal_free(ent_p->tcam_ent);
   9371 
   9372     ent_p->tcam_ent = NULL;
   9373 
   9374     return (rv);
   9375 }
   9376 
   9377 /*
   9378  * Function:
   9379  *     _bcm_l2_station_entry_prio_install
   9380  * Purpose:
   9381  *     Install an entry based on priority value.
   9382  * Parameters:
   9383  *     unit     - (IN) BCM device number
   9384  *     ent_p    - (IN) Pointer to station entry.
   9385  * Returns:
   9386  *     BCM_E_XXX
   9387  */
   9388 STATIC int
   9389 _bcm_l2_station_entry_prio_install(int unit, _bcm_l2_station_entry_t *ent_p, uint32 station_flags)
   9390 {
   9391     _bcm_l2_station_control_t  *sc;                /* Control structure.     */
   9392     _bcm_l2_station_entry_t  **entry_arr;          /* L2 station entry       */
   9393     int                        idx_old;            /* Entry old TCAM index.  */
   9394     int                        idx_target;         /* Entry target index.    */
   9395     int                        prev_null_idx = -1; /* Prev NULL entry index. */
   9396     int                        next_null_idx = -1; /* Next NULL entry index. */
   9397     int                        temp;               /* Temporary variable.    */
   9398     int                        dir = -1;           /* -1 = UP, 1 = DOWN      */
   9399     int                        decr_on_shift_up = TRUE; /* Shift up status   */
   9400     int                        rv;                 /* Return status.         */
   9401     int                        flag_no_free_entries = FALSE; /* No free      */
   9402                                                    /* entries status         */
   9403     int                        max_entries; 
   9404     int                        free_entries; 
   9405     int                        overlay;
   9406     prio_with_no_free_entries = FALSE;
   9407 
   9408     BCM_IF_ERROR_RETURN(_bcm_l2_station_control_get(unit, &sc));
   9409 #if defined(BCM_KATANA2_SUPPORT) || defined(BCM_TRIDENT2PLUS_SUPPORT)
   9410     if ((SOC_IS_KATANA2(unit) || 
   9411             soc_feature(unit, soc_feature_fp_based_oam)) && 
   9412         (ent_p->flags & _BCM_L2_STATION_ENTRY_TYPE_NON_TCAM)) {
   9413         return BCM_E_NONE;  
   9414     }
   9415 #endif
   9416 
   9417     if ((ent_p->flags & _BCM_L2_STATION_ENTRY_PRIO_NO_CHANGE)
   9418         || (FALSE == _bcm_l2_station_prio_move_required(unit, ent_p))) {
   9419         goto end;
   9420     }
   9421 
   9422     idx_old = ent_p->hw_index;
   9423 
   9424 #ifdef BCM_RIOT_SUPPORT
   9425     if (_BCM_L2_STATION_ID_OVERLAY(ent_p->sid)) {
   9426         overlay = _BCM_L2_STATION_ENTRY_OVERLAY;
   9427         max_entries = sc->entries_total_2;
   9428         entry_arr = (sc->entry_arr_2);
   9429         free_entries = sc->entries_free_2;
   9430     } else
   9431 #endif /* BCM_RIOT_SUPPORT */
   9432     {
   9433         overlay = _BCM_L2_STATION_ENTRY_UNDERLAY;
   9434         max_entries = sc->entries_total;
   9435         entry_arr = (sc->entry_arr);
   9436         free_entries  = sc->entries_free;
   9437     }
   9438 
   9439     if (idx_old >= max_entries) {
   9440         return (BCM_E_INTERNAL);
   9441     }
   9442 
   9443     if (0 == free_entries) {
   9444         if (0 == (ent_p->flags & _BCM_L2_STATION_ENTRY_INSTALLED)) {
   9445             entry_arr[ent_p->hw_index] = NULL;
   9446             flag_no_free_entries = TRUE;
   9447         } else {
   9448             return (BCM_E_CONFIG);
   9449         }
   9450     }
   9451 
   9452     for (idx_target = 0; idx_target < max_entries; idx_target++) {
   9453 
   9454         /* Skip the entry itself. */
   9455         if (ent_p == entry_arr[idx_target]) {
   9456             continue;
   9457         }
   9458 
   9459         if (NULL == entry_arr[idx_target]) {
   9460             /* Store the null slot index. */
   9461             prev_null_idx = idx_target;
   9462             continue;
   9463         }
   9464 
   9465         if (_bcm_l2_station_entry_prio_cmp
   9466             (ent_p->prio, entry_arr[idx_target]->prio) > 0) {
   9467             /* Found the entry with priority lower than ent_p prio. */
   9468             break;
   9469         }
   9470     }
   9471 
   9472     temp = idx_target;
   9473 
   9474     if (idx_target != (max_entries - 1)) {
   9475         /*  Find next empty slot after ent_p. */
   9476         for (; temp < max_entries; temp++) {
   9477             if (NULL == entry_arr[temp]) {
   9478                 next_null_idx = temp;
   9479                 break;
   9480             }
   9481         }
   9482     }
   9483 
   9484     /* Put the entry back. */
   9485     if (TRUE == flag_no_free_entries) {
   9486         entry_arr[ent_p->hw_index] = ent_p;
   9487     }
   9488 
   9489     /* No empty slot found. */
   9490     if (-1 == prev_null_idx && -1 == next_null_idx) {
   9491         return (BCM_E_CONFIG);
   9492     }
   9493 
   9494     if (idx_target == max_entries) {
   9495         /* Target location is after the last installed entry. */
   9496         if (prev_null_idx == (max_entries - 1)) {
   9497             idx_target = prev_null_idx;
   9498             goto only_move;
   9499         } else {
   9500             idx_target = (max_entries - 1);
   9501             decr_on_shift_up = FALSE;
   9502         }
   9503     }
   9504 
   9505     if (FALSE
   9506         == _bcm_l2_station_entry_dir_get(unit,
   9507                                          ent_p,
   9508                                          prev_null_idx,
   9509                                          next_null_idx,
   9510                                          idx_target,
   9511                                          &dir)) {
   9512         return (BCM_E_PARAM);
   9513     }
   9514 
   9515     if (1 == dir) {
   9516         /* 
   9517          * Move the entry at the target index to target_index+1. This may
   9518          * mean shifting more entries down to make room. In other words,
   9519          * shift the target index and any that follow it down 1 as far as the
   9520          * next empty index.
   9521          */
   9522         if (NULL != entry_arr[idx_target]) {
   9523             BCM_IF_ERROR_RETURN
   9524                 (_bcm_l2_station_entry_shift_down(unit,
   9525                                                   overlay,
   9526                                                   idx_target,
   9527                                                   next_null_idx));
   9528         }
   9529     } else {
   9530         if (TRUE == decr_on_shift_up) {
   9531             idx_target--;
   9532             LOG_DEBUG(BSL_LS_BCM_L2,
   9533                       (BSL_META_U(unit,
   9534                                   "L2(unit %d) Info: Decr. on Shift UP (idx_tgt=%d).\n"),
   9535                        unit, idx_target));
   9536         }
   9537         if (NULL != entry_arr[idx_target]) {
   9538             /* coverity[negative_returns] */
   9539             BCM_IF_ERROR_RETURN
   9540                 (_bcm_l2_station_entry_shift_up(unit,
   9541                                                 overlay,
   9542                                                 idx_target,
   9543                                                 prev_null_idx));
   9544         }
   9545     }
   9546 
   9547     /* Move the entry from old index to new index. */
   9548 only_move:
   9549     if (0 != (idx_target - ent_p->hw_index)) {
   9550 
   9551         if (TRUE == flag_no_free_entries) {
   9552             prio_with_no_free_entries = TRUE;
   9553         }
   9554 
   9555         rv = _bcm_l2_station_entry_move(unit,
   9556                                         ent_p,
   9557                                         (idx_target - ent_p->hw_index));
   9558         if (BCM_FAILURE(rv)) {
   9559             prio_with_no_free_entries = FALSE;
   9560             return (rv);
   9561         }
   9562 
   9563         prio_with_no_free_entries = FALSE;
   9564     }
   9565 
   9566 end:
   9567 
   9568     ent_p->flags &= ~_BCM_L2_STATION_ENTRY_PRIO_NO_CHANGE;
   9569 
   9570     rv = _bcm_l2_station_entry_install(unit, ent_p, station_flags);
   9571     if (BCM_FAILURE(rv)) {
   9572         return rv;
   9573     }
   9574     return (BCM_E_NONE);
   9575 }
   9576 
   9577 
   9578 /*
   9579  * Function:
   9580  *     _bcm_tr_l2_station_entry_parse
   9581  * Purpose:
   9582  *     Get station information from H/W format.
   9583  * Parameters:
   9584  *     unit         - (IN) BCM device number
   9585  *     tcam_mem     - (IN) TCAM memory name.
   9586  *     station      - (IN/OUT) Station entry lookup information.
   9587  * Returns:
   9588  *     BCM_E_XXX
   9589  */
   9590 STATIC int
   9591 _bcm_tr_l2_station_tcam_entry_parse(int unit, soc_mem_t tcam_mem, uint32 *entry,
   9592                                         bcm_l2_station_t *station)
   9593 {
   9594 #ifdef BCM_RIOT_SUPPORT
   9595     int                         overlay = 0; /* Overlay/Underlay indicator */
   9596 #endif /* BCM_RIOT_SUPPORT */
   9597 
   9598     /* Input parameter check. */
   9599     if (tcam_mem != MY_STATION_TCAMm
   9600         && tcam_mem != MY_STATION_TCAM_2m
   9601         && tcam_mem != MPLS_STATION_TCAMm) {
   9602         return (BCM_E_PARAM);
   9603     }
   9604 
   9605     if (NULL == entry) {
   9606         return (BCM_E_PARAM);
   9607     }
   9608 
   9609     if (NULL == station) {
   9610         return (BCM_E_PARAM);
   9611     }
   9612 
   9613     soc_mem_mac_addr_get(unit, tcam_mem, entry,
   9614                          MAC_ADDRf, station->dst_mac);
   9615 
   9616     soc_mem_mac_addr_get(unit, tcam_mem, entry,
   9617                          MAC_ADDR_MASKf, station->dst_mac_mask);
   9618 
   9619 #ifdef BCM_RIOT_SUPPORT
   9620     if (tcam_mem == MY_STATION_TCAM_2m) {
   9621         overlay = soc_mem_field32_get(unit, tcam_mem, entry,
   9622                                       FORWARDING_FIELD_TYPEf);
   9623     }
   9624 
   9625     if (overlay) {
   9626         int vfi = 0;
   9627         int vfi_mask = 0;
   9628 
   9629         vfi = soc_mem_field32_get(unit, tcam_mem, entry, VFI_IDf);
   9630         _BCM_VPN_SET(station->vlan, _BCM_VPN_TYPE_VFI, vfi);
   9631 
   9632         vfi_mask = soc_mem_field32_get(unit, tcam_mem, entry, VFI_ID_MASKf);
   9633         if (vfi_mask != 0) {
   9634             _BCM_VPN_SET(station->vlan_mask, _BCM_VPN_TYPE_VFI, vfi_mask);
   9635         }
   9636     } else
   9637 #endif /* BCM_RIOT_SUPPORT */
   9638     {
   9639 #ifdef BCM_RIOT_SUPPORT
   9640         if (soc_feature(unit, soc_feature_riot)) {
   9641             station->flags |= BCM_L2_STATION_UNDERLAY;
   9642         }
   9643 #endif
   9644         station->vlan
   9645             = soc_mem_field32_get(unit, tcam_mem, entry, VLAN_IDf);
   9646 
   9647         station->vlan_mask
   9648             = soc_mem_field32_get(unit, tcam_mem, entry, VLAN_ID_MASKf);
   9649     }
   9650 
   9651 #if defined(BCM_TRIDENT_SUPPORT)
   9652     if (SOC_IS_KATANAX(unit)
   9653         || SOC_IS_TRIDENT(unit)
   9654         || SOC_IS_TD2_TT2(unit)
   9655         || SOC_IS_TRIUMPH3(unit)) {
   9656         int src_field;
   9657         int src_mask_field;
   9658         int src_type = 0;
   9659         _bcm_gport_dest_t src;
   9660         _bcm_gport_dest_t src_mask;
   9661         int num_bits_for_port;
   9662 
   9663         _bcm_gport_dest_t_init(&src);
   9664         _bcm_gport_dest_t_init(&src_mask);
   9665 
   9666         if (SOC_MEM_FIELD_VALID(unit, tcam_mem, SOURCE_FIELDf)) {
   9667             src_field= soc_mem_field32_get(unit, tcam_mem, entry,
   9668                             SOURCE_FIELDf);
   9669             src_mask_field = soc_mem_field32_get(unit, tcam_mem, entry,
   9670                                   SOURCE_FIELD_MASKf);
   9671 
   9672             if (SOC_MEM_FIELD_VALID(unit, tcam_mem, SOURCE_TYPEf)) {
   9673                 src_type = soc_mem_field32_get(unit, tcam_mem, entry,
   9674                                                SOURCE_TYPEf);
   9675             }
   9676 
   9677 #ifdef BCM_RIOT_SUPPORT
   9678             if (soc_feature(unit, soc_feature_riot) && (src_type & 0x1)) {
   9679                 _bcm_vp_gport_dest_fill(unit, src_field, &src);
   9680                 src_mask.gport_type = src.gport_type;
   9681                 switch (src_mask.gport_type) {
   9682                     case _SHR_GPORT_TYPE_MPLS_PORT:
   9683                         src_mask.mpls_id = src_mask_field;
   9684                         break;
   9685                     case _SHR_GPORT_TYPE_MIM_PORT:
   9686                         src_mask.mim_id = src_mask_field;
   9687                         break;
   9688                     case _SHR_GPORT_TYPE_TRILL_PORT:
   9689                         src_mask.trill_id = src_mask_field;
   9690                         break;
   9691                     case _SHR_GPORT_TYPE_L2GRE_PORT:
   9692                         src_mask.l2gre_id = src_mask_field;
   9693                         break;
   9694                     case _SHR_GPORT_TYPE_VXLAN_PORT:
   9695                         src_mask.vxlan_id = src_mask_field;
   9696                         break;
   9697                     default:
   9698                         return BCM_E_PARAM;
   9699                 }
   9700             } else
   9701 #endif /* BCM_RIOT_SUPPORT */
   9702             if ((SOC_IS_KATANAX(unit) && (src_type & 0x1)) ||
   9703                     (src_field >> SOC_TRUNK_BIT_POS(unit)) & 0x1) {
   9704                 src.tgid = src_field & ((1 << SOC_TRUNK_BIT_POS(unit)) - 1);
   9705                 src.gport_type = _SHR_GPORT_TYPE_TRUNK;
   9706                 src_mask.tgid = src_mask_field &
   9707                     ((1 << SOC_TRUNK_BIT_POS(unit)) - 1);
   9708                 src_mask.gport_type = _SHR_GPORT_TYPE_TRUNK;
   9709             } else {
   9710                 src.port = src_field & SOC_PORT_ADDR_MAX(unit);
   9711                 src.modid = (src_field - src.port) /
   9712                                (SOC_PORT_ADDR_MAX(unit) + 1);
   9713                 src.gport_type = _SHR_GPORT_TYPE_MODPORT;
   9714                 num_bits_for_port = _shr_popcount(
   9715                                  (unsigned int)SOC_PORT_ADDR_MAX(unit));
   9716                 src_mask.port = src_mask_field & SOC_PORT_ADDR_MAX(unit);
   9717                 src_mask.gport_type = _SHR_GPORT_TYPE_MODPORT;
   9718                 src_mask.modid = (src_mask_field >> num_bits_for_port) &
   9719                                  SOC_MODID_MAX(unit);
   9720             }
   9721             if (BCM_GPORT_IS_SET(station->src_port)) {
   9722                 /* caller is expecting gport format*/
   9723                 BCM_IF_ERROR_RETURN(_bcm_esw_gport_construct(unit, &src,
   9724                                     &(station->src_port)));
   9725                 BCM_IF_ERROR_RETURN(_bcm_esw_gport_construct(unit, &src_mask,
   9726                                     &(station->src_port_mask)));
   9727             } else {
   9728                 /* only port and port_mask can be conveyed*/
   9729                 station->src_port      = src.port;
   9730                 station->src_port_mask = src_mask.port;
   9731             }
   9732         } else {
   9733             station->src_port
   9734                 = soc_mem_field32_get(unit, tcam_mem, entry,
   9735                                   ING_PORT_NUMf);
   9736             station->src_port_mask
   9737                 = soc_mem_field32_get(unit, tcam_mem, entry,
   9738                                   ING_PORT_NUM_MASKf);
   9739         }
   9740 
   9741         if (soc_mem_field_valid(unit, tcam_mem, MIM_TERMINATION_ALLOWEDf)) {
   9742             if (soc_mem_field32_get(unit, tcam_mem, entry,
   9743                                     MIM_TERMINATION_ALLOWEDf)) {
   9744                 station->flags |= BCM_L2_STATION_MIM;
   9745             }
   9746         }
   9747 
   9748         if (soc_mem_field_valid(unit, tcam_mem, MPLS_TERMINATION_ALLOWEDf)) {
   9749             if (soc_mem_field32_get(unit, tcam_mem, entry,
   9750                                     MPLS_TERMINATION_ALLOWEDf)) {
   9751                 station->flags |= BCM_L2_STATION_MPLS;
   9752             }
   9753         }
   9754 
   9755         if (soc_mem_field_valid(unit, tcam_mem, IPV4_TERMINATION_ALLOWEDf)) {
   9756             if (soc_mem_field32_get(unit, tcam_mem, entry,
   9757                                     IPV4_TERMINATION_ALLOWEDf)) {
   9758                 station->flags |= BCM_L2_STATION_IPV4;
   9759             }
   9760         }
   9761 
   9762         if (soc_mem_field_valid(unit, tcam_mem, IPV6_TERMINATION_ALLOWEDf)) {
   9763             if (soc_mem_field32_get(unit, tcam_mem, entry,
   9764                                     IPV6_TERMINATION_ALLOWEDf)) {
   9765                 station->flags |= BCM_L2_STATION_IPV6;
   9766             }
   9767         }
   9768 
   9769         if (soc_mem_field_valid(unit, tcam_mem, ARP_RARP_TERMINATION_ALLOWEDf)) {
   9770             if (soc_mem_field32_get(unit, tcam_mem, entry,
   9771                                     ARP_RARP_TERMINATION_ALLOWEDf)) {
   9772                 station->flags |= BCM_L2_STATION_ARP_RARP;
   9773             }
   9774         }
   9775 
   9776         if (soc_mem_field32_get(unit, tcam_mem, entry,
   9777                                 COPY_TO_CPUf)) {
   9778             station->flags |= BCM_L2_STATION_COPY_TO_CPU;
   9779         }
   9780     }
   9781 #endif
   9782 
   9783 #if defined(BCM_TRIDENT_SUPPORT)
   9784     if (SOC_IS_TRIDENT(unit)
   9785         || SOC_IS_TD2_TT2(unit)) {
   9786         if (soc_mem_field_valid(unit, tcam_mem, TRILL_TERMINATION_ALLOWEDf)) {
   9787             if (soc_mem_field32_get(unit, tcam_mem, entry,
   9788                                     TRILL_TERMINATION_ALLOWEDf)) {
   9789                 station->flags |= BCM_L2_STATION_TRILL;
   9790             }
   9791         }
   9792 
   9793         if (soc_mem_field_valid(unit, tcam_mem, FCOE_TERMINATION_ALLOWEDf)) {
   9794             if (soc_mem_field32_get(unit, tcam_mem, entry,
   9795                                     FCOE_TERMINATION_ALLOWEDf)) {
   9796                 station->flags |= BCM_L2_STATION_FCOE;
   9797             }
   9798         }
   9799     }
   9800 #endif
   9801 
   9802 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_HELIX5_SUPPORT)
   9803     if (SOC_IS_KATANAX(unit) || SOC_IS_TRIUMPH3(unit) ||
   9804         soc_feature(unit, soc_feature_hx5_oam_support)) {
   9805         if (soc_mem_field_valid(unit, tcam_mem, OAM_TERMINATION_ALLOWEDf)) {
   9806             if (soc_mem_field32_get(unit, tcam_mem, entry,
   9807                                     OAM_TERMINATION_ALLOWEDf)) {
   9808                 station->flags |= BCM_L2_STATION_OAM;
   9809             }
   9810         }
   9811     }
   9812 #endif
   9813 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_TRIDENT_SUPPORT)
   9814     if (SOC_IS_KATANAX(unit) || SOC_IS_TRIDENT(unit)
   9815         || SOC_IS_TD2_TT2(unit) || SOC_IS_TRIUMPH3(unit)) {
   9816 
   9817         if (soc_mem_field_valid(unit, tcam_mem, DISCARDf)) {
   9818             if (soc_mem_field32_get(unit, tcam_mem, entry, DISCARDf)) {
   9819                 station->flags |= BCM_L2_STATION_DISCARD;
   9820             }
   9821         }
   9822 
   9823     }
   9824 #endif
   9825 
   9826 #if defined(BCM_TRIDENT3_SUPPORT)
   9827     if (soc_feature(unit, soc_feature_mysta_profile)) {
   9828         uint32 mysta_profile_id = 0;
   9829         uint32 dest_type = 0;
   9830         my_station_profile_1_entry_t entry_prof;
   9831         soc_mem_t prof_mem =  INVALIDm;
   9832         int mem_no = 0;
   9833 
   9834         if (tcam_mem == MY_STATION_TCAM_2m) {
   9835             prof_mem = MY_STATION_PROFILE_2m;
   9836             mem_no = 1;
   9837         } else {
   9838             prof_mem = MY_STATION_PROFILE_1m;
   9839         }
   9840         mysta_profile_id = soc_mem_field32_dest_get(unit, tcam_mem, entry,
   9841             DESTINATIONf, &dest_type);
   9842         if (dest_type == SOC_MEM_FIF_DEST_MYSTA) {
   9843             if (BCM_E_NONE == _bcm_l2_mysta_profile_entry_get(unit, &entry_prof,
   9844                                     mem_no, mysta_profile_id)){
   9845                 _bcm_l2_mysta_entry_to_station(unit, &entry_prof, prof_mem,
   9846                     station);
   9847             }
   9848         }
   9849     }
   9850 #endif
   9851 
   9852 #if defined(BCM_TSN_SUPPORT)
   9853     if (soc_feature(unit, soc_feature_tsn_taf)) {
   9854         if (soc_mem_field_valid(unit, tcam_mem, TAF_GATE_ID_PROFILEf)) {
   9855             uint32 hw_profile_id;
   9856 
   9857             hw_profile_id = soc_mem_field32_get(unit, tcam_mem,
   9858                                                 entry, TAF_GATE_ID_PROFILEf);
   9859             if (0 != hw_profile_id) {
   9860                 bcm_tsn_pri_map_t sw_index;
   9861 
   9862                 BCM_IF_ERROR_RETURN(
   9863                     bcmi_esw_tsn_pri_map_map_id_get(
   9864                         unit, bcmTsnPriMapTypeTafGate,
   9865                         hw_profile_id, &sw_index));
   9866 
   9867                 station->taf_gate_primap = sw_index;
   9868             } else {
   9869                 station->taf_gate_primap = BCM_TSN_PRI_MAP_INVALID;
   9870             }
   9871         }
   9872     } else
   9873 #endif /* BCM_TSN_SUPPORT */
   9874     {
   9875         station->taf_gate_primap = BCM_TSN_PRI_MAP_INVALID;
   9876     }
   9877 
   9878     return (BCM_E_NONE);
   9879 }
   9880 
   9881 /*
   9882  * Function:
   9883  *     _bcm_l2_station_tcam_replica_find
   9884  * Purpose:
   9885  *     Find a replica entry from my station table. Assuming SC_LOCK has been taken.
   9886  * Parameters:
   9887  *     unit         - (IN) BCM device number
   9888  *     station      - (IN) Station information for lookup by hardware.
   9889  *     station_id   - (IN/OUT) Station entry ID / the id of existing station.
   9890  * Returns:
   9891  *      BCM_E_NONE            entry found
   9892  *      BCM_E_XXX
   9893  */
   9894 STATIC int
   9895 _bcm_l2_station_tcam_replica_find(int unit, bcm_l2_station_t *station, int *station_id)
   9896 {
   9897     _bcm_l2_station_control_t *sc;               /* Pointer to station        */
   9898                                                  /* control structure.        */
   9899     int                       rv = BCM_E_FAIL;   /* Operation return status.  */
   9900     uint32                    *tcam_buf = NULL;  /* Buffer to store TCAM      */
   9901                                                  /* table entries.            */
   9902     soc_mem_t                 tcam_mem;          /* Memory name.              */
   9903     int                       count;
   9904     _bcm_l2_station_entry_t   **entry_arr;
   9905     int                       index;             /* Table index iterator.     */
   9906     void                      *my_station_hw;   /* Table entry pointer.      */
   9907     uint32                    flags_care = BCM_L2_STATION_IPV4
   9908                                             | BCM_L2_STATION_IPV6
   9909                                             | BCM_L2_STATION_ARP_RARP
   9910                                             | BCM_L2_STATION_MPLS
   9911                                             | BCM_L2_STATION_MIM
   9912                                             | BCM_L2_STATION_TRILL
   9913                                             | BCM_L2_STATION_FCOE
   9914                                             | BCM_L2_STATION_OAM
   9915                                             | BCM_L2_STATION_COPY_TO_CPU
   9916                                             | BCM_L2_STATION_IPV4_MCAST
   9917                                             | BCM_L2_STATION_IPV6_MCAST
   9918                                             | BCM_L2_STATION_UNDERLAY
   9919                                             | BCM_L2_STATION_DISCARD;
   9920     int i;
   9921     bcm_l2_station_t station_entry;
   9922 #if defined(BCM_RIOT_SUPPORT)
   9923     int vfi_mask_zero = 0;
   9924 #endif
   9925 
   9926     if (station == NULL)
   9927     {
   9928         return (BCM_E_PARAM);
   9929     }
   9930 
   9931     BCM_IF_ERROR_RETURN(_bcm_l2_station_control_get(unit, &sc));
   9932 
   9933     rv = _bcm_l2_station_tcam_mem_get(unit, _BCM_L2_STATION_OVERLAY(station),
   9934                                       &tcam_mem);
   9935     BCM_IF_ERROR_RETURN(rv);
   9936 
   9937 #ifdef BCM_RIOT_SUPPORT
   9938         if (_BCM_L2_STATION_OVERLAY(station)) {
   9939             count = sc->entries_total_2;
   9940             entry_arr = (sc->entry_arr_2);
   9941         } else
   9942 #endif /* BCM_RIOT_SUPPORT */
   9943         {
   9944             count = sc->entries_total;
   9945             entry_arr = (sc->entry_arr);
   9946         }
   9947 
   9948     /* Allocate buffer to store the DMAed table entries. */
   9949     tcam_buf = soc_cm_salloc(unit, SOC_MAX_MEM_BYTES * count,
   9950                               "MY STATION TCAM buffer");
   9951     if (NULL == tcam_buf) {
   9952         return (BCM_E_MEMORY);
   9953     }
   9954     /* Initialize the entry buffer. */
   9955     sal_memset(tcam_buf, 0, SOC_MAX_MEM_BYTES * count);
   9956 
   9957     /* Read the table entries into the buffer. */
   9958     rv = soc_mem_read_range(unit, tcam_mem, MEM_BLOCK_ALL,
   9959                             0, (count - 1), tcam_buf);
   9960     if (BCM_FAILURE(rv)) {
   9961         goto cleanup;
   9962     }
   9963 
   9964 #if defined(BCM_RIOT_SUPPORT)
   9965     _BCM_VPN_SET(vfi_mask_zero, _BCM_VPN_TYPE_VFI, 0);
   9966 #endif
   9967     /* Iterate over the table entries. */
   9968     for (index = 0; index < count; index++) {
   9969         if (entry_arr[index] == NULL) {
   9970             continue;
   9971         }
   9972 
   9973         my_station_hw = soc_mem_table_idx_to_pointer(unit,
   9974                             tcam_mem, void*,
   9975                             tcam_buf, entry_arr[index]->hw_index);
   9976 
   9977         sal_memset(&station_entry, 0, sizeof(station_entry));
   9978         station_entry.src_port = station->src_port;
   9979         rv = _bcm_tr_l2_station_tcam_entry_parse(unit, tcam_mem, my_station_hw,
   9980                                                  &station_entry);
   9981         if (BCM_FAILURE(rv)) {
   9982             goto cleanup;
   9983         }
   9984 
   9985         /* check keys */
   9986         for (i = 0; i < sizeof(bcm_mac_t); i++) {
   9987             if ((station_entry.dst_mac[i] & station_entry.dst_mac_mask[i]) !=
   9988                 (station->dst_mac[i] & station->dst_mac_mask[i])) {
   9989                 break;
   9990             }
   9991         }
   9992         if (i < sizeof(bcm_mac_t)) {
   9993             continue;
   9994         }
   9995 
   9996         if (((station_entry.vlan & station_entry.vlan_mask) !=
   9997             (station->vlan & station->vlan_mask)
   9998 #if defined(BCM_RIOT_SUPPORT)
   9999             && !((station_entry.vlan_mask == 0) &&
  10000             (station->vlan_mask == vfi_mask_zero))) ||
  10001             ((station_entry.vlan_mask == 0) &&
  10002             ((station->vlan_mask == 0)
  10003             || (station->vlan_mask == vfi_mask_zero)) &&
  10004             (_BCM_VPN_VFI_IS_SET(station_entry.vlan)
  10005             != _BCM_VPN_VFI_IS_SET(station->vlan))
  10006 #endif
  10007             )) {
  10008             continue;
  10009         }
  10010         if ((station_entry.src_port & station_entry.src_port_mask) !=
  10011             (station->src_port & station->src_port_mask)) {
  10012             continue;
  10013         }
  10014 
  10015         /* check actions */
  10016         if ((station_entry.flags ^ station->flags) & flags_care) {
  10017             continue;
  10018         }
  10019 
  10020          /* entry exists */
  10021         if (station_id != NULL) {
  10022             *station_id = entry_arr[index]->sid;
  10023         }
  10024         rv = BCM_E_NONE;
  10025         break;
  10026     }
  10027 
  10028     if (index == count) {
  10029         rv = BCM_E_FAIL;
  10030     }
  10031 
  10032 cleanup:
  10033     if (tcam_buf) {
  10034         soc_cm_sfree(unit, tcam_buf);
  10035     }
  10036 
  10037     return (rv);
  10038 }
  10039 
  10040 
  10041 /*
  10042  * Function:
  10043  *     _bcm_l2_station_param_check
  10044  * Purpose:
  10045  *     Validate L2 station user input parameters.
  10046  * Parameters:
  10047  *     unit         - (IN) BCM device number
  10048  *     station      - (IN) Station information for lookup by hardware.
  10049  *     station_id   - (IN) Station entry ID.
  10050  * Returns:
  10051  *     BCM_E_XXX
  10052  */
  10053 STATIC int
  10054 _bcm_l2_station_param_check(int unit, bcm_l2_station_t *station, int station_id)
  10055 {
  10056     soc_mem_t tcam_mem; /* Hardware table name.     */
  10057 
  10058     /* Input parameter check. */
  10059     if (NULL == station) {
  10060         return (BCM_E_PARAM);
  10061     }
  10062 
  10063 #ifdef BCM_RIOT_SUPPORT
  10064     if (!soc_feature(unit, soc_feature_riot)) {
  10065         if ((_BCM_VPN_VFI_IS_SET(station->vlan))) {
  10066             return (BCM_E_PARAM);
  10067         }
  10068     }
  10069 #endif /* BCM_RIOT_SUPPORT */
  10070 
  10071     if ((SOC_IS_ENDURO(unit) || SOC_IS_TRIUMPH(unit)
  10072         || SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit)
  10073         || SOC_IS_VALKYRIE(unit) || SOC_IS_VALKYRIE2(unit)
  10074         || SOC_IS_HURRICANE(unit) || SOC_IS_HURRICANE2(unit))
  10075         && (_BCM_L2_STATION_TERM_FLAGS_MASK & station->flags)) {
  10076         return (BCM_E_UNAVAIL);
  10077     }
  10078 
  10079     /* Check allowed L2 station flag options */
  10080     if (soc_feature(unit, soc_feature_gh2_my_station) && 
  10081         (~_BCM_GH2_L2_STATION_FLAGS_MASK & station->flags)) {
  10082         return (BCM_E_UNAVAIL);
  10083     }
  10084 
  10085     if ((station->flags & BCM_L2_STATION_FCOE)
  10086         && (!SOC_IS_TRIDENT(unit) && !SOC_IS_TD2_TT2(unit))) {
  10087         /* FCoE Termination is support only on Trident family. */
  10088         return (BCM_E_UNAVAIL);
  10089     }
  10090 
  10091     if ((station->flags & BCM_L2_STATION_COPY_TO_CPU)
  10092         && (!SOC_IS_KATANAX(unit) && !SOC_IS_TRIUMPH3(unit) &&
  10093             !SOC_IS_TRIDENT(unit) && !SOC_IS_TD2_TT2(unit) &&
  10094             !soc_feature(unit, soc_feature_gh2_my_station))) {
  10095         return (BCM_E_UNAVAIL);
  10096     }
  10097 #if defined (BCM_OLP_SUPPORT)
  10098     if(soc_feature(unit, soc_feature_olp) &&
  10099        ((station->flags & BCM_L2_STATION_OAM) ||
  10100         (station->flags & BCM_L2_STATION_OLP) ||
  10101         (station->flags & BCM_L2_STATION_XGS_MAC))) {
  10102         if (_BCM_SWITCH_OLP_APIV(unit) == _BCM_SWITCH_OLP_TRUE_API) {
  10103             if (station->flags & BCM_L2_STATION_OAM) {
  10104                 LOG_VERBOSE(BSL_LS_BCM_L2,
  10105                         (BSL_META_U(unit,
  10106                                     "use bcmPortControlPortMacOui \n")));
  10107             } else {
  10108                 LOG_VERBOSE(BSL_LS_BCM_L2,
  10109                         (BSL_META_U(unit,
  10110                                     "use bcm_switch_olp_l2_addr_xxx API\n")));
  10111             }
  10112             return BCM_E_UNAVAIL;
  10113         }
  10114         _BCM_SWITCH_OLP_APIV_SET(unit, _BCM_SWITCH_OLP_L2_STATION_API);
  10115     }
  10116 #endif
  10117 
  10118     if ((station->flags & BCM_L2_STATION_OAM)
  10119         && (!SOC_IS_KATANAX(unit) && !SOC_IS_TRIUMPH3(unit) &&
  10120         !soc_feature(unit, soc_feature_fp_based_oam) &&
  10121         !soc_feature(unit, soc_feature_gh2_my_station))
  10122 #if defined(BCM_HELIX5_SUPPORT)
  10123         && (!soc_feature(unit, soc_feature_hx5_oam_support))
  10124 #endif
  10125        ) {
  10126 
  10127         return (BCM_E_UNAVAIL);
  10128     }
  10129     /* OLP/XGS STATION should not have overlay flag set */
  10130     if (soc_feature(unit, soc_feature_fp_based_oam) &&
  10131         ((station->flags & BCM_L2_STATION_OLP) ||
  10132             (station->flags & BCM_L2_STATION_XGS_MAC)) &&
  10133             _BCM_L2_STATION_OVERLAY(station)) {
  10134         return (BCM_E_PARAM);
  10135     }                   
  10136 
  10137 #ifdef BCM_RIOT_SUPPORT
  10138     if (station->flags & BCM_L2_STATION_WITH_ID) {
  10139         if (_BCM_L2_STATION_OVERLAY(station)) {
  10140             if ((station_id < _BCM_L2_STATION_ID_2_BASE) ||
  10141                 (station_id > _BCM_L2_STATION_ID_2_MAX)) {
  10142                 return (BCM_E_PARAM);
  10143             }
  10144         } else {
  10145             if ((station_id < _BCM_L2_STATION_ID_BASE) ||
  10146                 (station_id > _BCM_L2_STATION_ID_MAX)) {
  10147                 return (BCM_E_PARAM);
  10148             }
  10149         }
  10150     }
  10151 #endif /* BCM_RIOT_SUPPORT */
  10152 
  10153     if (((0 != station->src_port) || (0 != station->src_port_mask))
  10154         && (!SOC_IS_KATANAX(unit) && !SOC_IS_TRIDENT(unit)
  10155             && !SOC_IS_TD2_TT2(unit) && !SOC_IS_TRIUMPH3(unit)
  10156             && !soc_feature(unit, soc_feature_gh2_my_station))) {
  10157         /* Ingress Port match lookup not supported. */
  10158         return (BCM_E_UNAVAIL);
  10159     }
  10160 
  10161     /* In case of KT2  OAM, OLP and XGS MAC are not part of TCAM */
  10162     if ((SOC_IS_KATANA2(unit) || 
  10163          soc_feature(unit, soc_feature_fp_based_oam)) && 
  10164        ((station->flags & BCM_L2_STATION_OAM) || 
  10165           (station->flags & BCM_L2_STATION_OLP) || 
  10166           (station->flags & BCM_L2_STATION_XGS_MAC))) { 
  10167           return (BCM_E_NONE);
  10168     } else {
  10169 #ifdef BCM_RIOT_SUPPORT
  10170         if (_BCM_L2_STATION_OVERLAY(station)) {
  10171             int vfi;
  10172             int vfi_mask;
  10173 
  10174             /* vlan/vlan_mask is VFI or source_port/source_port_mask is vp
  10175              * are not possible because they can 'masked out' */
  10176             BCM_IF_ERROR_RETURN(_bcm_l2_station_tcam_mem_get(unit, 1, &tcam_mem));
  10177             if ((_BCM_VPN_VFI_IS_SET(station->vlan)
  10178                 != _BCM_VPN_VFI_IS_SET(station->vlan_mask)) && (station->vlan_mask)) {
  10179                 return (BCM_E_PARAM);
  10180             }
  10181 
  10182             if ((_BCM_VPN_VFI_IS_SET(station->vlan)) && (station->vlan)) {
  10183                 _BCM_VPN_GET(vfi, _BCM_VPN_TYPE_VFI, station->vlan);
  10184                 ParamCheck(unit, tcam_mem, VFI_IDf, vfi);
  10185             } else {
  10186                 ParamCheck(unit, tcam_mem, VLAN_IDf, station->vlan);
  10187             }
  10188 
  10189             if ((_BCM_VPN_VFI_IS_SET(station->vlan_mask)) && (station->vlan_mask)) {
  10190                 _BCM_VPN_GET(vfi_mask, _BCM_VPN_TYPE_VFI, station->vlan_mask);
  10191                 ParamCheck(unit, tcam_mem, VFI_ID_MASKf, vfi_mask);
  10192             } else {
  10193                 ParamCheck(unit, tcam_mem, VLAN_ID_MASKf, station->vlan_mask);
  10194             }
  10195 
  10196         } else
  10197 #endif /* BCM_RIOT_SUPPORT */
  10198         {
  10199             BCM_IF_ERROR_RETURN(_bcm_l2_station_tcam_mem_get(unit, 0, &tcam_mem));
  10200             ParamCheck(unit, tcam_mem, VLAN_IDf, station->vlan);
  10201             ParamCheck(unit, tcam_mem, VLAN_ID_MASKf, station->vlan_mask);
  10202         }
  10203 
  10204 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_GREYHOUND2_SUPPORT)
  10205        if (SOC_IS_KATANAX(unit)
  10206             || SOC_IS_TRIDENT(unit)
  10207             || SOC_IS_TD2_TT2(unit)
  10208             || SOC_IS_TRIUMPH3(unit)
  10209             || soc_feature(unit, soc_feature_gh2_my_station)) {
  10210            bcm_gport_t gport_id;
  10211            bcm_port_t port_out;
  10212            bcm_module_t mod_out;
  10213            bcm_trunk_t trunk_id;
  10214            uint32 mod_port_data = 0; /* concatenated modid and port */
  10215            int num_bits_for_port;
  10216 
  10217            if (GPORT_TYPE(station->src_port) != 
  10218                                   GPORT_TYPE(station->src_port_mask)) {
  10219                return BCM_E_PARAM;
  10220            }
  10221            num_bits_for_port = _shr_popcount(
  10222                                   (unsigned int)SOC_PORT_ADDR_MAX(unit));
  10223            if (BCM_GPORT_IS_SET(station->src_port)) {
  10224                BCM_IF_ERROR_RETURN(_bcm_esw_gport_resolve(unit, 
  10225                           station->src_port,
  10226                           &mod_out,
  10227                           &port_out, &trunk_id,
  10228                           &gport_id));
  10229                if (BCM_GPORT_IS_TRUNK(station->src_port)) {
  10230                    if (BCM_TRUNK_INVALID == trunk_id) {
  10231                        return BCM_E_PORT;
  10232                    }
  10233                    if (SOC_IS_KATANAX(unit) || 
  10234                        soc_feature(unit, soc_feature_gh2_my_station)) {
  10235                        mod_port_data = trunk_id;
  10236                    } else {
  10237                        mod_port_data = ((1 << SOC_TRUNK_BIT_POS(unit)) | trunk_id);
  10238                    }
  10239                }
  10240 #ifdef BCM_RIOT_SUPPORT
  10241                else if((gport_id != BCM_GPORT_INVALID) &&
  10242                        (_BCM_L2_STATION_OVERLAY(station))) {
  10243                    bcm_port_t port_mask = -1;
  10244                    bcm_module_t mod_mask = -1;
  10245                    bcm_trunk_t trunk_mask = -1;
  10246                    int gport_mask = -1;
  10247                    BCM_IF_ERROR_RETURN(
  10248                        _l2_port_mask_gport_resolve(unit, station->src_port_mask,
  10249                                                    &mod_mask, &port_mask,
  10250                                                    &trunk_mask, &gport_mask));
  10251                    ParamCheck(unit, tcam_mem, SOURCE_FIELD_MASKf, gport_mask);
  10252                    mod_port_data = gport_id;
  10253                }
  10254 #endif /* BCM_RIOT_SUPPORT */
  10255                else {
  10256                    if ((-1 == mod_out) || (-1 == port_out)) {
  10257                        return BCM_E_PORT;
  10258                    }
  10259                    mod_port_data = (mod_out << num_bits_for_port) | port_out;
  10260                }
  10261            } else {
  10262                int my_modid;
  10263                BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit,&my_modid));
  10264                port_out = station->src_port;
  10265                mod_port_data = station->src_port | 
  10266                                (my_modid << num_bits_for_port);
  10267            } 
  10268            if (SOC_MEM_FIELD_VALID(unit, tcam_mem, SOURCE_FIELDf)) {
  10269                ParamCheck(unit, tcam_mem, SOURCE_FIELDf, mod_port_data);
  10270            } else {
  10271                ParamCheck(unit, tcam_mem, ING_PORT_NUMf, port_out);
  10272            }
  10273         }
  10274 #endif
  10275     }
  10276     return (BCM_E_NONE);
  10277 }
  10278 
  10279 /*
  10280  * Function:
  10281  *     bcm_tr_l2_station_add
  10282  * Purpose:
  10283  *     Create an entry with specified ID or generated ID and install
  10284  *     the entry in hardware.
  10285  * Parameters:
  10286  *     unit         - (IN) BCM device number
  10287  *     station_id   - (IN/OUT) Station entry ID.
  10288  *     station      - (IN) Station information for lookup by hardware.
  10289  * Returns:
  10290  *     BCM_E_XXX
  10291  */
  10292 int
  10293 bcm_tr_l2_station_add(int unit,
  10294                       int *station_id,
  10295                       bcm_l2_station_t *station)
  10296 {
  10297     _bcm_l2_station_control_t *sc;         /* Control structure.       */
  10298     _bcm_l2_station_entry_t   *ent = NULL; /* Entry pointer.           */
  10299     int                       rv;          /* Operation return status. */
  10300     int                       sid = -1;    /* Entry ID.                */
  10301     /* Input parameter check. */
  10302     if (NULL == station || NULL == station_id)  {
  10303         return (BCM_E_PARAM);
  10304     }
  10305 
  10306     /* ID needs to be passed for replace operation. */
  10307     if ((station->flags & BCM_L2_STATION_REPLACE)
  10308         && !(station->flags & BCM_L2_STATION_WITH_ID)) {
  10309         return (BCM_E_PARAM);
  10310     }
  10311 #ifdef BCM_RIOT_SUPPORT
  10312     if(soc_feature(unit, soc_feature_riot) &&
  10313             soc_feature(unit, soc_feature_fp_based_oam) &&
  10314             ((station->flags & BCM_L2_STATION_OLP) ||
  10315              (station->flags & BCM_L2_STATION_XGS_MAC))) {
  10316         /* OLP/XGS STATION should go to tcam1 software database */
  10317         station->flags |= BCM_L2_STATION_UNDERLAY;
  10318      }               
  10319 #endif
  10320     rv = _bcm_l2_station_param_check(unit, station, *station_id);
  10321     if (BCM_FAILURE(rv)) {
  10322         return (BCM_E_PARAM);
  10323     }
  10324 
  10325     BCM_IF_ERROR_RETURN(_bcm_l2_station_control_get(unit, &sc));
  10326 
  10327     SC_LOCK(sc);
  10328 
  10329     if (SOC_IS_TRIDENT2PLUS(unit) || SOC_IS_APACHE(unit) || SOC_IS_TRIDENT3X(unit)) {
  10330         rv = _bcm_l2_station_tcam_replica_find(unit, station, &sid);
  10331         if (BCM_SUCCESS(rv)) {
  10332             if (!((station->flags & BCM_L2_STATION_WITH_ID) &&
  10333                   (station->flags & BCM_L2_STATION_REPLACE) &&
  10334                   (sid == *station_id))) {
  10335                 SC_UNLOCK(sc);
  10336                 rv = BCM_E_EXISTS;
  10337                 return (rv);
  10338             }
  10339         }
  10340     }
  10341 
  10342     if (station->flags & BCM_L2_STATION_WITH_ID) {
  10343         if ((sc->last_allocated_sid < *station_id) &&
  10344             (*station_id <= _BCM_L2_STATION_ID_MAX)) {
  10345             sc->last_allocated_sid = *station_id;
  10346         }
  10347         sid = *station_id;
  10348     } else {
  10349 
  10350 #ifdef BCM_RIOT_SUPPORT
  10351         if (_BCM_L2_STATION_OVERLAY(station)) {
  10352             sid = ++sc->last_allocated_sid_2;
  10353 
  10354             if (_BCM_L2_STATION_ID_2_MAX < sid) {
  10355                 sc->last_allocated_sid_2 = _BCM_L2_STATION_ID_2_MAX;
  10356 
  10357                 for (sid = _BCM_L2_STATION_ID_2_BASE;
  10358                      sid <= _BCM_L2_STATION_ID_2_MAX; sid++) {
  10359                     if (BCM_E_NOT_FOUND == 
  10360                             _bcm_l2_station_entry_get(unit, sid, &ent)) {
  10361                         break;
  10362                     }
  10363                 }
  10364             }
  10365         } else
  10366 #endif /* BCM_RIOT_SUPPORT */
  10367         {
  10368             sid = ++sc->last_allocated_sid;
  10369 
  10370             if (_BCM_L2_STATION_ID_MAX < sid) {
  10371                 sc->last_allocated_sid = _BCM_L2_STATION_ID_MAX;
  10372 
  10373                 for (sid = _BCM_L2_STATION_ID_BASE;
  10374                      sid <= _BCM_L2_STATION_ID_MAX; sid++) {
  10375                     if (BCM_E_NOT_FOUND == 
  10376                             _bcm_l2_station_entry_get(unit, sid, &ent)) {
  10377                         break;
  10378                     }
  10379                 }
  10380             }
  10381         }
  10382 
  10383         *station_id = sid;
  10384     }
  10385 
  10386     rv = _bcm_l2_station_entry_get(unit, sid, &ent);
  10387 
  10388     /* For replace operation, entry must exist. */
  10389     if (BCM_FAILURE(rv)
  10390         && (station->flags & BCM_L2_STATION_REPLACE)) {
  10391         LOG_ERROR(BSL_LS_BCM_L2,
  10392                   (BSL_META_U(unit,
  10393                               "L2(unit %d) Error: Replace (SID=%d) - Invalid (%s).\n"),
  10394                    unit, sid, bcm_errmsg(rv)));
  10395         SC_UNLOCK(sc);
  10396         return (rv);
  10397     }
  10398 
  10399     /* For non-replace operations, entry must not exist. */
  10400     if (BCM_SUCCESS(rv)
  10401         && (0 == (station->flags & BCM_L2_STATION_REPLACE))) {
  10402         LOG_INFO(BSL_LS_BCM_L2,
  10403                   (BSL_META_U(unit,
  10404                               "L2(unit %d) Error: (SID=%d) add - failed (%s).\n"),
  10405                    unit, sid, bcm_errmsg(rv)));
  10406         SC_UNLOCK(sc);
  10407         return (BCM_E_EXISTS);
  10408     }
  10409 
  10410     if (0 == (station->flags & BCM_L2_STATION_REPLACE)) {
  10411         rv = _bcm_l2_station_entry_create(unit, sid, station, &ent);
  10412         if (BCM_FAILURE(rv)) {
  10413             LOG_INFO(BSL_LS_BCM_L2,
  10414                       (BSL_META_U(unit,
  10415                                   "L2(unit %d) Error: Station (SID=%d) add - failed (%s).\n"),
  10416                        unit, sid, bcm_errmsg(rv)));
  10417             SC_UNLOCK(sc);
  10418             return (rv);
  10419         }
  10420     } else {
  10421         rv = _bcm_l2_station_entry_update(unit, sid, station, ent);
  10422         if (BCM_FAILURE(rv)) {
  10423             LOG_ERROR(BSL_LS_BCM_L2,
  10424                       (BSL_META_U(unit,
  10425                                   "L2(unit %d) Error: Station (SID=%d) update - failed (%s).\n"),
  10426                        unit, sid, bcm_errmsg(rv)));
  10427             SC_UNLOCK(sc);
  10428             return (rv);
  10429         }
  10430     }
  10431 
  10432     rv = _bcm_l2_station_entry_prio_install(unit, ent, station->flags);
  10433     if (BCM_FAILURE(rv)) {
  10434         if (NULL != ent->tcam_ent) {
  10435             sal_free(ent->tcam_ent);
  10436         }
  10437         LOG_ERROR(BSL_LS_BCM_L2,
  10438                   (BSL_META_U(unit,
  10439                               "L2(unit %d) Error: (SID=%d) install - failed (%s).\n"),
  10440                    unit, sid, bcm_errmsg(rv)));
  10441         SC_UNLOCK(sc);
  10442         return (rv);
  10443     }
  10444 
  10445     /* Mark the entry as installed. */
  10446     ent->flags |= _BCM_L2_STATION_ENTRY_INSTALLED;
  10447 
  10448     SC_UNLOCK(sc);
  10449     return (rv);
  10450 }
  10451 
  10452 /*
  10453  * Function:
  10454  *     bcm_tr_l2_station_delete
  10455  * Purpose:
  10456  *     Deallocate the memory used to track an entry and remove the entry
  10457  *     from hardware.
  10458  * Parameters:
  10459  *     unit         - (IN) BCM device number
  10460  *     station_id   - (IN) Station entry ID.
  10461  * Returns:
  10462  *     BCM_E_XXX
  10463  */
  10464 int
  10465 bcm_tr_l2_station_delete(int unit, int station_id)
  10466 {
  10467     _bcm_l2_station_entry_t     *s_ent = NULL; /* Entry pointer.           */
  10468     _bcm_l2_station_entry_t     **entry_arr = NULL; /* Entry pointer.      */
  10469     _bcm_l2_station_control_t   *sc = NULL;    /* Control structure.       */
  10470     int                         rv;            /* Operation return status. */
  10471     int                         overlay;       /* MY_STATION_2 entry.      */
  10472     soc_mem_t                   tcam_mem;      /* TCMA memory name.        */
  10473 
  10474 #if defined(BCM_TRIUMPH_SUPPORT)
  10475     my_station_tcam_entry_t     entry;
  10476 #endif
  10477 
  10478     BCM_IF_ERROR_RETURN(_bcm_l2_station_control_get(unit, &sc));
  10479 
  10480     SC_LOCK(sc);
  10481 
  10482     /* Get the entry by ID. */
  10483     rv = _bcm_l2_station_entry_get(unit, station_id, &s_ent);
  10484     if (BCM_FAILURE(rv)) {
  10485         SC_UNLOCK(sc);
  10486         return (rv);
  10487     }
  10488 #if defined(BCM_KATANA2_SUPPORT) || defined(BCM_TRIDENT2PLUS_SUPPORT)
  10489     if ((SOC_IS_KATANA2(unit) || 
  10490                 soc_feature(unit, soc_feature_fp_based_oam)) &&
  10491             (s_ent->flags & _BCM_L2_STATION_ENTRY_TYPE_NON_TCAM)) {
  10492         rv = _bcm_l2_station_non_tcam_entry_delete(unit, sc, s_ent, station_id);
  10493         /* Free the entry. */
  10494         sal_free(s_ent);
  10495         SC_UNLOCK(sc);
  10496         return rv;
  10497     }  
  10498 #endif
  10499 
  10500 #ifdef BCM_RIOT_SUPPORT
  10501     if (_BCM_L2_STATION_ID_OVERLAY(s_ent->sid)) {
  10502         overlay = _BCM_L2_STATION_ENTRY_OVERLAY;
  10503         entry_arr = (sc->entry_arr_2);
  10504     } else
  10505 #endif /* BCM_RIOT_SUPPORT */
  10506     {
  10507         overlay = _BCM_L2_STATION_ENTRY_UNDERLAY;
  10508         entry_arr = (sc->entry_arr);
  10509     }
  10510 
  10511     /* Get the TCAM memory name. */
  10512     rv = _bcm_l2_station_tcam_mem_get(unit, overlay, &tcam_mem);
  10513     if (BCM_FAILURE(rv)) {
  10514         SC_UNLOCK(sc);
  10515         return (rv);
  10516     }
  10517 
  10518 #if defined(BCM_TRIUMPH_SUPPORT)
  10519     if (soc_feature(unit, soc_feature_mysta_profile)) {
  10520         uint32 mysta_profile_id = 0;
  10521         uint32 dest_type = SOC_MEM_FIF_DEST_INVALID;
  10522 
  10523         rv = soc_mem_read(unit, tcam_mem, MEM_BLOCK_ANY, s_ent->hw_index,
  10524                           &entry);
  10525         if (BCM_FAILURE(rv)) {
  10526             SC_UNLOCK(sc);
  10527             return (rv);
  10528         }
  10529         if (soc_mem_field32_get(unit, tcam_mem, &entry, VALIDf) != 0) {
  10530             mysta_profile_id = soc_mem_field32_dest_get(unit, tcam_mem, &entry,
  10531                                     DESTINATIONf, &dest_type);
  10532             if (dest_type != SOC_MEM_FIF_DEST_MYSTA) {
  10533                 SC_UNLOCK(sc);
  10534                 return BCM_E_FAIL;
  10535             }
  10536             rv = _bcm_l2_mysta_profile_entry_delete(unit,
  10537                                  (tcam_mem == MY_STATION_TCAM_2m)?1:0,
  10538                                 mysta_profile_id);
  10539             if (BCM_FAILURE(rv)) {
  10540                 SC_UNLOCK(sc);
  10541                 return (rv);
  10542             }
  10543 #ifdef BCM_TRIDENT3_SUPPORT
  10544             if (!soc_feature(unit, soc_feature_riot)) {
  10545                 if (tcam_mem == MY_STATION_TCAMm) {
  10546                     uint32 mem_no = 1;
  10547                     rv = _bcm_l2_mysta_profile_entry_delete(unit, mem_no,
  10548                                     mysta_profile_id);
  10549                     if (BCM_FAILURE(rv)) {
  10550                         SC_UNLOCK(sc);
  10551                         return (rv);
  10552                     }
  10553                 }
  10554             }
  10555 #endif
  10556         }
  10557     }
  10558 #endif
  10559 
  10560     /* Remove the entry from hardware by clearing the index. */
  10561     rv = soc_mem_write(unit, tcam_mem, MEM_BLOCK_ALL, s_ent->hw_index,
  10562                        soc_mem_entry_null(unit, tcam_mem));
  10563     if (BCM_FAILURE(rv)) {
  10564         SC_UNLOCK(sc);
  10565         return (rv);
  10566     }
  10567 #ifdef BCM_TRIDENT3_SUPPORT
  10568     if (SOC_IS_TRIDENT3X(unit) && (!soc_feature(unit, soc_feature_riot))) {
  10569         if (tcam_mem == MY_STATION_TCAMm) {
  10570             tcam_mem = MY_STATION_TCAM_2m;
  10571             rv = soc_mem_write(unit, tcam_mem, MEM_BLOCK_ALL, s_ent->hw_index,
  10572                            soc_mem_entry_null(unit, tcam_mem));
  10573             if (BCM_FAILURE(rv)) {
  10574                 SC_UNLOCK(sc);
  10575                 return (rv);
  10576             }
  10577         }
  10578     }
  10579 #endif
  10580     /* Free tcam buffer. */
  10581     if (NULL != s_ent->tcam_ent) {
  10582         sal_free(s_ent->tcam_ent);
  10583     }
  10584 
  10585     /* Remove the entry pointer from the list. */
  10586     entry_arr[s_ent->hw_index] = NULL;
  10587 
  10588     /* Increment free entries count. */
  10589 #ifdef BCM_RIOT_SUPPORT
  10590     if (_BCM_L2_STATION_ID_OVERLAY(s_ent->sid)) {
  10591         sc->entries_free_2++;
  10592         sc->entry_count_2--;
  10593     } else 
  10594 #endif /* BCM_RIOT_SUPPORT */
  10595     {
  10596         sc->entries_free++;
  10597         sc->entry_count--;
  10598     }
  10599 
  10600     /* Free the entry. */
  10601     sal_free(s_ent);
  10602     
  10603     /* Rset the last_allocated_sid */
  10604     if (station_id == sc->last_allocated_sid) {
  10605         --sc->last_allocated_sid;
  10606     }
  10607 
  10608     SC_UNLOCK(sc);
  10609 
  10610     return (rv);
  10611 }
  10612 
  10613 /*
  10614  * Function:
  10615  *     _bcm_tr_l2_station_entry_delete_all
  10616  * Purpose:
  10617  *     Deallocate all memory used to track entries and remove entries from
  10618  *     hardware.
  10619  * Parameters:
  10620  *     unit     - (IN) BCM device number
  10621  *     overlay  - (IN) Overlay/Underlay identification
  10622  * Returns:
  10623  *     BCM_E_XXX
  10624  */
  10625 STATIC int
  10626 _bcm_tr_l2_station_entry_delete_all(int unit, int overlay)
  10627 {
  10628     _bcm_l2_station_control_t   *sc = NULL; /* Control strucutre.       */
  10629     _bcm_l2_station_entry_t    **entry_arr = NULL; /* Entry array.      */
  10630     int                         rv;         /* Operation return status. */
  10631     int                         index;      /* Entry index.             */
  10632     int                         max_entries;
  10633     BCM_IF_ERROR_RETURN(_bcm_l2_station_control_get(unit, &sc));
  10634 
  10635     SC_LOCK(sc);
  10636 
  10637 
  10638     max_entries = (overlay == _BCM_L2_STATION_ENTRY_OVERLAY) ?
  10639                       sc->entries_total_2 : sc->entries_total;
  10640     entry_arr = (overlay == _BCM_L2_STATION_ENTRY_OVERLAY) ?
  10641                     (sc->entry_arr_2) : (sc->entry_arr);
  10642 
  10643     if (NULL == entry_arr) {
  10644         SC_UNLOCK(sc);
  10645         return (BCM_E_NONE);
  10646     }
  10647 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
  10648     if (soc_feature(unit, soc_feature_fp_based_oam) &&
  10649         (overlay == _BCM_L2_STATION_ENTRY_UNDERLAY)) {
  10650         max_entries = sc->entries_total + sc->olp_entries_total + 1;
  10651     }
  10652 #endif
  10653 
  10654 #ifdef BCM_KATANA2_SUPPORT
  10655     if (SOC_IS_KATANA2(unit)) {
  10656         max_entries = sc->entries_total + sc->port_entries_total + 
  10657                                           sc->olp_entries_total + 1;
  10658     }
  10659 #endif 
  10660 
  10661     for (index = 0; index < max_entries; index++) {
  10662 
  10663         if (NULL == entry_arr[index]) {
  10664             continue;
  10665         }
  10666 
  10667         rv = bcm_tr_l2_station_delete(unit, entry_arr[index]->sid);
  10668         if (BCM_FAILURE(rv)) {
  10669             SC_UNLOCK(sc);
  10670             return (rv);
  10671         }
  10672     }
  10673 
  10674     SC_UNLOCK(sc);
  10675     return (BCM_E_NONE);
  10676 }
  10677 
  10678 /*
  10679  * Function:
  10680  *     bcm_tr_l2_station_delete_all
  10681  * Purpose:
  10682  *     Deallocate all memory used to track entries and remove entries from
  10683  *     hardware.
  10684  * Parameters:
  10685  *     unit     - (IN) BCM device number
  10686  * Returns:
  10687  *     BCM_E_XXX
  10688  */
  10689 int
  10690 bcm_tr_l2_station_delete_all(int unit)
  10691 {
  10692     int rv;
  10693 
  10694     rv = _bcm_tr_l2_station_entry_delete_all(unit,
  10695              _BCM_L2_STATION_ENTRY_UNDERLAY);
  10696     BCM_IF_ERROR_RETURN(rv);
  10697 
  10698 #ifdef BCM_RIOT_SUPPORT
  10699     if (soc_feature(unit, soc_feature_riot)) {
  10700         rv = _bcm_tr_l2_station_entry_delete_all(unit,
  10701                  _BCM_L2_STATION_ENTRY_OVERLAY);
  10702 
  10703         BCM_IF_ERROR_RETURN(rv);
  10704     }
  10705 #endif /* BCM_RIOT_SUPPORT */
  10706 
  10707    return BCM_E_NONE;
  10708 }
  10709 
  10710 
  10711 /*
  10712  * Function:
  10713  *     bcm_tr_l2_station_get
  10714  * Purpose:
  10715  *     Get station information for a given station ID.
  10716  * Parameters:
  10717  *     unit         - (IN) BCM device number
  10718  *     station_id   - (IN) Station entry ID.
  10719  *     station      - (OUT) Station entry lookup information.
  10720  * Returns:
  10721  *     BCM_E_XXX
  10722  */
  10723 int
  10724 bcm_tr_l2_station_get(int unit, int station_id, bcm_l2_station_t *station)
  10725 {
  10726     _bcm_l2_station_entry_t     *s_ent = NULL; /* Entry pointer.           */
  10727     _bcm_l2_station_control_t   *sc = NULL;    /* Control structure.       */
  10728     int                         rv;            /* Operation return status. */
  10729     soc_mem_t                   tcam_mem;      /* TCAM memory name.        */
  10730     uint32                      entry[SOC_MAX_MEM_FIELD_WORDS]; /* Entry   */
  10731                                                                 /* buffer. */
  10732 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_GREYHOUND2_SUPPORT)
  10733     soc_mem_t prof_mem = MY_STATION_PROFILE_1m;
  10734 #endif
  10735 #ifdef BCM_RIOT_SUPPORT
  10736     int                         overlay = 0; /* Overlay/Underlay indicator */
  10737 #endif /* BCM_RIOT_SUPPORT */
  10738 
  10739     /* Input parameter check. */
  10740     if (NULL == station) {
  10741         return (BCM_E_PARAM);
  10742     }
  10743 
  10744     BCM_IF_ERROR_RETURN(_bcm_l2_station_control_get(unit, &sc));
  10745     SC_LOCK(sc);
  10746 
  10747     /* Get the entry by ID. */
  10748     rv = _bcm_l2_station_entry_get(unit, station_id, &s_ent);
  10749     if (BCM_FAILURE(rv)) {
  10750         SC_UNLOCK(sc);
  10751         return (rv);
  10752     }
  10753 #if defined(BCM_KATANA2_SUPPORT) || defined(BCM_TRIDENT2PLUS_SUPPORT)
  10754     if ((SOC_IS_KATANA2(unit) || 
  10755                 soc_feature(unit, soc_feature_fp_based_oam)) &&
  10756             (s_ent->flags & _BCM_L2_STATION_ENTRY_TYPE_NON_TCAM)) {
  10757         rv = _bcm_l2_station_non_tcam_entry_get(unit, sc, s_ent, 
  10758                 station_id, station);
  10759         SC_UNLOCK(sc);
  10760         return rv;
  10761     }  
  10762 #endif
  10763     rv = _bcm_l2_station_tcam_mem_get(unit,
  10764              _BCM_L2_STATION_ID_OVERLAY(station_id), &tcam_mem);
  10765     if (BCM_FAILURE(rv)) {
  10766         SC_UNLOCK(sc);
  10767         return (rv);
  10768     }
  10769 
  10770     /* Clear entry buffer. */
  10771     sal_memset(entry, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32));
  10772 
  10773     rv = soc_mem_read(unit, tcam_mem, MEM_BLOCK_ANY, s_ent->hw_index, entry);
  10774     if (BCM_FAILURE(rv)) {
  10775         SC_UNLOCK(sc);
  10776         return (rv);
  10777     }
  10778 
  10779     station->priority = s_ent->prio;
  10780 
  10781     soc_mem_mac_addr_get(unit, tcam_mem, entry,
  10782                          MAC_ADDRf, station->dst_mac);
  10783 
  10784     soc_mem_mac_addr_get(unit, tcam_mem, entry,
  10785                          MAC_ADDR_MASKf, station->dst_mac_mask);
  10786 
  10787 #ifdef BCM_RIOT_SUPPORT
  10788     if (_BCM_L2_STATION_ID_OVERLAY(station_id)) {
  10789         overlay = soc_mem_field32_get(unit, tcam_mem, entry,
  10790                                       FORWARDING_FIELD_TYPEf);
  10791     }
  10792 
  10793     if (overlay) {
  10794         int vfi = 0;
  10795         int vfi_mask = 0;
  10796 
  10797         vfi = soc_mem_field32_get(unit, tcam_mem, entry, VFI_IDf);
  10798         _BCM_VPN_SET(station->vlan, _BCM_VPN_TYPE_VFI, vfi);
  10799 
  10800         vfi_mask = soc_mem_field32_get(unit, tcam_mem, entry, VFI_ID_MASKf);
  10801         _BCM_VPN_SET(station->vlan_mask, _BCM_VPN_TYPE_VFI, vfi_mask);
  10802     } else
  10803 #endif /* BCM_RIOT_SUPPORT */
  10804     {
  10805 #ifdef BCM_RIOT_SUPPORT
  10806         if (soc_feature(unit, soc_feature_riot)) {
  10807             station->flags |= BCM_L2_STATION_UNDERLAY;
  10808         }
  10809 #endif
  10810         station->vlan
  10811             = soc_mem_field32_get(unit, tcam_mem, entry, VLAN_IDf);
  10812 
  10813         station->vlan_mask
  10814             = soc_mem_field32_get(unit, tcam_mem, entry, VLAN_ID_MASKf);
  10815     }
  10816 
  10817 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_GREYHOUND2_SUPPORT)
  10818     if (SOC_IS_KATANAX(unit)
  10819         || SOC_IS_TRIDENT(unit)
  10820         || SOC_IS_TD2_TT2(unit)
  10821         || SOC_IS_TRIUMPH3(unit)
  10822         || soc_feature(unit, soc_feature_gh2_my_station)) {
  10823         int src_field;
  10824         int src_mask_field;
  10825         int src_type = 0;
  10826         _bcm_gport_dest_t src;
  10827         _bcm_gport_dest_t src_mask;
  10828         int num_bits_for_port;
  10829 
  10830         _bcm_gport_dest_t_init(&src);
  10831         _bcm_gport_dest_t_init(&src_mask);
  10832 
  10833         if (tcam_mem == MY_STATION_TCAM_2m) {
  10834             prof_mem = MY_STATION_PROFILE_2m;
  10835         }
  10836 
  10837         if (SOC_MEM_FIELD_VALID(unit, tcam_mem, SOURCE_FIELDf)) {
  10838             src_field= soc_mem_field32_get(unit, tcam_mem, entry,
  10839                             SOURCE_FIELDf);
  10840             src_mask_field = soc_mem_field32_get(unit, tcam_mem, entry,
  10841                                   SOURCE_FIELD_MASKf);
  10842 
  10843             if (SOC_MEM_FIELD_VALID(unit, tcam_mem, SOURCE_TYPEf)) {
  10844                 src_type = soc_mem_field32_get(unit, tcam_mem, entry,
  10845                                                SOURCE_TYPEf);
  10846             }
  10847 
  10848 #ifdef BCM_RIOT_SUPPORT
  10849             if (soc_feature(unit, soc_feature_riot) && (src_type & 0x1)) {
  10850                 _bcm_vp_gport_dest_fill(unit, src_field, &src);
  10851                 src_mask.gport_type = src.gport_type;
  10852                 switch (src_mask.gport_type) {
  10853                     case _SHR_GPORT_TYPE_MPLS_PORT:
  10854                         src_mask.mpls_id = src_mask_field;
  10855                         break;
  10856                     case _SHR_GPORT_TYPE_MIM_PORT:
  10857                         src_mask.mim_id = src_mask_field;
  10858                         break;
  10859                     case _SHR_GPORT_TYPE_TRILL_PORT:
  10860                         src_mask.trill_id = src_mask_field;
  10861                         break;
  10862                     case _SHR_GPORT_TYPE_L2GRE_PORT:
  10863                         src_mask.l2gre_id = src_mask_field;
  10864                         break;
  10865                     case _SHR_GPORT_TYPE_VXLAN_PORT:
  10866                         src_mask.vxlan_id = src_mask_field;
  10867                         break;
  10868                     default:
  10869                         return BCM_E_PARAM;
  10870                 }
  10871             } else
  10872 #endif /* BCM_RIOT_SUPPORT */
  10873             if ((SOC_IS_KATANAX(unit) && (src_type & 0x1)) || 
  10874                     (src_field >> SOC_TRUNK_BIT_POS(unit)) & 0x1) {
  10875                 src.tgid = src_field & ((1 << SOC_TRUNK_BIT_POS(unit)) - 1);
  10876                 src.gport_type = _SHR_GPORT_TYPE_TRUNK;
  10877                 src_mask.tgid = src_mask_field & 
  10878                     ((1 << SOC_TRUNK_BIT_POS(unit)) - 1);
  10879                 src_mask.gport_type = _SHR_GPORT_TYPE_TRUNK;
  10880             } else if (soc_feature(unit, soc_feature_gh2_my_station) &&
  10881                        (src_type & 0x1)) {
  10882                 src.tgid = src_field;
  10883                 src.gport_type = _SHR_GPORT_TYPE_TRUNK;
  10884                 src_mask.tgid = src_mask_field;
  10885                 src_mask.gport_type = _SHR_GPORT_TYPE_TRUNK;
  10886             } else {
  10887                 src.port = src_field & SOC_PORT_ADDR_MAX(unit);
  10888                 src.modid = (src_field - src.port) /
  10889                                (SOC_PORT_ADDR_MAX(unit) + 1);
  10890                 src.gport_type = _SHR_GPORT_TYPE_MODPORT;
  10891                 num_bits_for_port = _shr_popcount(
  10892                                  (unsigned int)SOC_PORT_ADDR_MAX(unit));
  10893                 src_mask.port = src_mask_field & SOC_PORT_ADDR_MAX(unit);
  10894                 src_mask.gport_type = _SHR_GPORT_TYPE_MODPORT;
  10895                 src_mask.modid = (src_mask_field >> num_bits_for_port) & 
  10896                                  SOC_MODID_MAX(unit);
  10897             }
  10898             BCM_IF_ERROR_RETURN(_bcm_esw_gport_construct(unit, &src, 
  10899                                 &(station->src_port)));
  10900             BCM_IF_ERROR_RETURN(_bcm_esw_gport_construct(unit, &src_mask, 
  10901                                 &(station->src_port_mask)));
  10902         } else {
  10903             station->src_port
  10904                 = soc_mem_field32_get(unit, tcam_mem, entry,
  10905                                   ING_PORT_NUMf);
  10906             station->src_port_mask
  10907                 = soc_mem_field32_get(unit, tcam_mem, entry,
  10908                                   ING_PORT_NUM_MASKf);
  10909         }
  10910         
  10911         if (soc_feature(unit, soc_feature_mysta_profile)) {
  10912             uint32 mysta_profile_id = 0;
  10913             uint32 dest_type = SOC_MEM_FIF_DEST_INVALID;
  10914             my_station_profile_1_entry_t entry_prof;
  10915             mysta_profile_id = soc_mem_field32_dest_get(unit, tcam_mem, entry,
  10916                                     DESTINATIONf, &dest_type);
  10917             if (dest_type != SOC_MEM_FIF_DEST_MYSTA) {
  10918                 SC_UNLOCK(sc);
  10919                 return BCM_E_FAIL;
  10920             }
  10921 
  10922             rv = _bcm_l2_mysta_profile_entry_get(unit, &entry_prof,
  10923                                                  (prof_mem == MY_STATION_PROFILE_2m)?1:0,
  10924                                                  mysta_profile_id);
  10925             if (BCM_FAILURE(rv)) {
  10926                 SC_UNLOCK(sc);
  10927                 return rv;
  10928             }
  10929             _bcm_l2_mysta_entry_to_station(unit, &entry_prof, prof_mem, station);
  10930         } else {
  10931         if (soc_mem_field_valid(unit, tcam_mem, MIM_TERMINATION_ALLOWEDf)) { 
  10932         if (soc_mem_field32_get(unit, tcam_mem, entry,
  10933                                 MIM_TERMINATION_ALLOWEDf)) {
  10934             station->flags |= BCM_L2_STATION_MIM;
  10935         }
  10936         }
  10937 
  10938         if (soc_mem_field_valid(unit, tcam_mem, MPLS_TERMINATION_ALLOWEDf)) { 
  10939         if (soc_mem_field32_get(unit, tcam_mem, entry,
  10940                                 MPLS_TERMINATION_ALLOWEDf)) {
  10941             station->flags |= BCM_L2_STATION_MPLS;
  10942         }
  10943         }   
  10944         
  10945         if (soc_mem_field32_get(unit, tcam_mem, entry,
  10946                                 IPV4_TERMINATION_ALLOWEDf)) {
  10947             station->flags |= BCM_L2_STATION_IPV4;
  10948         }
  10949 
  10950         if (soc_mem_field32_get(unit, tcam_mem, entry,
  10951                                 IPV6_TERMINATION_ALLOWEDf)) {
  10952             station->flags |= BCM_L2_STATION_IPV6;
  10953         }
  10954         
  10955         if (soc_mem_field32_get(unit, tcam_mem, entry,
  10956                                 ARP_RARP_TERMINATION_ALLOWEDf)) {
  10957             station->flags |= BCM_L2_STATION_ARP_RARP;
  10958         }
  10959         }
  10960 
  10961         if (soc_mem_field32_get(unit, tcam_mem, entry,
  10962                                 COPY_TO_CPUf)) {
  10963             station->flags |= BCM_L2_STATION_COPY_TO_CPU;
  10964         }
  10965     }
  10966 #endif
  10967 
  10968 #if defined(BCM_TRIDENT_SUPPORT)
  10969     if (SOC_IS_TRIDENT(unit)
  10970         || SOC_IS_TD2_TT2(unit)) {
  10971 
  10972         if (soc_feature(unit, soc_feature_mysta_profile)) {
  10973             uint32 mysta_profile_id = 0;
  10974             uint32 dest_type = SOC_MEM_FIF_DEST_INVALID;
  10975             my_station_profile_1_entry_t entry_prof;
  10976             mysta_profile_id = soc_mem_field32_dest_get(unit, tcam_mem, entry,
  10977                                     DESTINATIONf, &dest_type);
  10978             if (dest_type != SOC_MEM_FIF_DEST_MYSTA) {
  10979                 SC_UNLOCK(sc);
  10980                 return BCM_E_FAIL;
  10981             }
  10982 
  10983             rv = _bcm_l2_mysta_profile_entry_get(unit, &entry_prof,
  10984                                                  (prof_mem == MY_STATION_PROFILE_2m)?1:0,
  10985                                                  mysta_profile_id);
  10986             if (BCM_FAILURE(rv)) {
  10987                 SC_UNLOCK(sc);
  10988                 return rv;
  10989             }
  10990             _bcm_l2_mysta_entry_to_station(unit, &entry_prof, prof_mem, station);
  10991         } else {
  10992         if (soc_mem_field32_get(unit, tcam_mem, entry,
  10993                                 TRILL_TERMINATION_ALLOWEDf)) {
  10994             station->flags |= BCM_L2_STATION_TRILL;
  10995         }
  10996 
  10997         if (soc_mem_field32_get(unit, tcam_mem, entry,
  10998                                 FCOE_TERMINATION_ALLOWEDf)) {
  10999             station->flags |= BCM_L2_STATION_FCOE;
  11000         }
  11001     }
  11002     }
  11003 #endif
  11004 
  11005 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || \
  11006     defined(BCM_GREYHOUND2_SUPPORT) || defined(BCM_HELIX5_SUPPORT)
  11007     if (SOC_IS_KATANAX(unit) || SOC_IS_TRIUMPH3(unit) ||
  11008         soc_feature(unit, soc_feature_gh2_my_station) ||
  11009         soc_feature(unit, soc_feature_hx5_oam_support)) {
  11010 
  11011         if (soc_mem_field_valid(unit, tcam_mem, OAM_TERMINATION_ALLOWEDf)) { 
  11012             if (soc_mem_field32_get(unit, tcam_mem, entry,
  11013                                     OAM_TERMINATION_ALLOWEDf)) {
  11014                 station->flags |= BCM_L2_STATION_OAM;
  11015             }
  11016         }
  11017     }
  11018 #endif
  11019 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || \
  11020     defined(BCM_TRIDENT_SUPPORT) || defined(BCM_GREYHOUND2_SUPPORT)
  11021     if (SOC_IS_KATANAX(unit) || SOC_IS_TRIDENT(unit) ||
  11022         SOC_IS_TD2_TT2(unit) || SOC_IS_TRIUMPH3(unit) ||
  11023          soc_feature(unit, soc_feature_gh2_my_station)) {
  11024 
  11025         if (soc_mem_field_valid(unit, tcam_mem, DISCARDf)) { 
  11026             if (soc_mem_field32_get(unit, tcam_mem, entry, DISCARDf)) {
  11027                 station->flags |= BCM_L2_STATION_DISCARD;
  11028             }
  11029         }
  11030 
  11031     }
  11032 #endif
  11033 #if defined(BCM_TSN_SUPPORT)
  11034     if (soc_feature(unit, soc_feature_tsn_taf)) {
  11035         if (soc_mem_field_valid(unit, tcam_mem, TAF_GATE_ID_PROFILEf)) {
  11036             uint32 hw_profile_id;
  11037 
  11038             hw_profile_id = soc_mem_field32_get(unit, tcam_mem,
  11039                                                 entry, TAF_GATE_ID_PROFILEf);
  11040             if (0 != hw_profile_id) {
  11041                 bcm_tsn_pri_map_t sw_index;
  11042 
  11043                 BCM_IF_ERROR_RETURN(
  11044                     bcmi_esw_tsn_pri_map_map_id_get(
  11045                         unit, bcmTsnPriMapTypeTafGate,
  11046                         hw_profile_id, &sw_index));
  11047                 station->taf_gate_primap = sw_index;
  11048             } else {
  11049                 station->taf_gate_primap = BCM_TSN_PRI_MAP_INVALID;
  11050             }
  11051         }
  11052     } else
  11053 #endif /* BCM_TSN_SUPPORT */
  11054     {
  11055         station->taf_gate_primap = BCM_TSN_PRI_MAP_INVALID;
  11056     }
  11057 
  11058     SC_UNLOCK(sc);
  11059 
  11060     return (rv);
  11061 }
  11062 
  11063 /*
  11064  * Function:
  11065  *     bcm_tr_l2_station_size_get
  11066  * Purpose:
  11067  *     Get number of entries supported by L2 station API.
  11068  * Parameters:
  11069  *     unit   - (IN) BCM device number
  11070  *     size   - (OUT) Station entry ID.
  11071  * Returns:
  11072  *     BCM_E_XXX
  11073  */
  11074 int
  11075 bcm_tr_l2_station_size_get(int unit, int *size)       
  11076 {
  11077     _bcm_l2_station_control_t   *sc = NULL; /* Station control structure. */
  11078     
  11079     /* Input parameter check. */
  11080     if (NULL == size) {
  11081         return (BCM_E_PARAM);
  11082     }
  11083 
  11084     BCM_IF_ERROR_RETURN(_bcm_l2_station_control_get(unit, &sc));
  11085     SC_LOCK(sc);
  11086 
  11087     *size = sc->entries_total;
  11088 
  11089     SC_UNLOCK(sc);
  11090     return (BCM_E_NONE);
  11091 }
  11092 
  11093 /*
  11094  * Function:
  11095  *     _bcm_tr_l2_station_entry_max_size_get
  11096  * Purpose:
  11097  *     Get number of max entries for L2 station.
  11098  * Parameters:
  11099  *     unit    - (IN) BCM device number
  11100  *     overlay - (IN) Overlay/Underlay identification
  11101  *     size    - (OUT)Max size of l2 station.
  11102  * Returns:
  11103  *     BCM_E_XXX
  11104  */
  11105 int
  11106 _bcm_tr_l2_station_entry_max_size_get(int unit, int overlay, int *size)
  11107 {
  11108     _bcm_l2_station_control_t   *sc = NULL;
  11109 
  11110     /* Input parameter check. */
  11111     if (NULL == size) {
  11112         return (BCM_E_PARAM);
  11113     }
  11114 
  11115     BCM_IF_ERROR_RETURN(_bcm_l2_station_control_get(unit, &sc));
  11116 
  11117     if (overlay) {
  11118         *size = sc->entries_total_2;
  11119     } else {
  11120         *size = sc->entries_total;
  11121 #ifdef BCM_TRIDENT2PLUS_SUPPORT
  11122         if (soc_feature(unit, soc_feature_fp_based_oam)) {
  11123             *size = sc->entries_total + sc->olp_entries_total + 1;
  11124         }
  11125 #endif
  11126 #ifdef BCM_KATANA2_SUPPORT
  11127         if (SOC_IS_KATANA2(unit)) {
  11128             *size = sc->entries_total + sc->port_entries_total +
  11129                     sc->olp_entries_total + 1;
  11130         }
  11131 #endif
  11132     }
  11133 
  11134     return (BCM_E_NONE);
  11135 }
  11136 
  11137 /*
  11138  * Function:
  11139  *     _bcm_tr_l2_station_entry_last_sid_set
  11140  * Purpose:
  11141  *     Set the current last station id for L2 station.
  11142  * Parameters:
  11143  *     unit    - (IN) BCM device number
  11144  *     overlay - (IN) Overlay/Underlay identification
  11145  *     sid     - (IN) Station ID.
  11146  * Returns:
  11147  *     BCM_E_XXX
  11148  */
  11149 int
  11150 _bcm_tr_l2_station_entry_last_sid_set(int unit, int overlay, int sid)
  11151 {
  11152     _bcm_l2_station_control_t *sc = NULL;
  11153 
  11154     BCM_IF_ERROR_RETURN(_bcm_l2_station_control_get(unit, &sc));
  11155 
  11156     if (overlay) {
  11157         if (sid) {
  11158             sc->last_allocated_sid_2 = sid;
  11159         } else {
  11160             sc->last_allocated_sid_2 = _BCM_L2_STATION_ID_2_BASE - 1;
  11161         }
  11162     } else {
  11163         if (sid) {
  11164             sc->last_allocated_sid = sid;
  11165         } else {
  11166             sc->last_allocated_sid = _BCM_L2_STATION_ID_BASE - 1;
  11167         }
  11168     }
  11169     return BCM_E_NONE;
  11170 }
  11171 
  11172 int
  11173 bcm_tr_l2_station_traverse(int unit, bcm_l2_station_traverse_cb trav_fn, void *user_data) 
  11174 {
  11175     _bcm_l2_station_control_t *sc = NULL;           /* Station control structure. */
  11176     int                       index; /* Entry index.                       */
  11177     int                       count;
  11178     int                       rv = BCM_E_NONE;
  11179     _bcm_l2_station_entry_t   *s_ent = NULL;
  11180     bcm_l2_station_t          l2_station;
  11181     int                       station_id;
  11182     /* Input parameter check. */
  11183     if (!trav_fn) {
  11184         return BCM_E_PARAM;
  11185     }
  11186     
  11187     memset((void *)(&l2_station), 0, sizeof(bcm_l2_station_t));
  11188     
  11189     BCM_IF_ERROR_RETURN(_bcm_l2_station_control_get(unit, &sc));
  11190 
  11191     count = sc->entries_total;
  11192     
  11193 #ifdef BCM_KATANA2_SUPPORT
  11194     if (SOC_IS_KATANA2(unit)) {
  11195         count = sc->entries_total + sc->port_entries_total + sc->olp_entries_total + 1;
  11196     }
  11197 #endif 
  11198 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
  11199     if (soc_feature(unit, soc_feature_fp_based_oam)) {
  11200         count = sc->entries_total + sc->olp_entries_total + 1;
  11201     }
  11202 #endif
  11203 
  11204     for (index = 0; index < count; index++) {
  11205 
  11206         s_ent = sc->entry_arr[index]; /* H/W index */
  11207         
  11208         if (NULL == s_ent) {
  11209             continue;
  11210         }
  11211         station_id = sc->entry_arr[index]->sid; /* Get S/W handle */
  11212             
  11213         rv = bcm_tr_l2_station_get(unit, station_id, &l2_station);
  11214         if (BCM_FAILURE(rv)) {
  11215             break;
  11216         }
  11217         
  11218         rv = trav_fn(unit, &l2_station, user_data);
  11219         if (BCM_FAILURE(rv)) {
  11220             LOG_DEBUG(BSL_LS_BCM_L2,
  11221                       (BSL_META_U(unit,
  11222                                   "L2(unit %d) Info: Traverse (SID=%d)/(idx=%d) entry failed.\n"),
  11223                        unit, station_id, index));
  11224             break;
  11225         }
  11226     }
  11227 
  11228     BCM_IF_ERROR_RETURN(rv);
  11229 
  11230 #ifdef BCM_RIOT_SUPPORT
  11231     if (soc_feature(unit, soc_feature_riot)) {
  11232         count = sc->entries_total_2;
  11233 
  11234         for (index = 0; index < count; index++) {
  11235             s_ent = sc->entry_arr_2[index];
  11236 
  11237             if (s_ent == NULL) {
  11238                 continue;
  11239             }
  11240 
  11241             station_id = s_ent->sid;
  11242             sal_memset((void*)&l2_station, 0, sizeof(bcm_l2_station_t));
  11243             rv = bcm_tr_l2_station_get(unit, station_id, &l2_station);
  11244             if (BCM_FAILURE(rv)) {
  11245                 break;
  11246             }
  11247 
  11248             rv = trav_fn(unit, &l2_station, user_data);
  11249             if (BCM_FAILURE(rv)) {
  11250                 LOG_DEBUG(BSL_LS_BCM_L2,
  11251                           (BSL_META_U(unit,
  11252                                       "L2(unit %d) Info: Traverse (SID=%d)/(idx=%d) entry failed.\n"),
  11253                            unit, station_id, index));
  11254                 break;
  11255             }
  11256         }
  11257     }
  11258 #endif /* BCM_RIOT_SUPPORT */
  11259 
  11260     return rv;
  11261 }
  11262 
  11263 #endif /* !BCM_TRIUMPH_SUPPORT */
  11264 
  11265 /*
  11266  * Function:
  11267  *     _bcm_tr_l2_ppa_setup
  11268  * Description:
  11269  *     Setup hardware L2 PPA registers
  11270  * Parameters:
  11271  *     unit         device number
  11272  *     flags        flags BCM_L2_REPLACE_*
  11273  *     rep_st       structure with information of what to replace
  11274  * Return:
  11275  *     BCM_E_XXX
  11276  */
  11277 STATIC int
  11278 _bcm_tr_l2_ppa_setup(int unit, _bcm_l2_replace_t *rep_st)
  11279 {
  11280     soc_field_t field;
  11281     uint32  rval, ppa_mode;
  11282     uint32  rval_limit, limit_en;
  11283     int field_len;
  11284 #ifdef BCM_HURRICANE3_SUPPORT
  11285     uint64  rval64;
  11286 #endif
  11287 
  11288     switch (rep_st->flags &
  11289             (BCM_L2_REPLACE_MATCH_DEST | BCM_L2_REPLACE_MATCH_VLAN |
  11290              BCM_L2_REPLACE_DELETE)) {
  11291     case BCM_L2_REPLACE_MATCH_DEST | BCM_L2_REPLACE_DELETE:
  11292         ppa_mode = 0;
  11293         break;
  11294     case BCM_L2_REPLACE_MATCH_VLAN | BCM_L2_REPLACE_DELETE:
  11295         ppa_mode = 1;
  11296         break;
  11297     case BCM_L2_REPLACE_MATCH_DEST | BCM_L2_REPLACE_MATCH_VLAN |
  11298         BCM_L2_REPLACE_DELETE:
  11299         ppa_mode = 2;
  11300         break;
  11301     case BCM_L2_REPLACE_DELETE:
  11302         ppa_mode = 3;
  11303         break;
  11304     case BCM_L2_REPLACE_MATCH_DEST:
  11305         ppa_mode = 4;
  11306         break;
  11307     case BCM_L2_REPLACE_MATCH_VLAN:
  11308         ppa_mode = 5;
  11309         break;
  11310     case BCM_L2_REPLACE_MATCH_DEST | BCM_L2_REPLACE_MATCH_VLAN :
  11311         ppa_mode = 6;
  11312         break;
  11313     default:
  11314         return BCM_E_PARAM;
  11315     }
  11316 
  11317     SOC_IF_ERROR_RETURN(READ_PER_PORT_REPL_CONTROLr(unit, &rval));
  11318     if ((soc_feature(unit, soc_feature_mac_learn_limit))) {
  11319 
  11320         SOC_IF_ERROR_RETURN(READ_SYS_MAC_LIMIT_CONTROLr(unit, &rval_limit));
  11321         limit_en = soc_reg_field_get(unit, SYS_MAC_LIMIT_CONTROLr, 
  11322                                  rval_limit, ENABLEf);
  11323         soc_reg_field_set(unit, PER_PORT_REPL_CONTROLr, &rval, LIMIT_COUNTEDf, 
  11324                           limit_en);
  11325         soc_reg_field_set(unit, PER_PORT_REPL_CONTROLr, &rval, 
  11326                       USE_OLD_LIMIT_COUNTEDf, limit_en);
  11327     }
  11328     soc_reg_field_set(unit, PER_PORT_REPL_CONTROLr, &rval, KEY_TYPEf,
  11329                       rep_st->key_type);
  11330     soc_reg_field_set(unit, PER_PORT_REPL_CONTROLr, &rval, EXCL_STATICf,
  11331                       rep_st->flags & BCM_L2_REPLACE_MATCH_STATIC ? 0 : 1);
  11332     soc_reg_field_set(unit, PER_PORT_REPL_CONTROLr, &rval, EXCL_NON_PENDINGf,
  11333                       rep_st->flags & BCM_L2_REPLACE_PENDING ? 1 : 0);
  11334     soc_reg_field_set(unit, PER_PORT_REPL_CONTROLr, &rval, EXCL_PENDINGf,
  11335                       rep_st->flags & BCM_L2_REPLACE_PENDING ? 0 : 1);
  11336     if (!(rep_st->flags & BCM_L2_REPLACE_DELETE)) {
  11337         if (rep_st->new_dest.vp != -1) {
  11338             /* For virtual ports PORT_NUMf provides new VPG,
  11339              * Reset MODULE_IDf and PORT_NUMf as it is overlayed with VPG
  11340              */
  11341             soc_reg_field_set(unit, PER_PORT_REPL_CONTROLr, &rval, Tf, 0);
  11342             soc_reg_field_set(unit, PER_PORT_REPL_CONTROLr, &rval, MODULE_IDf, 
  11343                               (rep_st->new_dest.vp >> 6));
  11344             soc_reg_field_set(unit, PER_PORT_REPL_CONTROLr, &rval, PORT_NUMf, 
  11345                               (rep_st->new_dest.vp & 0x3F));
  11346             if (soc_reg_field_valid(unit, PER_PORT_REPL_CONTROLr, DEST_TYPEf)) {
  11347                 soc_reg_field_set(unit, PER_PORT_REPL_CONTROLr, &rval,
  11348                                   DEST_TYPEf, 2);
  11349             }
  11350         } else if (rep_st->new_dest.trunk != -1) {
  11351             soc_reg_field_set(unit, PER_PORT_REPL_CONTROLr, &rval, Tf, 1);
  11352             soc_reg_field_set(unit, PER_PORT_REPL_CONTROLr, &rval, TGIDf,
  11353                               rep_st->new_dest.trunk);
  11354         } else {
  11355             soc_reg_field_set(unit, PER_PORT_REPL_CONTROLr, &rval, Tf, 0);
  11356             soc_reg_field_set(unit, PER_PORT_REPL_CONTROLr, &rval, MODULE_IDf,
  11357                               rep_st->new_dest.module);
  11358             soc_reg_field_set(unit, PER_PORT_REPL_CONTROLr, &rval, PORT_NUMf,
  11359                               rep_st->new_dest.port);
  11360         }
  11361     }
  11362     SOC_IF_ERROR_RETURN(WRITE_PER_PORT_REPL_CONTROLr(unit, rval));
  11363 
  11364 #ifdef BCM_HURRICANE3_SUPPORT
  11365     if (SOC_REG_IS_VALID(unit, PER_PORT_AGE_CONTROL_64r)) {
  11366         COMPILER_64_ZERO(rval64); 
  11367         soc_reg64_field32_set(unit, PER_PORT_AGE_CONTROL_64r, &rval64, 
  11368                               PPA_MODEf, ppa_mode);
  11369         if (rep_st->flags & BCM_L2_REPLACE_MATCH_VLAN) {
  11370             soc_reg64_field32_set(unit, PER_PORT_AGE_CONTROL_64r, &rval64, 
  11371                                   VLAN_IDf, 
  11372                                   rep_st->key_vfi != -1 ?
  11373                                   rep_st->key_vfi : rep_st->key_vlan);
  11374         }
  11375         if (rep_st->flags & BCM_L2_REPLACE_MATCH_DEST) {
  11376             if (rep_st->match_dest.vp != -1) {
  11377                 if (soc_reg_field_valid(unit, PER_PORT_AGE_CONTROL_64r, DEST_TYPEf)) {
  11378                     soc_reg64_field32_set(unit, PER_PORT_AGE_CONTROL_64r, &rval64, 
  11379                                           DEST_TYPEf, 2);
  11380                     soc_reg64_field32_set(unit, PER_PORT_AGE_CONTROL_64r, &rval64, 
  11381                                           VPGf, rep_st->match_dest.vp);
  11382                 } else {
  11383                     BCM_IF_ERROR_RETURN
  11384                         (soc_reg_field32_modify(unit, ING_Q_BEGINr, REG_PORT_ANY,
  11385                                                 VPG_TYPEf, 1));
  11386                     field_len = soc_reg_field_length(unit, PER_PORT_AGE_CONTROL_64r,
  11387                                                      PORT_NUMf);
  11388                     soc_reg64_field32_set(unit, PER_PORT_AGE_CONTROL_64r, &rval64, 
  11389                                           MODULE_IDf, rep_st->match_dest.vp >> field_len);
  11390                     soc_reg64_field32_set(unit, PER_PORT_AGE_CONTROL_64r, &rval64, 
  11391                                           PORT_NUMf, 
  11392                                           rep_st->match_dest.vp & ((1 << field_len) - 1));
  11393                 }
  11394             } else if (rep_st->match_dest.trunk != -1) {
  11395                 soc_reg64_field32_set(unit, PER_PORT_AGE_CONTROL_64r, &rval64, 
  11396                                       Tf, 1);
  11397                 soc_reg64_field32_set(unit, PER_PORT_AGE_CONTROL_64r, &rval64, 
  11398                                       TGIDf, rep_st->match_dest.trunk);
  11399             } else {
  11400                 soc_reg64_field32_set(unit, PER_PORT_AGE_CONTROL_64r, &rval64, 
  11401                                       MODULE_IDf, rep_st->match_dest.module);
  11402                 soc_reg64_field32_set(unit, PER_PORT_AGE_CONTROL_64r, &rval64, 
  11403                                       PORT_NUMf, rep_st->match_dest.port);
  11404             }
  11405         }
  11406         SOC_IF_ERROR_RETURN(WRITE_PER_PORT_AGE_CONTROL_64r(unit, rval64));
  11407     } else 
  11408 #endif
  11409     {
  11410         rval = 0;
  11411         soc_reg_field_set(unit, PER_PORT_AGE_CONTROLr, &rval, PPA_MODEf,
  11412                           ppa_mode);
  11413         if (rep_st->flags & BCM_L2_REPLACE_MATCH_VLAN) {
  11414             soc_reg_field_set(unit, PER_PORT_AGE_CONTROLr, &rval, VLAN_IDf,
  11415                               rep_st->key_vfi != -1 ?
  11416                               rep_st->key_vfi : rep_st->key_vlan);
  11417         }
  11418         if (rep_st->flags & BCM_L2_REPLACE_MATCH_DEST) {
  11419             if (rep_st->match_dest.vp != -1) {
  11420                 if (soc_reg_field_valid(unit, PER_PORT_AGE_CONTROLr, DEST_TYPEf)) {
  11421                     soc_reg_field_set(unit, PER_PORT_AGE_CONTROLr, &rval,
  11422                                       DEST_TYPEf, 2);
  11423                     soc_reg_field_set(unit, PER_PORT_AGE_CONTROLr, &rval, VPGf,
  11424                                       rep_st->match_dest.vp);
  11425                 } else {
  11426                     BCM_IF_ERROR_RETURN
  11427                         (soc_reg_field32_modify(unit, ING_Q_BEGINr, REG_PORT_ANY,
  11428                                                 VPG_TYPEf, 1));
  11429                     field_len = soc_reg_field_length(unit, PER_PORT_AGE_CONTROLr,
  11430                                                      PORT_NUMf);
  11431                     soc_reg_field_set(unit, PER_PORT_AGE_CONTROLr, &rval,
  11432                                       MODULE_IDf,
  11433                                       rep_st->match_dest.vp >> field_len);
  11434                     soc_reg_field_set(unit, PER_PORT_AGE_CONTROLr, &rval,
  11435                                       PORT_NUMf,
  11436                                       rep_st->match_dest.vp &
  11437                                       ((1 << field_len) - 1));
  11438                 }
  11439             } else if (rep_st->match_dest.trunk != -1) {
  11440                 soc_reg_field_set(unit, PER_PORT_AGE_CONTROLr, &rval, Tf, 1);
  11441                 soc_reg_field_set(unit, PER_PORT_AGE_CONTROLr, &rval, TGIDf,
  11442                                   rep_st->match_dest.trunk);
  11443             } else {
  11444                 soc_reg_field_set(unit, PER_PORT_AGE_CONTROLr, &rval, MODULE_IDf,
  11445                                   rep_st->match_dest.module);
  11446                 soc_reg_field_set(unit, PER_PORT_AGE_CONTROLr, &rval, PORT_NUMf,
  11447                                   rep_st->match_dest.port);
  11448             }
  11449         }
  11450         SOC_IF_ERROR_RETURN(WRITE_PER_PORT_AGE_CONTROLr(unit, rval));
  11451     }
  11452 
  11453     if (SOC_CONTROL(unit)->l2x_mode == L2MODE_FIFO) {
  11454         field = rep_st->flags & BCM_L2_REPLACE_DELETE ?
  11455             L2_MOD_FIFO_ENABLE_PPA_DELETEf : L2_MOD_FIFO_ENABLE_PPA_REPLACEf;
  11456         BCM_IF_ERROR_RETURN(soc_reg_field32_modify
  11457                             (unit, AUX_ARB_CONTROLr, REG_PORT_ANY, field,
  11458                              rep_st->flags & BCM_L2_REPLACE_NO_CALLBACKS ?
  11459                              0 : soc_l2mod_running(unit, NULL, NULL)));
  11460     }
  11461 
  11462     return BCM_E_NONE;
  11463 }
  11464 
  11465 #ifdef BCM_TRIUMPH_SUPPORT
  11466 /*
  11467  * Function:
  11468  *     _bcm_tr_ext_l2_ppa_setup
  11469  * Description:
  11470  *     Setup hardware external L2 PPA registers
  11471  * Parameters:
  11472  *     unit         device number
  11473  *     rep_st       structure with information of what to replace
  11474  * Return:
  11475  *     BCM_E_XXX
  11476  */
  11477 STATIC int
  11478 _bcm_tr_ext_l2_ppa_setup(int unit, _bcm_l2_replace_t *rep_st)
  11479 {
  11480     uint32 rval, ppa_mode;
  11481     ext_l2_mod_fifo_entry_t ext_l2_mod_entry;
  11482     ext_l2_entry_entry_t ext_l2_entry;
  11483 
  11484     switch (rep_st->flags &
  11485             (BCM_L2_REPLACE_MATCH_DEST | BCM_L2_REPLACE_MATCH_VLAN |
  11486              BCM_L2_REPLACE_DELETE)) {
  11487     case BCM_L2_REPLACE_MATCH_DEST | BCM_L2_REPLACE_DELETE:
  11488         ppa_mode = 0;
  11489         break;
  11490     case BCM_L2_REPLACE_MATCH_VLAN | BCM_L2_REPLACE_DELETE:
  11491         ppa_mode = 1;
  11492         break;
  11493     case BCM_L2_REPLACE_MATCH_DEST | BCM_L2_REPLACE_MATCH_VLAN |
  11494         BCM_L2_REPLACE_DELETE:
  11495         ppa_mode = 2;
  11496         break;
  11497     case BCM_L2_REPLACE_DELETE:
  11498         ppa_mode = 3;
  11499         break;
  11500     case BCM_L2_REPLACE_MATCH_DEST:
  11501         ppa_mode = 4;
  11502         break;
  11503     case BCM_L2_REPLACE_MATCH_VLAN:
  11504         ppa_mode = 5;
  11505         break;
  11506     case BCM_L2_REPLACE_MATCH_DEST | BCM_L2_REPLACE_MATCH_VLAN :
  11507         ppa_mode = 6;
  11508         break;
  11509     default:
  11510         return BCM_E_PARAM;
  11511     }
  11512 
  11513     SOC_IF_ERROR_RETURN(READ_ESM_PER_PORT_REPL_CONTROLr(unit, &rval));
  11514     soc_reg_field_set(unit, ESM_PER_PORT_REPL_CONTROLr, &rval, KEY_TYPE_VFIf,
  11515                       rep_st->key_vfi != -1 ? 1 : 0);
  11516     soc_reg_field_set(unit, ESM_PER_PORT_REPL_CONTROLr, &rval, EXCL_STATICf,
  11517                       rep_st->flags & BCM_L2_REPLACE_MATCH_STATIC ? 0 : 1);
  11518     if (!(rep_st->flags & BCM_L2_REPLACE_DELETE)) {
  11519         if(rep_st->new_dest.vp != -1)
  11520         {
  11521             soc_reg_field_set(unit, ESM_PER_PORT_REPL_CONTROLr, &rval, Tf, 0);
  11522             soc_reg_field_set(unit, ESM_PER_PORT_REPL_CONTROLr, &rval, MODULE_IDf, 
  11523                               (rep_st->new_dest.vp >> 6));
  11524             soc_reg_field_set(unit, ESM_PER_PORT_REPL_CONTROLr, &rval, PORT_NUMf, 
  11525                               (rep_st->new_dest.vp & 0x3F));
  11526         }
  11527         else if (rep_st->new_dest.trunk != -1) {
  11528             soc_reg_field_set(unit, ESM_PER_PORT_REPL_CONTROLr, &rval, Tf, 1);
  11529             soc_reg_field_set(unit, ESM_PER_PORT_REPL_CONTROLr, &rval, TGIDf,
  11530                               rep_st->new_dest.trunk);
  11531         } else {
  11532             soc_reg_field_set(unit, ESM_PER_PORT_REPL_CONTROLr, &rval, Tf, 0);
  11533             soc_reg_field_set(unit, ESM_PER_PORT_REPL_CONTROLr, &rval,
  11534                               MODULE_IDf, rep_st->new_dest.module);
  11535             soc_reg_field_set(unit, ESM_PER_PORT_REPL_CONTROLr, &rval,
  11536                               PORT_NUMf, rep_st->new_dest.port);
  11537         }
  11538     }
  11539     if (SOC_CONTROL(unit)->l2x_mode == L2MODE_FIFO) {
  11540         soc_reg_field_set(unit, ESM_PER_PORT_REPL_CONTROLr, &rval, CPU_NOTIFYf,
  11541                           rep_st->flags & BCM_L2_REPLACE_NO_CALLBACKS ? 0 : 1);
  11542     }
  11543     SOC_IF_ERROR_RETURN(WRITE_ESM_PER_PORT_REPL_CONTROLr(unit, rval));
  11544 
  11545     /*
  11546      * Unlike L2_MOD_FIFO, EXT_L2_MOD_FIFO does not report both new and
  11547      * replaced L2 destination for PPA replace command. To workaround
  11548      * the problem, we add an special entry to EXT_L2_MOD_FIFO before
  11549      * issuing the PPA replace command. The special entry has the new
  11550      * destination and a special "type" value. L2 mod fifo processing
  11551      * thread knows all entries after this special entry are associated
  11552      * with this new destination.
  11553      */
  11554     sal_memset(&ext_l2_mod_entry, 0, sizeof(ext_l2_mod_entry));
  11555     sal_memset(&ext_l2_entry, 0, sizeof(ext_l2_entry));
  11556 
  11557     if (rep_st->new_dest.trunk != -1) {
  11558         soc_mem_field32_set(unit, EXT_L2_ENTRYm, &ext_l2_entry, Tf, 1);
  11559         soc_mem_field32_set(unit, EXT_L2_ENTRYm, &ext_l2_entry, TGIDf,
  11560                             rep_st->new_dest.trunk);
  11561     } else {
  11562         soc_mem_field32_set(unit, EXT_L2_ENTRYm, &ext_l2_entry, MODULE_IDf,
  11563                             rep_st->new_dest.module);
  11564         soc_mem_field32_set(unit, EXT_L2_ENTRYm, &ext_l2_entry, PORT_NUMf,
  11565                             rep_st->new_dest.port);
  11566     }
  11567     soc_mem_field_set(unit, EXT_L2_MOD_FIFOm, (uint32 *)&ext_l2_mod_entry,
  11568                       WR_DATAf, (uint32 *)&ext_l2_entry);
  11569     /* borrow INSERTED type (value 3) as special mark */
  11570     soc_mem_field32_set(unit, EXT_L2_MOD_FIFOm, &ext_l2_mod_entry, TYPf, 3);
  11571     BCM_IF_ERROR_RETURN(soc_mem_write(unit, EXT_L2_MOD_FIFOm, MEM_BLOCK_ANY,
  11572                                       0, &ext_l2_mod_entry));
  11573 
  11574     rval = 0;
  11575     soc_reg_field_set(unit, ESM_PER_PORT_AGE_CONTROLr, &rval, PPA_MODEf,
  11576                       ppa_mode);
  11577     if (rep_st->flags & BCM_L2_REPLACE_MATCH_VLAN) {
  11578         soc_reg_field_set(unit, ESM_PER_PORT_AGE_CONTROLr, &rval, VLAN_IDf,
  11579                           rep_st->key_vfi != -1 ?
  11580                           rep_st->key_vfi : rep_st->key_vlan);
  11581     }
  11582     if (rep_st->flags & BCM_L2_REPLACE_MATCH_DEST) {
  11583         if (rep_st->match_dest.trunk != -1) {
  11584             soc_reg_field_set(unit, ESM_PER_PORT_AGE_CONTROLr, &rval, Tf, 1);
  11585             soc_reg_field_set(unit, ESM_PER_PORT_AGE_CONTROLr, &rval, TGIDf,
  11586                               rep_st->match_dest.trunk);
  11587         } else {
  11588             soc_reg_field_set(unit, ESM_PER_PORT_AGE_CONTROLr, &rval,
  11589                               MODULE_IDf, rep_st->match_dest.module);
  11590             soc_reg_field_set(unit, ESM_PER_PORT_AGE_CONTROLr, &rval,
  11591                               PORT_NUMf, rep_st->match_dest.port);
  11592         }
  11593     }
  11594     SOC_IF_ERROR_RETURN(WRITE_ESM_PER_PORT_AGE_CONTROLr(unit, rval));
  11595 
  11596     return BCM_E_NONE;
  11597 }
  11598 #endif /* BCM_TRIUMPH_SUPPORT */
  11599 
  11600 /*
  11601  * Function:
  11602  *     _bcm_td_l2_bulk_control_setup
  11603  * Description:
  11604  *     Setup hardware L2 bulk control registers
  11605  * Parameters:
  11606  *     unit         device number
  11607  *     rep_st       structure with information of what to replace
  11608  * Return:
  11609  *     BCM_E_XXX
  11610  */
  11611 STATIC int
  11612 _bcm_td_l2_bulk_control_setup(int unit, _bcm_l2_replace_t *rep_st)
  11613 {
  11614     uint32 rval;
  11615     int action;
  11616 
  11617     SOC_IF_ERROR_RETURN(READ_L2_BULK_CONTROLr(unit, &rval)); 
  11618     if (rep_st->int_flags & _BCM_L2_REPLACE_INT_NO_ACTION) {
  11619         action = 0;
  11620     } else if (rep_st->flags & BCM_L2_REPLACE_DELETE) {
  11621         action = 1;
  11622     } else if (rep_st->flags & BCM_L2_REPLACE_AGE) {
  11623         action = 3;
  11624     } else {
  11625         action = 2;
  11626     }
  11627     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ACTIONf, action);
  11628     if (SOC_CONTROL(unit)->l2x_mode == L2MODE_FIFO) {
  11629         int fifo_record = rep_st->flags & BCM_L2_REPLACE_NO_CALLBACKS ? 0 : 1;
  11630         if (!soc_l2mod_running(unit, NULL, NULL)) {
  11631             fifo_record = 0;
  11632         }
  11633         soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, L2_MOD_FIFO_RECORDf, 
  11634                           fifo_record); 
  11635     }
  11636     SOC_IF_ERROR_RETURN(WRITE_L2_BULK_CONTROLr(unit, rval)); 
  11637 
  11638     BCM_IF_ERROR_RETURN
  11639         (WRITE_L2_BULK_MATCH_MASKm(unit, MEM_BLOCK_ALL, 0,
  11640                                    &rep_st->match_mask));
  11641     BCM_IF_ERROR_RETURN
  11642         (WRITE_L2_BULK_MATCH_DATAm(unit, MEM_BLOCK_ALL, 0,
  11643                                    &rep_st->match_data));
  11644 
  11645     if (action == 2) {
  11646         BCM_IF_ERROR_RETURN
  11647             (WRITE_L2_BULK_REPLACE_MASKm(unit, MEM_BLOCK_ALL, 0,
  11648                                          &rep_st->new_mask));
  11649         BCM_IF_ERROR_RETURN
  11650             (WRITE_L2_BULK_REPLACE_DATAm(unit, MEM_BLOCK_ALL, 0,
  11651                                          &rep_st->new_data));
  11652     }
  11653 
  11654     return BCM_E_NONE;
  11655 }
  11656 
  11657 /*
  11658  * Function:
  11659  *     _bcm_th_l2_bulk_control_setup
  11660  * Description:
  11661  *     Setup hardware L2 bulk control registers for Tomahawk chip
  11662  * Parameters:
  11663  *     unit         device number
  11664  *     rep_st       structure with information of what to replace
  11665  * Return:
  11666  *     BCM_E_XXX
  11667  */
  11668 STATIC int
  11669 _bcm_th_l2_bulk_control_setup(int unit, _bcm_l2_replace_t *rep_st)
  11670 {
  11671 #if defined(BCM_TOMAHAWK_SUPPORT)
  11672     uint32 rval;
  11673     uint32 action;
  11674 
  11675     SOC_IF_ERROR_RETURN(READ_L2_BULK_CONTROLr(unit, &rval));
  11676 
  11677     if (rep_st->int_flags & _BCM_L2_REPLACE_INT_NO_ACTION) {
  11678         action = 0;
  11679     } else if (rep_st->flags & BCM_L2_REPLACE_DELETE) {
  11680         action = 1;
  11681     } else if (rep_st->flags & BCM_L2_REPLACE_AGE) {
  11682         action = 3;
  11683     } else {
  11684         action = 2;
  11685     }
  11686     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ACTIONf, action);
  11687     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, NUM_ENTRIESf, 
  11688                       soc_mem_index_count(unit, L2Xm));
  11689     if (SOC_CONTROL(unit)->l2x_mode == L2MODE_FIFO) {
  11690         int fifo_record = rep_st->flags & BCM_L2_REPLACE_NO_CALLBACKS ? 0 : 1;
  11691         if (!soc_l2mod_running(unit, NULL, NULL)) {
  11692             fifo_record = 0;
  11693         }
  11694 
  11695         soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, L2_MOD_FIFO_RECORDf,
  11696                           fifo_record);
  11697     }
  11698     SOC_IF_ERROR_RETURN(WRITE_L2_BULK_CONTROLr(unit, rval));
  11699 
  11700     BCM_IF_ERROR_RETURN
  11701         (WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, _BCM_L2_BULK_MATCH_MASK_INX,
  11702                                    &rep_st->match_mask));
  11703     BCM_IF_ERROR_RETURN
  11704         (WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, _BCM_L2_BULK_MATCH_DATA_INX,
  11705                                    &rep_st->match_data));
  11706 
  11707     if (!(rep_st->flags & BCM_L2_REPLACE_DELETE)) {
  11708         BCM_IF_ERROR_RETURN
  11709             (WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, _BCM_L2_BULK_REPLACE_MASK_INX,
  11710                                          &rep_st->new_mask));
  11711         BCM_IF_ERROR_RETURN
  11712             (WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, _BCM_L2_BULK_REPLACE_DATA_INX,
  11713                                          &rep_st->new_data));
  11714     }
  11715 
  11716     return BCM_E_NONE;
  11717 #else
  11718     return BCM_E_UNAVAIL;
  11719 #endif
  11720 }
  11721 
  11722 /*
  11723  * Match DEST_TYPE + MODULE_ID + PORT_NUM and replace with one of following:
  11724  * DEST_TYPE = 0, new MODULE_ID, new PORT_NUM
  11725  * DEST_TYPE = 1, new TGID
  11726  * Notes:
  11727  *     Need to match all bits of DEST_TYPE + DESTINATION, therefore can not
  11728  *     match on trunk destination because the unused overlay bits can have any
  11729  *     data.
  11730  */
  11731 STATIC int
  11732 _bcm_td_l2_bulk_replace_modport(int unit, _bcm_l2_replace_t *rep_st)
  11733 {
  11734     l2_bulk_match_mask_entry_t match_mask;
  11735     l2_bulk_match_data_entry_t match_data;
  11736     l2_bulk_replace_mask_entry_t repl_mask;
  11737     l2_bulk_replace_data_entry_t repl_data;
  11738     int field_len;
  11739 
  11740     sal_memset(&match_mask, 0, sizeof(match_mask));
  11741     sal_memset(&match_data, 0, sizeof(match_data));
  11742     sal_memset(&repl_mask, 0, sizeof(repl_mask));
  11743     sal_memset(&repl_data, 0, sizeof(repl_data));
  11744 
  11745     soc_mem_field32_set(unit, L2_BULK_MATCH_MASKm, &match_mask, VALIDf, 1);
  11746     soc_mem_field32_set(unit, L2_BULK_MATCH_DATAm, &match_data, VALIDf, 1);
  11747 
  11748     field_len = soc_mem_field_length(unit, L2_BULK_MATCH_MASKm, KEY_TYPEf);
  11749     soc_mem_field32_set(unit, L2_BULK_MATCH_MASKm, &match_mask, KEY_TYPEf,
  11750                         (1 << field_len) - 1);
  11751     /* KEY_TYPE field in data is 0 */
  11752 
  11753     field_len = soc_mem_field_length(unit, L2_BULK_MATCH_MASKm, DEST_TYPEf);
  11754     soc_mem_field32_set(unit, L2_BULK_MATCH_MASKm, &match_mask, DEST_TYPEf,
  11755                         (1 << field_len) - 1);
  11756     /* DEST_TYPE field in data is 0 */
  11757 
  11758     field_len = soc_mem_field_length(unit, L2_BULK_MATCH_MASKm, MODULE_IDf);
  11759     soc_mem_field32_set(unit, L2_BULK_MATCH_MASKm, &match_mask, MODULE_IDf,
  11760                         (1 << field_len) - 1);
  11761     soc_mem_field32_set(unit, L2_BULK_MATCH_DATAm, &match_data, MODULE_IDf,
  11762                         rep_st->match_dest.module);
  11763 
  11764     field_len = soc_mem_field_length(unit, L2_BULK_MATCH_MASKm, PORT_NUMf);
  11765     soc_mem_field32_set(unit, L2_BULK_MATCH_MASKm, &match_mask, PORT_NUMf,
  11766                         (1 << field_len) - 1);
  11767     soc_mem_field32_set(unit, L2_BULK_MATCH_DATAm, &match_data, PORT_NUMf,
  11768                         rep_st->match_dest.port);
  11769 
  11770     if (!(rep_st->flags & BCM_L2_REPLACE_MATCH_STATIC)) {
  11771         soc_mem_field32_set(unit, L2_BULK_MATCH_MASKm, &match_mask,
  11772                             STATIC_BITf, 1);
  11773         /* STATIC_BIT field in data is 0 */
  11774     }
  11775 
  11776     soc_mem_field32_set(unit, L2_BULK_MATCH_MASKm, &match_mask, PENDINGf, 1);
  11777     if (rep_st->flags & BCM_L2_REPLACE_PENDING) {
  11778         soc_mem_field32_set(unit, L2_BULK_MATCH_DATAm, &match_data, PENDINGf,
  11779                             1);
  11780     }
  11781 
  11782     soc_mem_field32_set(unit, L2_BULK_MATCH_MASKm, &match_mask, EVEN_PARITYf,
  11783                         1);
  11784 
  11785     BCM_IF_ERROR_RETURN
  11786         (WRITE_L2_BULK_MATCH_MASKm(unit, MEM_BLOCK_ALL, 0, &match_mask));
  11787 
  11788     field_len = soc_mem_field_length(unit, L2_BULK_REPLACE_MASKm, DEST_TYPEf);
  11789     soc_mem_field32_set(unit, L2_BULK_REPLACE_MASKm, &repl_mask, DEST_TYPEf,
  11790                         (1 << field_len) - 1);
  11791 
  11792     field_len = soc_mem_field_length(unit, L2_BULK_REPLACE_MASKm, MODULE_IDf);
  11793     soc_mem_field32_set(unit, L2_BULK_REPLACE_MASKm, &repl_mask, MODULE_IDf,
  11794                         (1 << field_len) - 1);
  11795 
  11796     field_len = soc_mem_field_length(unit, L2_BULK_REPLACE_MASKm, PORT_NUMf);
  11797     soc_mem_field32_set(unit, L2_BULK_REPLACE_MASKm, &repl_mask, PORT_NUMf,
  11798                         (1 << field_len) - 1);
  11799 
  11800     if (rep_st->new_dest.trunk != -1) {
  11801         soc_mem_field32_set(unit, L2_BULK_REPLACE_DATAm, &repl_data, Tf, 1);
  11802         soc_mem_field32_set(unit, L2_BULK_REPLACE_DATAm, &repl_data, TGIDf,
  11803                             rep_st->new_dest.trunk);
  11804     } else {
  11805         /* T field in data is 0 */
  11806         soc_mem_field32_set(unit, L2_BULK_REPLACE_DATAm, &repl_data,
  11807                             MODULE_IDf, rep_st->new_dest.module);
  11808         soc_mem_field32_set(unit, L2_BULK_REPLACE_DATAm, &repl_data, PORT_NUMf,
  11809                             rep_st->new_dest.port);
  11810     }
  11811 
  11812     soc_mem_field32_set(unit, L2_BULK_REPLACE_MASKm, &repl_mask, EVEN_PARITYf,
  11813                         1);
  11814     BCM_IF_ERROR_RETURN
  11815         (WRITE_L2_BULK_REPLACE_MASKm(unit, MEM_BLOCK_ALL, 0, &repl_mask));
  11816 
  11817     BCM_IF_ERROR_RETURN
  11818         (soc_reg_field32_modify(unit, L2_BULK_CONTROLr, REG_PORT_ANY, ACTIONf,
  11819                                 2));
  11820 
  11821     /* Replace all entries having EVEN_PARITY == 0 */
  11822     /* EVEN_PARITY field in data is 0 */
  11823     BCM_IF_ERROR_RETURN
  11824         (WRITE_L2_BULK_MATCH_DATAm(unit, MEM_BLOCK_ALL, 0, &match_data));
  11825 
  11826     soc_mem_field32_set(unit, L2_BULK_REPLACE_DATAm, &repl_data, EVEN_PARITYf,
  11827                         1);
  11828     BCM_IF_ERROR_RETURN
  11829         (WRITE_L2_BULK_REPLACE_DATAm(unit, MEM_BLOCK_ALL, 0, &repl_data));
  11830 
  11831     BCM_IF_ERROR_RETURN(soc_l2x_port_age(unit, L2_BULK_CONTROLr, INVALIDr));
  11832 
  11833     /* Replace all entries having EVEN_PARITY == 1 */
  11834     soc_mem_field32_set(unit, L2_BULK_MATCH_DATAm, &match_data, EVEN_PARITYf,
  11835                         1);
  11836     BCM_IF_ERROR_RETURN
  11837         (WRITE_L2_BULK_MATCH_DATAm(unit, MEM_BLOCK_ALL, 0, &match_data));
  11838 
  11839     soc_mem_field32_set(unit, L2_BULK_REPLACE_DATAm, &repl_data, EVEN_PARITYf,
  11840                         0);
  11841     BCM_IF_ERROR_RETURN
  11842         (WRITE_L2_BULK_REPLACE_DATAm(unit, MEM_BLOCK_ALL, 0, &repl_data));
  11843 
  11844     BCM_IF_ERROR_RETURN(soc_l2x_port_age(unit, L2_BULK_CONTROLr, INVALIDr));
  11845 
  11846     return BCM_E_NONE;
  11847 }
  11848 
  11849 #ifdef BCM_TRIDENT2_SUPPORT
  11850 /*
  11851  * Function:
  11852  *     _bcm_td_l2_bulk_replace_delete_age
  11853  * Description:
  11854  *     Use replace operation to replace the delete or age operation
  11855  * Parameters:
  11856  *     unit         device number
  11857  *     rep_st       structure with information of what to replace
  11858  * Return:
  11859  *     BCM_E_XXX
  11860  */
  11861 STATIC int
  11862 _bcm_td_l2_bulk_replace_delete_age(int unit, _bcm_l2_replace_t *rep_st)
  11863 {
  11864     int rv = BCM_E_NONE;
  11865     _bcm_l2_replace_t   rep_st_replace;
  11866     soc_control_t *soc = SOC_CONTROL(unit);
  11867 
  11868     sal_memcpy(&rep_st_replace, rep_st, 
  11869                             sizeof(_bcm_l2_replace_t));
  11870 
  11871     rep_st_replace.flags &= ~(BCM_L2_REPLACE_DELETE | BCM_L2_REPLACE_AGE);
  11872 
  11873     if (rep_st->flags & BCM_L2_REPLACE_DELETE) {
  11874         if (SOC_CONTROL(unit)->l2x_mode == L2MODE_FIFO) {
  11875             /* Only Clear VALIDf */
  11876             if (soc_feature(unit, soc_feature_base_valid)) {
  11877                 soc_mem_field32_set(unit, L2Xm, 
  11878                                 &rep_st_replace.new_mask, BASE_VALIDf, 1);
  11879             } else {
  11880             soc_mem_field32_set(unit, L2Xm, 
  11881                                 &rep_st_replace.new_mask, VALIDf, 1);
  11882             }
  11883         } else {
  11884             /* Clear All Fields */
  11885             sal_memset(&rep_st_replace.new_mask, 0xff, 
  11886                                        sizeof(l2x_entry_t));
  11887         }
  11888     } else if (rep_st->flags & BCM_L2_REPLACE_AGE) {
  11889         _bcm_l2_replace_t   rep_st_age;
  11890 
  11891         soc_mem_field32_set(unit, L2Xm, 
  11892                                 &rep_st_replace.new_mask, HITSAf, 1);
  11893         soc_mem_field32_set(unit, L2Xm, 
  11894                                 &rep_st_replace.new_mask, HITDAf, 1);
  11895         soc_mem_field32_set(unit, L2Xm, 
  11896                                 &rep_st_replace.new_mask, LOCAL_SAf, 1);
  11897 
  11898         sal_memcpy(&rep_st_age, &rep_st_replace, 
  11899                                 sizeof(_bcm_l2_replace_t));
  11900 
  11901         /* Iteration 1: Match VALIDf=1, STATICf=0, HITSAf=0, HITDAf=0 */
  11902         soc_mem_field32_set(unit, L2Xm, 
  11903                                 &rep_st_age.match_mask, HITSAf, 1);
  11904         soc_mem_field32_set(unit, L2Xm, 
  11905                                 &rep_st_age.match_mask, HITDAf, 1);
  11906 
  11907         if (SOC_CONTROL(unit)->l2x_mode == L2MODE_FIFO) {
  11908             /* Iteration 1: Only Clear VALIDf */
  11909             if (soc_feature(unit, soc_feature_base_valid)) {
  11910                 soc_mem_field32_set(unit, L2Xm, 
  11911                                     &rep_st_age.new_mask, BASE_VALIDf, 1);
  11912             } else {
  11913             soc_mem_field32_set(unit, L2Xm, 
  11914                                 &rep_st_age.new_mask, VALIDf, 1);
  11915             }
  11916 
  11917             /* Iteration 2: L2_BULK_CONTROLr_L2_MOD_FIFO_RECORDf = 0 */
  11918             rep_st_replace.flags |= BCM_L2_REPLACE_NO_CALLBACKS;
  11919 
  11920         } else {
  11921             /* Iteration 1: Clear All Fields */
  11922             sal_memset(&rep_st_age.new_mask, 0xff, 
  11923                                        sizeof(l2x_entry_t));
  11924         }
  11925 
  11926         BCM_IF_ERROR_RETURN(_bcm_td_l2_bulk_control_setup(unit, &rep_st_age));
  11927 
  11928         BCM_IF_ERROR_RETURN(soc_l2x_port_age(unit, L2_BULK_CONTROLr, INVALIDr));
  11929     }
  11930 
  11931     BCM_IF_ERROR_RETURN(_bcm_td_l2_bulk_control_setup(unit, &rep_st_replace));
  11932 
  11933     BCM_IF_ERROR_RETURN(soc_l2x_port_age(unit, L2_BULK_CONTROLr, INVALIDr));
  11934 
  11935     if (SOC_L2_DEL_SYNC_LOCK(soc) < 0) {
  11936         return BCM_E_RESOURCE;
  11937     }
  11938 
  11939     rv = _soc_l2x_sync_replace
  11940                 (unit, &rep_st->match_data, &rep_st->match_mask,
  11941                  rep_st->flags & BCM_L2_REPLACE_NO_CALLBACKS ?
  11942                  SOC_L2X_NO_CALLBACKS : 0);
  11943     
  11944     SOC_L2_DEL_SYNC_UNLOCK(soc);
  11945 
  11946     return rv;
  11947 }
  11948 #endif
  11949 
  11950 /*
  11951  *     _bcm_th_l2_bulk_replace_modport
  11952  * Description:
  11953  *     Match L2 entries with these fields: DEST_TYPE + MODULE_ID + PORT_NUM 
  11954  *     Replace with one of following:
  11955  *         DEST_TYPE = 0, new MODULE_ID, new PORT_NUM 
  11956  *         DEST_TYPE = 1, new TGID
  11957  * Parameters:
  11958  *     unit         device number
  11959  *     rep_st       structure with match/replace information
  11960  * Return:
  11961  *     BCM_E_XXX
  11962  */
  11963 STATIC int 
  11964 _bcm_th_l2_bulk_replace_modport(int unit, _bcm_l2_replace_t *rep_st)
  11965 {
  11966 #if defined(BCM_TOMAHAWK_SUPPORT)
  11967     l2_bulk_entry_t match_mask;
  11968     l2_bulk_entry_t match_data;
  11969     l2_bulk_entry_t repl_mask;
  11970     l2_bulk_entry_t repl_data;
  11971     int field_len;
  11972 
  11973 #ifdef BCM_TRIDENT3_SUPPORT
  11974     if (soc_feature(unit, soc_feature_flex_flow) &&
  11975         (rep_st->view_id != 0)) {
  11976         return _bcm_td3_flex_l2_bulk_replace_modport(unit, rep_st);
  11977     }
  11978 #endif
  11979 
  11980     sal_memset(&match_mask, 0, sizeof(match_mask));
  11981     sal_memset(&match_data, 0, sizeof(match_data));
  11982     sal_memset(&repl_mask, 0, sizeof(repl_mask));
  11983     sal_memset(&repl_data, 0, sizeof(repl_data));
  11984 
  11985     if (soc_feature(unit, soc_feature_base_valid)) {
  11986         soc_mem_field32_set(unit, L2_BULKm, &match_mask, BASE_VALIDf, 1);
  11987         soc_mem_field32_set(unit, L2_BULKm, &match_data, BASE_VALIDf, 1);
  11988     } else {
  11989     soc_mem_field32_set(unit, L2_BULKm, &match_mask, VALIDf, 1);
  11990     soc_mem_field32_set(unit, L2_BULKm, &match_data, VALIDf, 1);
  11991     }
  11992 
  11993     field_len = soc_mem_field_length(unit, L2_BULKm, KEY_TYPEf);
  11994     soc_mem_field32_set(unit, L2_BULKm, &match_mask, KEY_TYPEf,
  11995                         (1 << field_len) - 1);
  11996     /* KEY_TYPE field in data is 0 */
  11997 
  11998     field_len = soc_mem_field_length(unit, L2_BULKm, DEST_TYPEf);
  11999     soc_mem_field32_set(unit, L2_BULKm, &match_mask, DEST_TYPEf,
  12000                         (1 << field_len) - 1);
  12001     /* DEST_TYPE field in data is 0 */
  12002     if (soc_feature(unit, soc_feature_generic_dest)) {
  12003         soc_mem_field32_dest_set(unit, L2_BULKm, &match_mask,
  12004             DESTINATIONf, SOC_MEM_FIF_DEST_DGPP,
  12005             SOC_MEM_FIF_DGPP_MOD_ID_MASK | SOC_MEM_FIF_DGPP_PORT_MASK);
  12006         soc_mem_field32_dest_set(unit, L2_BULKm, &match_data,
  12007             DESTINATIONf, SOC_MEM_FIF_DEST_DGPP,
  12008             rep_st->match_dest.module | rep_st->match_dest.port);
  12009     } else {
  12010     field_len = soc_mem_field_length(unit, L2_BULKm, MODULE_IDf);
  12011     soc_mem_field32_set(unit, L2_BULKm, &match_mask, MODULE_IDf,
  12012                         (1 << field_len) - 1);
  12013     soc_mem_field32_set(unit, L2_BULKm, &match_data, MODULE_IDf,
  12014                         rep_st->match_dest.module);
  12015 
  12016     field_len = soc_mem_field_length(unit, L2_BULKm, PORT_NUMf);
  12017     soc_mem_field32_set(unit, L2_BULKm, &match_mask, PORT_NUMf,
  12018                         (1 << field_len) - 1);
  12019     soc_mem_field32_set(unit, L2_BULKm, &match_data, PORT_NUMf,
  12020                         rep_st->match_dest.port);
  12021     }
  12022 
  12023     if (!(rep_st->flags & BCM_L2_REPLACE_MATCH_STATIC)) {
  12024         soc_mem_field32_set(unit, L2_BULKm, &match_mask,
  12025                             STATIC_BITf, 1);
  12026         /* STATIC_BIT field in data is 0 */
  12027     }
  12028 
  12029     soc_mem_field32_set(unit, L2_BULKm, &match_mask, PENDINGf, 1);
  12030     if (rep_st->flags & BCM_L2_REPLACE_PENDING) {
  12031         soc_mem_field32_set(unit, L2_BULKm, &match_data, PENDINGf,
  12032                             1);
  12033     }
  12034 
  12035     soc_mem_field32_set(unit, L2_BULKm, &match_mask, EVEN_PARITYf,
  12036                         1);
  12037 
  12038     BCM_IF_ERROR_RETURN
  12039         (WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, _BCM_L2_BULK_MATCH_MASK_INX, 
  12040                         &match_mask));
  12041 
  12042     field_len = soc_mem_field_length(unit, L2_BULKm, DEST_TYPEf);
  12043     soc_mem_field32_set(unit, L2_BULKm, &repl_mask, DEST_TYPEf,
  12044                         (1 << field_len) - 1);
  12045 
  12046     if (soc_feature(unit, soc_feature_generic_dest)) {
  12047         soc_mem_field32_dest_set(unit, L2_BULKm, &repl_mask,
  12048             DESTINATIONf, SOC_MEM_FIF_DEST_DGPP,
  12049             SOC_MEM_FIF_DGPP_MOD_ID_MASK | SOC_MEM_FIF_DGPP_PORT_MASK);
  12050         if (rep_st->new_dest.trunk != -1) {
  12051             soc_mem_field32_dest_set(unit, L2_BULKm, &repl_data,
  12052                 DESTINATIONf, SOC_MEM_FIF_DEST_LAG, rep_st->new_dest.trunk);
  12053         } else {
  12054             soc_mem_field32_dest_set(unit, L2_BULKm, &repl_data,
  12055                 DESTINATIONf, SOC_MEM_FIF_DEST_DGPP,
  12056                 rep_st->new_dest.module | rep_st->new_dest.port);
  12057         }
  12058     } else {
  12059     field_len = soc_mem_field_length(unit, L2_BULKm, MODULE_IDf);
  12060     soc_mem_field32_set(unit, L2_BULKm, &repl_mask, MODULE_IDf,
  12061                         (1 << field_len) - 1);
  12062 
  12063     field_len = soc_mem_field_length(unit, L2_BULKm, PORT_NUMf);
  12064     soc_mem_field32_set(unit, L2_BULKm, &repl_mask, PORT_NUMf,
  12065                         (1 << field_len) - 1);
  12066 
  12067     if (rep_st->new_dest.trunk != -1) {
  12068         soc_mem_field32_set(unit, L2_BULKm, &repl_data, Tf, 1);
  12069         soc_mem_field32_set(unit, L2_BULKm, &repl_data, TGIDf,
  12070                             rep_st->new_dest.trunk);
  12071     } else {
  12072         /* T field in data is 0 */
  12073         soc_mem_field32_set(unit, L2_BULKm, &repl_data,
  12074                             MODULE_IDf, rep_st->new_dest.module);
  12075         soc_mem_field32_set(unit, L2_BULKm, &repl_data, PORT_NUMf,
  12076                             rep_st->new_dest.port);
  12077     }
  12078     }
  12079 
  12080     soc_mem_field32_set(unit, L2_BULKm, &repl_mask, EVEN_PARITYf,
  12081                         1);
  12082     BCM_IF_ERROR_RETURN
  12083         (WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, _BCM_L2_BULK_REPLACE_MASK_INX, 
  12084                         &repl_mask));
  12085 
  12086     BCM_IF_ERROR_RETURN
  12087         (soc_reg_field32_modify(unit, L2_BULK_CONTROLr, REG_PORT_ANY, ACTIONf,
  12088                                 2));
  12089     BCM_IF_ERROR_RETURN
  12090         (soc_reg_field32_modify(unit, L2_BULK_CONTROLr, REG_PORT_ANY,
  12091                             NUM_ENTRIESf, soc_mem_index_count(unit, L2Xm)));
  12092 
  12093     /* Replace all entries having EVEN_PARITY == 0 */
  12094     /* EVEN_PARITY field in data is 0 */
  12095     BCM_IF_ERROR_RETURN
  12096         (WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, _BCM_L2_BULK_MATCH_DATA_INX, 
  12097                         &match_data));
  12098 
  12099     soc_mem_field32_set(unit, L2_BULKm, &repl_data, EVEN_PARITYf,
  12100                         1);
  12101     BCM_IF_ERROR_RETURN
  12102         (WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, _BCM_L2_BULK_REPLACE_DATA_INX, 
  12103                         &repl_data));
  12104 
  12105     BCM_IF_ERROR_RETURN(soc_l2x_port_age(unit, L2_BULK_CONTROLr, INVALIDr));
  12106 
  12107     /* Replace all entries having EVEN_PARITY == 1 */
  12108     soc_mem_field32_set(unit, L2_BULKm, &match_data, EVEN_PARITYf,
  12109                         1);
  12110     BCM_IF_ERROR_RETURN
  12111         (WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, _BCM_L2_BULK_MATCH_DATA_INX, 
  12112                         &match_data));
  12113 
  12114     soc_mem_field32_set(unit, L2_BULKm, &repl_data, EVEN_PARITYf,
  12115                         0);
  12116     BCM_IF_ERROR_RETURN
  12117         (WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, _BCM_L2_BULK_REPLACE_DATA_INX,
  12118                         &repl_data));
  12119 
  12120     BCM_IF_ERROR_RETURN(soc_l2x_port_age(unit, L2_BULK_CONTROLr, INVALIDr));
  12121 
  12122     return BCM_E_NONE;
  12123 #else
  12124     return BCM_E_UNAVAIL;
  12125 #endif
  12126 }
  12127 
  12128 /*
  12129  * Function:
  12130  *     _bcm_tr_l2_replace_by_hw
  12131  * Description:
  12132  *     Helper function to _bcm_l2_replace_by_hw
  12133  * Parameters:
  12134  *     unit         device number
  12135  *     rep_st       structure with information of what to replace
  12136  * Return:
  12137  *     BCM_E_XXX
  12138  */
  12139 int
  12140 _bcm_tr_l2_replace_by_hw(int unit, _bcm_l2_replace_t *rep_st)
  12141 {
  12142     soc_control_t *soc = SOC_CONTROL(unit);
  12143     soc_reg_t int_reg, ext_reg;
  12144     int rv;
  12145     int bulk_replace_modport;
  12146     uint32 parity_diff;
  12147 #if defined(BCM_TRIUMPH_SUPPORT)
  12148     int do_l2e_ppa_match = 1;
  12149 #endif	/* BCM_TRIUMPH_SUPPORT*/
  12150 #ifdef BCM_TRIDENT3_SUPPORT
  12151     soc_flow_db_mem_view_info_t mem_view_info;
  12152 #endif	/* BCM_TRIDENT3_SUPPORT*/
  12153 #ifdef BCM_TRIDENT2_SUPPORT
  12154     soc_mem_t L2mem = L2Xm;
  12155 #endif
  12156 
  12157     if (NULL == rep_st) {
  12158         return BCM_E_PARAM;
  12159     }
  12160 
  12161 #ifdef BCM_TRIDENT3_SUPPORT
  12162     if (soc_feature(unit, soc_feature_flex_flow) &&
  12163         (rep_st->view_id != 0)) {
  12164 
  12165         BCM_IF_ERROR_RETURN(
  12166             soc_flow_db_mem_view_info_get(unit,
  12167                               rep_st->view_id,
  12168                               &mem_view_info));
  12169         L2mem = mem_view_info.mem;
  12170     }
  12171 #endif
  12172 
  12173     bulk_replace_modport = FALSE;
  12174     if (soc_feature(unit, soc_feature_l2_bulk_bypass_replace) &&
  12175         !(rep_st->int_flags & _BCM_L2_REPLACE_INT_NO_ACTION)) {
  12176         if ((rep_st->flags &
  12177              (BCM_L2_REPLACE_MATCH_DEST | BCM_L2_REPLACE_MATCH_VLAN |
  12178               BCM_L2_REPLACE_DELETE | BCM_L2_REPLACE_AGE)) == BCM_L2_REPLACE_MATCH_DEST) {
  12179             if (rep_st->match_dest.trunk == -1) {
  12180                 /* Find out if the new data will cause parity bit change */
  12181                 if (rep_st->new_dest.trunk != -1) {
  12182                     parity_diff =
  12183                         rep_st->match_dest.module ^ rep_st->match_dest.port ^
  12184                         rep_st->new_dest.trunk ^ 1;
  12185                 } else {
  12186                     parity_diff = 
  12187                         rep_st->match_dest.module ^ rep_st->match_dest.port ^
  12188                         rep_st->new_dest.module ^ rep_st->new_dest.port;
  12189                 }
  12190                 parity_diff ^= parity_diff >> 4;
  12191                 parity_diff ^= parity_diff >> 2;
  12192                 parity_diff ^= parity_diff >> 1;
  12193                 bulk_replace_modport = parity_diff & 1 ? TRUE : FALSE;
  12194             }
  12195         }
  12196     }
  12197 
  12198 #ifdef BCM_TRIDENT2_SUPPORT
  12199         if (SOC_IS_TD2_TT2(unit)) {
  12200             soc_mem_lock(unit, L2mem);
  12201         }
  12202 #endif
  12203     if (bulk_replace_modport) {
  12204         if (soc_feature(unit, soc_feature_l2_bulk_unified_table)) {
  12205             rv =  _bcm_th_l2_bulk_replace_modport(unit, rep_st);
  12206         } else {
  12207             rv =  _bcm_td_l2_bulk_replace_modport(unit, rep_st);
  12208         }
  12209 #ifdef BCM_TRIDENT2_SUPPORT
  12210         if (SOC_IS_TD2_TT2(unit)) {
  12211             soc_mem_unlock(unit, L2mem);
  12212         }
  12213 #endif
  12214         return rv;
  12215     } else {
  12216         ext_reg = INVALIDr;
  12217         if (soc_feature(unit, soc_feature_l2_bulk_control)) {
  12218             if (soc_feature(unit, soc_feature_l2_bulk_unified_table)) {
  12219                 rv = _bcm_th_l2_bulk_control_setup(unit, rep_st);
  12220             } else {
  12221 #ifdef BCM_TRIDENT2_SUPPORT
  12222                 if (SOC_IS_TD2_TT2(unit) && 
  12223                     (rep_st->flags & (BCM_L2_REPLACE_DELETE | BCM_L2_REPLACE_AGE))) {
  12224                     rv = _bcm_td_l2_bulk_replace_delete_age(unit, rep_st);
  12225                     soc_mem_unlock(unit, L2mem);
  12226                     return rv;
  12227                 }
  12228 #endif
  12229                 rv = _bcm_td_l2_bulk_control_setup(unit, rep_st);
  12230             }
  12231             if (BCM_FAILURE(rv)) {
  12232 #ifdef BCM_TRIDENT2_SUPPORT
  12233                 if (SOC_IS_TD2_TT2(unit)) {
  12234                     soc_mem_unlock(unit, L2mem);
  12235                 }
  12236 #endif
  12237                 return rv;
  12238             }
  12239             int_reg = L2_BULK_CONTROLr;
  12240         } else {
  12241             BCM_IF_ERROR_RETURN(_bcm_tr_l2_ppa_setup(unit, rep_st));
  12242 #ifdef BCM_HURRICANE3_SUPPORT
  12243             if (SOC_REG_IS_VALID(unit, PER_PORT_AGE_CONTROL_64r)) {
  12244                 int_reg = PER_PORT_AGE_CONTROL_64r;
  12245             } else 
  12246 #endif
  12247             {
  12248                 int_reg = PER_PORT_AGE_CONTROLr;
  12249             }
  12250 
  12251 #if defined(BCM_TRIUMPH_SUPPORT)
  12252             if (soc_mem_is_valid(unit, EXT_L2_ENTRYm) &&
  12253                 soc_mem_index_count(unit, EXT_L2_ENTRYm) > 0) {
  12254                 /* s/w based ppa match is supported for non vfi entries. */
  12255                 if ((do_l2e_ppa_match) && (rep_st->key_type != 3)) {
  12256                     BCM_IF_ERROR_RETURN(_bcm_tr_l2e_ppa_match(unit, rep_st));
  12257                 } else {
  12258                     BCM_IF_ERROR_RETURN(_bcm_tr_ext_l2_ppa_setup(unit, rep_st));
  12259                     ext_reg = ESM_PER_PORT_AGE_CONTROLr;
  12260                 }
  12261             }
  12262 #endif	/* BCM_TRIUMPH_SUPPORT*/
  12263         }
  12264 
  12265 #ifdef PLISIM
  12266 #ifdef _KATANA_DEBUG /* BCM_KATANA_SUPPORT */
  12267     if (SAL_BOOT_PLISIM) {
  12268         _bcm_kt_enable_port_age_simulation(flags,rep_st);
  12269     }
  12270 #endif
  12271 #endif
  12272         rv = soc_l2x_port_age(unit, int_reg, ext_reg);
  12273 #ifdef BCM_TRIDENT2_SUPPORT
  12274         if (SOC_IS_TD2_TT2(unit)) {
  12275             soc_mem_unlock(unit, L2mem);
  12276         }
  12277 #endif
  12278         if (BCM_FAILURE(rv)) {
  12279             return rv;
  12280         }
  12281 
  12282         if (rep_st->int_flags & _BCM_L2_REPLACE_INT_NO_ACTION) {
  12283             return BCM_E_NONE;
  12284         }
  12285 
  12286         if (!(rep_st->flags & BCM_L2_REPLACE_DELETE)) {
  12287             return BCM_E_NONE;
  12288         }
  12289 
  12290         if (SOC_L2_DEL_SYNC_LOCK(soc) < 0) {
  12291             return BCM_E_RESOURCE;
  12292         }
  12293         rv = _soc_l2x_sync_replace
  12294             (unit, &rep_st->match_data, &rep_st->match_mask,
  12295              rep_st->flags & BCM_L2_REPLACE_NO_CALLBACKS ?
  12296              SOC_L2X_NO_CALLBACKS : 0);
  12297 
  12298         SOC_L2_DEL_SYNC_UNLOCK(soc);
  12299     }
  12300 
  12301     return rv;
  12302 }
  12303 
  12304 #ifndef BCM_SW_STATE_DUMP_DISABLE
  12305 /*
  12306  * Function:
  12307  *     _bcm_tr_l2_sw_dump
  12308  * Purpose:
  12309  *     Displays L2 information maintained by software.
  12310  * Parameters:
  12311  *     unit - Device unit number
  12312  * Returns:
  12313  *     None
  12314  */
  12315 void
  12316 _bcm_tr_l2_sw_dump(int unit)
  12317 {
  12318     _bcm_mac_block_info_t *mbi;
  12319      char                 pfmt[SOC_PBMP_FMT_LEN];
  12320      int                  i;
  12321 #if defined(BCM_TRIUMPH_SUPPORT) /* BCM_TRIUMPH_SUPPORT */
  12322     _bcm_l2_station_control_t *sc; /* Station control structure. */
  12323     int rv;
  12324 #endif /* BCM_TRIUMPH_SUPPORT */
  12325 
  12326     LOG_CLI((BSL_META_U(unit,
  12327                         "\n")));
  12328     LOG_CLI((BSL_META_U(unit,
  12329                         "  TR L2 MAC Blocking Info -\n")));
  12330     LOG_CLI((BSL_META_U(unit,
  12331                         "      Number : %d\n"), _mbi_num[unit]));
  12332 
  12333     mbi = _mbi_entries[unit];
  12334     LOG_CLI((BSL_META_U(unit,
  12335                         "      Entries (index: pbmp-count) :\n")));
  12336     if (mbi != NULL) {
  12337         for (i = 0; i < _mbi_num[unit]; i++) {
  12338             SOC_PBMP_FMT(mbi[i].mb_pbmp, pfmt);
  12339             LOG_CLI((BSL_META_U(unit,
  12340                                 "          %5d: %s-%d\n"), i, pfmt, mbi[i].ref_count));
  12341         }
  12342     }
  12343     LOG_CLI((BSL_META_U(unit,
  12344                         "\n")));
  12345 
  12346     LOG_CLI((BSL_META_U(unit,
  12347                         "\n  TR L2 PPA bypass - %s\n"),
  12348              SOC_CONTROL(unit)->l2x_ppa_bypass ? "TRUE" : "FALSE"));
  12349 #if defined(BCM_TRIUMPH_SUPPORT) /* BCM_TRIUMPH_SUPPORT */
  12350     rv = _bcm_l2_station_control_get(unit, &sc);
  12351     if (BCM_SUCCESS(rv)) {
  12352         LOG_CLI((BSL_META_U(unit,
  12353                             "\n  Station Control Info:\n")));
  12354         LOG_CLI((BSL_META_U(unit,
  12355                             "    entries_free = %d, entries_free_2 = %d\n"),
  12356                 sc->entries_free, sc->entries_free_2));
  12357         LOG_CLI((BSL_META_U(unit,
  12358                             "    entry_count  = %d, entry_count_2  = %d\n"),
  12359                 sc->entry_count, sc->entry_count_2));
  12360     }
  12361 #endif /* BCM_TRIUMPH_SUPPORT */
  12362     return;
  12363 }
  12364 #endif /* BCM_SW_STATE_DUMP_DISABLE */
  12365 
  12366 #else /* BCM_TRX_SUPPORT */
  12367 int bcm_esw_triumph_l2_not_empty;
  12368 #endif  /* BCM_TRX_SUPPORT */
  12369