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

l2cache.c (46482B)


      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  * L2 Cache - Layer 2 BPDU and overflow address cache
      8  */
      9 
     10 #include <sal/core/libc.h>
     11 
     12 #include <shared/bsl.h>
     13 
     14 #include <soc/mem.h>
     15 #include <soc/debug.h>
     16 #include <soc/drv.h>
     17 #include <soc/l2u.h>
     18 
     19 #include <bcm/l2.h>
     20 #include <bcm/error.h>
     21 #include <bcm_int/common/multicast.h>
     22 
     23 #include <bcm_int/esw/port.h>
     24 #include <bcm_int/esw/trunk.h>
     25 #include <bcm_int/esw/vlan.h>
     26 #include <bcm_int/esw/vpn.h>
     27 #include <bcm_int/esw/virtual.h>
     28 #include <bcm_int/esw/l2.h>
     29 #include <bcm_int/esw/stack.h>
     30 #ifdef BCM_TRIDENT_SUPPORT
     31 #include <bcm_int/esw/trident.h>
     32 #endif
     33 #if defined(BCM_TRIUMPH3_SUPPORT)
     34 #include <bcm_int/esw/triumph3.h>
     35 #endif /* BCM_TRIUMPH3_SUPPORT */
     36 #if defined(BCM_KATANA2_SUPPORT)
     37 #include <bcm_int/esw/katana2.h>
     38 #endif /* BCM_KATANA2_SUPPORT */
     39 #if defined(BCM_HGPROXY_COE_SUPPORT)
     40 #include <bcm_int/esw/subport.h>
     41 #endif /* BCM_HGPROXY_COE_SUPPORT */
     42 #ifdef BCM_GREYHOUND2_SUPPORT
     43 #include <bcm_int/esw/greyhound2.h>
     44 #endif
     45 
     46 #include <bcm_int/esw_dispatch.h>
     47 #if defined(BCM_TOMAHAWK3_SUPPORT)
     48 #include <bcm_int/tomahawk3_dispatch.h>
     49 #endif /* BCM_TOMAHAWK3_SUPPORT */
     50 #ifdef BCM_TRIDENT3_SUPPORT
     51 #include <bcm_int/esw/triumph.h>
     52 #endif
     53 #ifdef BCM_XGS3_SWITCH_SUPPORT
     54 
     55 /*
     56  * Function:
     57  *      _bcm_l2_cache_gport_resolve
     58  * Purpose:
     59  *      Convert destination in a GPORT format to modid port pair or trunk id
     60  * Parameters:
     61  *      unit - Unit number
     62  *      l2caddr - (IN/OUT) Hardware-independent L2 entry
     63  * Returns:
     64  *      BCM_E_XXX
     65  */
     66 STATIC int 
     67 _bcm_l2_cache_gport_resolve(int unit, bcm_l2_cache_addr_t *l2caddr)
     68 {
     69     bcm_port_t      port;
     70     bcm_module_t    modid;
     71     bcm_trunk_t     tgid;
     72     int             id;
     73 
     74 
     75     if (BCM_GPORT_IS_SET(l2caddr->dest_port)) {
     76         BCM_IF_ERROR_RETURN(_bcm_esw_gport_resolve(unit, l2caddr->dest_port, 
     77                                                    &modid, &port, &tgid, &id));
     78 
     79 #if defined(BCM_HGPROXY_COE_SUPPORT)
     80         if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) &&
     81             _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, l2caddr->dest_port)) {
     82         } else
     83 #endif
     84 #if defined(BCM_KATANA2_SUPPORT)
     85         if (_BCM_KT2_GPORT_IS_LINKPHY_OR_SUBTAG_SUBPORT_GPORT(unit,
     86             l2caddr->dest_port)) {
     87         } else
     88 #endif
     89         {
     90             /* MPLS MIM and WLAN GPORTS are not currently supported. */
     91             if (-1 != id) {
     92                 return (BCM_E_UNAVAIL);
     93             }
     94         }
     95         /* Trunk GPORT */
     96         if (BCM_TRUNK_INVALID != tgid) {
     97             l2caddr->flags |= BCM_L2_CACHE_TRUNK;
     98             l2caddr->dest_trunk = tgid;
     99         } else {    /* MODPORT GPORT */
    100             l2caddr->dest_port = port;
    101             l2caddr->dest_modid = modid;
    102         }
    103     }
    104     if (BCM_GPORT_IS_SET(l2caddr->src_port)) {
    105         BCM_IF_ERROR_RETURN(bcm_esw_port_local_get(unit, l2caddr->src_port, 
    106                                                    &port));
    107         l2caddr->src_port = port;
    108     }
    109 
    110 
    111     return BCM_E_NONE;
    112 }
    113 
    114 
    115 /*
    116  * Function:
    117  *      _bcm_l2_cache_gport_construct
    118  * Purpose:
    119  *      Constract a GPORT destination format from modid port pair or trunk id
    120  * Parameters:
    121  *      unit - Unit number
    122  *      l2caddr - (IN/OUT) Hardware-independent L2 entry
    123  * Returns:
    124  *      BCM_E_XXX
    125  */
    126 STATIC int 
    127 _bcm_l2_cache_gport_construct(int unit, bcm_l2_cache_addr_t *l2caddr)
    128 {
    129     bcm_gport_t         gport;
    130     _bcm_gport_dest_t   gport_dst;
    131 
    132      _bcm_gport_dest_t_init(&gport_dst);
    133 
    134      if (l2caddr->flags & BCM_L2_CACHE_TRUNK) {
    135          gport_dst.gport_type = BCM_GPORT_TYPE_TRUNK;
    136          gport_dst.tgid = l2caddr->dest_trunk;
    137      } else {
    138          gport_dst.gport_type = BCM_GPORT_TYPE_MODPORT;
    139          gport_dst.modid = l2caddr->dest_modid;
    140          gport_dst.port = l2caddr->dest_port;
    141      }
    142 
    143     BCM_IF_ERROR_RETURN(
    144         _bcm_esw_gport_construct(unit, &gport_dst, &gport));
    145 
    146     l2caddr->dest_port = gport;
    147 
    148     gport_dst.gport_type = BCM_GPORT_TYPE_MODPORT;
    149     gport_dst.port = l2caddr->src_port;
    150     BCM_IF_ERROR_RETURN(
    151         bcm_esw_stk_my_modid_get(unit, &gport_dst.modid));
    152     if (gport_dst.modid < 0) {
    153         return BCM_E_UNAVAIL;
    154     }
    155 
    156     BCM_IF_ERROR_RETURN(
    157         _bcm_esw_gport_construct(unit, &gport_dst, &gport));
    158 
    159     l2caddr->src_port = gport;
    160 
    161     return BCM_E_NONE;
    162 }
    163 
    164 /*
    165  * Function:
    166  *      _bcm_l2_from_l2u
    167  * Purpose:
    168  *      Convert L2 User table entry to a hardware-independent L2 cache entry.
    169  * Parameters:
    170  *      unit - Unit number
    171  *      l2caddr - (OUT) Hardware-independent L2 entry
    172  *      l2u_entry - Firebolt L2 User entry
    173  * Returns:
    174  *      BCM_E_XXX
    175  */
    176 STATIC int
    177 _bcm_l2_cache_from_l2u(int unit, 
    178                        bcm_l2_cache_addr_t *l2caddr, l2u_entry_t *l2u_entry)
    179 {
    180     l2u_entry_t     l2u_mask_entry;
    181     bcm_module_t    mod_in = 0, mod_out;
    182     bcm_port_t      port_in = 0, port_out;
    183     uint32          mask[SOC_MAX_MEM_WORDS];
    184     int             skip_l2u, isGport, port_field_len, modid_field_len, rval;
    185     bcm_vlan_t      vlan;
    186     soc_field_t     port_field = 0;
    187 #if defined(BCM_TRIDENT2PLUS_SUPPORT)	
    188     int             my_station_config = 0;
    189 #endif
    190 #if defined(BCM_GREYHOUND2_SUPPORT)
    191     int  l2caddr_l3_is_set = 0;
    192 #endif /* BCM_GREYHOUND2_SUPPORT */
    193 
    194     skip_l2u = soc_property_get(unit, spn_SKIP_L2_USER_ENTRY, 0);
    195 
    196     if (soc_feature(unit, soc_feature_l2_user_table) && !skip_l2u) {
    197 
    198         if (!_l2u_field32_get(unit, l2u_entry, VALIDf)) {
    199             return BCM_E_NOT_FOUND;
    200         }
    201 
    202 #if defined(BCM_GREYHOUND2_SUPPORT)
    203         /* BCM_L2_CACHE_L3 is specified to get the content from MY_STATION_TCAM */
    204         if (soc_feature(unit, soc_feature_gh2_my_station) &&
    205             l2caddr->flags & BCM_L2_CACHE_L3) {
    206             l2caddr_l3_is_set = 1;
    207         }
    208 #endif /* BCM_GREYHOUND2_SUPPORT */
    209         sal_memset(l2caddr, 0, sizeof (*l2caddr));
    210         sal_memset(&l2u_mask_entry, 0, sizeof (l2u_mask_entry));
    211 
    212         if (soc_mem_field_valid(unit, L2_USER_ENTRYm, KEYf)) {
    213             _l2u_field_get(unit, l2u_entry, MASKf, mask);
    214             _l2u_field_set(unit, &l2u_mask_entry, KEYf, mask);
    215         } else {
    216             _l2u_field_get(unit, l2u_entry, MASKf, (uint32 *)&l2u_mask_entry);
    217             /* key fields start from bit 1 */
    218             l2u_mask_entry.entry_data[2] = l2u_mask_entry.entry_data[1] >> 31; 
    219             l2u_mask_entry.entry_data[1] =
    220                 (l2u_mask_entry.entry_data[1] << 1) | 
    221                 (l2u_mask_entry.entry_data[0] >> 31); 
    222             l2u_mask_entry.entry_data[0] = l2u_mask_entry.entry_data[0] << 1;
    223         }
    224 
    225         _l2u_mac_addr_get(unit, l2u_entry, MAC_ADDRf, l2caddr->mac);
    226         _l2u_mac_addr_get(unit, &l2u_mask_entry, MAC_ADDRf, l2caddr->mac_mask);
    227 
    228         vlan = _l2u_field32_get(unit, l2u_entry, VLAN_IDf);
    229         l2caddr->vlan_mask = _l2u_field32_get(unit, &l2u_mask_entry, VLAN_IDf);
    230 
    231 #if defined(BCM_TRX_SUPPORT) && defined(INCLUDE_L3)
    232         if (soc_mem_field_valid(unit, L2_USER_ENTRYm, KEY_TYPEf) &&
    233             _l2u_field32_get(unit, l2u_entry, KEY_TYPEf)) {
    234 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
    235             if (SOC_IS_TD2P_TT2P(unit) || SOC_IS_APACHE(unit)) {
    236                 vlan = _l2u_field32_get(unit, l2u_entry, VFIf);
    237                 l2caddr->vlan_mask = _l2u_field32_get(unit, &l2u_mask_entry, VFIf);
    238                 _BCM_VPN_SET(l2caddr->vlan_mask, _BCM_VPN_TYPE_VFI, l2caddr->vlan_mask);
    239             }
    240 #endif
    241 
    242 #ifdef BCM_MPLS_SUPPORT
    243             if (soc_feature(unit, soc_feature_mpls) &&
    244                (_bcm_vfi_used_get(unit, vlan, _bcmVfiTypeMpls))) {
    245                     _BCM_VPN_SET(vlan, _BCM_VPN_TYPE_VFI, vlan);
    246             } else
    247 #endif /* BCM_MPLS_SUPPORT */
    248             {
    249                 _BCM_VPN_SET(vlan, _BCM_VPN_TYPE_VFI, vlan);
    250             }
    251         }
    252 #endif /* TRX && L3 */
    253         l2caddr->vlan = vlan;
    254 
    255         l2caddr->prio = _l2u_field32_get(unit, l2u_entry, PRIf);
    256 
    257         if (_l2u_field32_get(unit, l2u_entry, RPEf)) {
    258             l2caddr->flags |= BCM_L2_CACHE_SETPRI;
    259         }
    260 
    261 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT) \
    262  || defined(BCM_RAVEN_SUPPORT)
    263         if ((SOC_IS_FIREBOLT2(unit) || SOC_IS_TRX(unit)
    264              || SOC_IS_RAVEN(unit) || SOC_IS_HAWKEYE(unit)) &&
    265             _l2u_field32_get(unit, l2u_entry, DO_NOT_LEARN_MACSAf)) {
    266             l2caddr->flags |= BCM_L2_CACHE_LEARN_DISABLE;
    267         }
    268 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT || BCM_RAVEN_SUPPORT */
    269 
    270         if (_l2u_field32_get(unit, l2u_entry, CPUf)) {
    271             l2caddr->flags |= BCM_L2_CACHE_CPU;
    272         }
    273 
    274         if (_l2u_field32_get(unit, l2u_entry, BPDUf)) {
    275             l2caddr->flags |= BCM_L2_CACHE_BPDU;
    276         }
    277 
    278         if (soc_mem_field_valid(unit, L2_USER_ENTRYm, L2_PROTOCOL_PKTf)) {
    279             if (_l2u_field32_get(unit, l2u_entry, L2_PROTOCOL_PKTf)) {
    280                 l2caddr->flags |= BCM_L2_CACHE_PROTO_PKT;
    281             }
    282         }
    283 
    284         if (_l2u_field32_get(unit, l2u_entry, DST_DISCARDf)) {
    285             l2caddr->flags |= BCM_L2_CACHE_DISCARD;
    286         }
    287 
    288         if (soc_feature(unit, soc_feature_trunk_group_overlay)) {
    289             if (soc_feature(unit, soc_feature_generic_dest)) {
    290                 uint32 dest_t = SOC_MEM_FIF_DEST_INVALID;
    291                 uint32 dest_v = soc_mem_field32_dest_get(unit, L2_USER_ENTRYm, 
    292                                         l2u_entry, DESTINATIONf, &dest_t);
    293                 if (dest_t == SOC_MEM_FIF_DEST_LAG) {
    294                     l2caddr->flags |= BCM_L2_CACHE_TRUNK;
    295                     l2caddr->dest_trunk = dest_v & SOC_MEM_FIF_DGPP_TGID_MASK;
    296                 } else if (dest_t == SOC_MEM_FIF_DEST_DGPP) {
    297                     mod_in = (dest_v & SOC_MEM_FIF_DGPP_MOD_ID_MASK) >> 
    298                              SOC_MEM_FIF_DGPP_MOD_ID_SHIFT_BITS;
    299                     port_in = dest_v & SOC_MEM_FIF_DGPP_PORT_MASK;
    300                 } else {
    301                     /* XXX */;
    302                 }
    303             } else {
    304                 if (_l2u_field32_get(unit, l2u_entry, Tf)) {
    305                     l2caddr->flags |= BCM_L2_CACHE_TRUNK;
    306                     l2caddr->dest_trunk = _l2u_field32_get(unit, l2u_entry, TGIDf);
    307                 } else {
    308                     mod_in = _l2u_field32_get(unit, l2u_entry, MODULE_IDf);
    309                     port_in = _l2u_field32_get(unit, l2u_entry, PORT_NUMf);
    310                     port_field = PORT_NUMf;
    311                 }
    312             }
    313         } else {
    314             mod_in = _l2u_field32_get(unit, l2u_entry, MODULE_IDf);
    315             port_in = _l2u_field32_get(unit, l2u_entry, PORT_TGIDf);
    316             port_field = PORT_TGIDf;
    317             if (port_in & BCM_TGID_TRUNK_INDICATOR(unit)) {
    318                 l2caddr->flags |= BCM_L2_CACHE_TRUNK;
    319                 l2caddr->dest_trunk = BCM_MODIDf_TGIDf_TO_TRUNK(unit, mod_in,
    320                                                                 port_in);
    321             }
    322         }
    323 
    324         if (BCM_MAC_IS_MCAST(l2caddr->mac) &&
    325             !_BCM_VPN_IS_SET(l2caddr->vlan)) {
    326             l2caddr->flags |= BCM_L2_CACHE_MULTICAST;
    327             l2caddr->dest_modid = mod_in;
    328             l2caddr->dest_port = port_in;
    329             port_field_len = soc_mem_field_length(unit, L2_USER_ENTRYm,
    330                                                   port_field);
    331             modid_field_len = soc_mem_field_length(unit, L2_USER_ENTRYm,
    332                                                    MODULE_IDf);
    333             /* If MACDA is MC, HW interprets value encoded in MODULE_IDf
    334                and PORT_FIELD as L2MC_INDEX */
    335             l2caddr->group = ((port_in & ((1 << port_field_len) - 1)) |
    336                               ((mod_in & ((1 << modid_field_len) - 1))
    337                               << port_field_len));
    338             /* Translate l2mc index */
    339             BCM_IF_ERROR_RETURN(
    340                 bcm_esw_switch_control_get(unit, bcmSwitchL2McIdxRetType,
    341                                            &rval));
    342             if (rval) {
    343                 _BCM_MULTICAST_GROUP_SET(l2caddr->group, _BCM_MULTICAST_TYPE_L2,
    344                                          l2caddr->group);
    345             }
    346         }
    347 
    348         if (!((l2caddr->flags & BCM_L2_CACHE_TRUNK) ||
    349             (l2caddr->flags & BCM_L2_CACHE_MULTICAST))) {
    350             if (!SOC_MODID_ADDRESSABLE(unit, mod_in)) {
    351                 return BCM_E_BADID;
    352             }
    353             BCM_IF_ERROR_RETURN(_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET,
    354                                                        mod_in, port_in, &mod_out,
    355                                                        &port_out));
    356             l2caddr->dest_modid = mod_out;
    357             l2caddr->dest_port = port_out;
    358         }
    359         BCM_IF_ERROR_RETURN(
    360             bcm_esw_switch_control_get(unit, bcmSwitchUseGport, &isGport));
    361 
    362         if (isGport) {
    363             BCM_IF_ERROR_RETURN(
    364                 _bcm_l2_cache_gport_construct(unit, l2caddr));
    365         }
    366 
    367         if (SOC_MEM_FIELD_VALID(unit, L2_USER_ENTRYm, L3f)) {
    368             if (_l2u_field32_get(unit, l2u_entry, L3f)) {
    369                 l2caddr->flags |= BCM_L2_CACHE_L3;
    370             }
    371         } else if (SOC_MEM_FIELD_VALID(unit, L2_USER_ENTRYm, RESERVED_0f)) {
    372             if (_l2u_field32_get(unit, l2u_entry, RESERVED_0f)) {
    373                 l2caddr->flags |= BCM_L2_CACHE_L3;
    374             }
    375         }
    376 
    377 #if defined(BCM_GREYHOUND2_SUPPORT)
    378         if (soc_feature(unit, soc_feature_gh2_my_station) && l2caddr_l3_is_set) {
    379             l2caddr->flags |= BCM_L2_CACHE_L3;
    380         }
    381 #endif /* BCM_GREYHOUND2_SUPPORT */
    382 
    383         if (SOC_MEM_FIELD_VALID(unit, L2_USER_ENTRYm, MIRRORf)) {
    384             if (_l2u_field32_get(unit, l2u_entry, MIRRORf)) {
    385                 l2caddr->flags |= BCM_L2_CACHE_MIRROR;
    386             }
    387         }
    388 
    389 #if defined(BCM_TRX_SUPPORT) 
    390         if (SOC_MEM_FIELD_VALID(unit, L2_USER_ENTRYm, CLASS_IDf)) {
    391             l2caddr->lookup_class = _l2u_field32_get(unit, l2u_entry, CLASS_IDf);
    392         }
    393 #endif /* BCM_TRX_SUPPORT */
    394 
    395 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
    396         my_station_config = soc_property_get(unit, 
    397                                        spn_L2_ENTRY_USED_AS_MY_STATION, 0);
    398         if (soc_feature(unit, soc_feature_l2_entry_used_as_my_station)) {
    399             uint32 dest_type = 0;
    400 #if defined(BCM_TRIDENT3_SUPPORT)
    401             if (soc_feature(unit, soc_feature_mysta_profile)) {
    402                 if (my_station_config != 0) {
    403                     bcm_l2_station_t station;
    404                     uint32 mysta_prof_id = 0;
    405                     my_station_profile_1_entry_t entry_prof;
    406                     sal_memset(&station, 0, sizeof(bcm_l2_station_t));
    407                     mysta_prof_id = soc_mem_field32_dest_get(unit, L2_USER_ENTRYm, l2u_entry,
    408                                     DESTINATIONf, &dest_type);
    409                     if (dest_type == SOC_MEM_FIF_DEST_MYSTA) {
    410                         /*MY_STATION_PROFILE_2 is used*/
    411                         BCM_IF_ERROR_RETURN(_bcm_l2_mysta_profile_entry_get(unit,
    412                                             &entry_prof, 1, mysta_prof_id));
    413                         _bcm_l2_mysta_entry_to_station(unit, &entry_prof, MY_STATION_PROFILE_2m, &station);
    414                         l2caddr->station_flags = station.flags;
    415                     } else if (dest_type != SOC_MEM_FIF_DEST_INVALID) {
    416                         l2caddr->station_flags = 0;
    417                     }
    418                 }
    419             } else
    420 #endif
    421             {
    422                 dest_type = _l2u_field32_get(unit, l2u_entry, DEST_TYPEf);
    423 
    424                 if ((my_station_config != 0) && (dest_type == 1)) {
    425 
    426                     uint32 dst = _l2u_field32_get(unit, l2u_entry, DESTINATIONf);
    427 
    428                     if((dst & _BCM_L2_DEST_TYPE_MASK) == _BCM_L2_DEST_STATION_HIT){
    429                         if (dst & _BCM_L2_DEST_STATION_IPV4) {
    430                             l2caddr->station_flags |= BCM_L2_STATION_IPV4;
    431                         }
    432 
    433                         if (dst & _BCM_L2_DEST_STATION_IPV6) {
    434                             l2caddr->station_flags |= BCM_L2_STATION_IPV6;
    435                         }
    436 
    437                         if (dst & _BCM_L2_DEST_STATION_ARP_RARP) {
    438                             l2caddr->station_flags |= BCM_L2_STATION_ARP_RARP;
    439                         }
    440 
    441                         if (dst & _BCM_L2_DEST_STATION_OAM) {
    442                             l2caddr->station_flags |= BCM_L2_STATION_OAM;
    443                         }
    444 
    445                         if (dst & _BCM_L2_DEST_STATION_FCOE) {
    446                             l2caddr->station_flags |= BCM_L2_STATION_FCOE;
    447                         }
    448 
    449                         if (dst  & _BCM_L2_DEST_STATION_IPV4_MCAST) {
    450                             l2caddr->station_flags |= BCM_L2_STATION_IPV4_MCAST;
    451                         }
    452 
    453                         if (dst & _BCM_L2_DEST_STATION_IPV6_MCAST) {
    454                             l2caddr->station_flags |= BCM_L2_STATION_IPV6_MCAST;
    455                         }
    456                     }
    457                     /* clear fake trunk configuration */
    458                     if ((dst & _BCM_L2_DEST_TYPE_MASK) != _BCM_L2_DEST_TYPE_TRUNK) {
    459                         l2caddr->flags &= (~BCM_L2_CACHE_TRUNK);
    460                         l2caddr->dest_trunk = 0;
    461                     }
    462                 }
    463             }
    464         }
    465 #endif /* BCM_TRIDENT2PLUS_SUPPORT */
    466         return BCM_E_NONE;
    467     }
    468     return BCM_E_UNAVAIL;
    469 }
    470 
    471 /*
    472  * Function:
    473  *      _bcm_fb_l2_to_l2u
    474  * Purpose:
    475  *      Convert a hardware-independent L2 cache entry to a L2 User table entry.
    476  * Parameters:
    477  *      unit - Unit number
    478  *      l2u_entry - (OUT) Firebolt L2 User entry
    479  *      l2caddr - Hardware-independent L2 entry
    480  * Returns:
    481  *      BCM_E_XXX
    482  */
    483 STATIC int
    484 _bcm_l2_cache_to_l2u(int unit, 
    485                      l2u_entry_t *l2u_entry, bcm_l2_cache_addr_t *l2caddr)
    486 {
    487     l2u_entry_t     l2u_mask_entry;
    488     bcm_module_t    mod_in, mod_out;
    489     bcm_port_t      port_in, port_out;
    490     uint32          mask[SOC_MAX_MEM_WORDS];
    491     soc_field_t     port_field = 0;
    492     int             skip_l2u, isGport;
    493     bcm_vlan_t      vlan;
    494     int             int_pri_max, modid_field_len, port_field_len;
    495 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
    496     int             my_station_config = 0;
    497     uint32          dest_value = 0;
    498 #endif
    499     int valid_bit = 0;
    500     skip_l2u = soc_property_get(unit, spn_SKIP_L2_USER_ENTRY, 0);
    501     
    502     if (soc_feature(unit, soc_feature_l2_user_table) && !skip_l2u) {
    503 
    504         if ((_BCM_VPN_IS_SET(l2caddr->vlan) != _BCM_VPN_IS_SET(l2caddr->vlan_mask)) && (l2caddr->vlan_mask)) {
    505             return BCM_E_PARAM;
    506         }
    507 
    508         /* If VPN specified do not perform vlan id check */
    509         if (!_BCM_VPN_IS_SET(l2caddr->vlan)) {
    510             VLAN_CHK_ID(unit, l2caddr->vlan);
    511             VLAN_CHK_ID(unit, l2caddr->vlan_mask);
    512         }
    513 
    514         if (l2caddr->flags & BCM_L2_CACHE_SETPRI) {
    515             int_pri_max = (SOC_IS_TD_TT(unit) || SOC_IS_KATANAX(unit)) ? 15 : 7;
    516             if (l2caddr->prio < 0 || l2caddr->prio > int_pri_max) {
    517                 return BCM_E_PARAM;
    518             }
    519 
    520             if (SOC_IS_TRIDENT3X(unit) &&
    521                 (l2caddr->flags & BCM_L2_CACHE_BPDU) &&
    522                 !(l2caddr->flags & BCM_L2_CACHE_CPU) &&
    523                 !(l2caddr->flags & BCM_L2_CACHE_DISCARD)) {
    524                 LOG_ERROR(BSL_LS_BCM_L2, (BSL_META_U(unit,
    525                           "L2Cache: SETPRI is not supported "
    526                           "for BPDU packet in this device, please use FP\n")));
    527             }
    528         }
    529 
    530 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
    531         if (soc_feature(unit, soc_feature_l2_entry_used_as_my_station)){
    532             my_station_config = soc_property_get(unit, spn_L2_ENTRY_USED_AS_MY_STATION, 0);
    533             if(my_station_config != 0) {
    534                 if ((l2caddr->station_flags &
    535                     (~( BCM_L2_STATION_IPV4        |
    536                         BCM_L2_STATION_IPV6        |
    537                         BCM_L2_STATION_ARP_RARP    |
    538                         BCM_L2_STATION_OAM         |
    539                         BCM_L2_STATION_FCOE        |
    540                         BCM_L2_STATION_IPV4_MCAST  |
    541                         BCM_L2_STATION_IPV6_MCAST))) != 0) {
    542                     return BCM_E_PARAM;
    543                 }
    544                 if (l2caddr->station_flags == 0) {
    545                     my_station_config = 0;
    546                 }
    547                 else if ((l2caddr->flags & BCM_L2_CACHE_TRUNK) != 0) {
    548                     return BCM_E_UNAVAIL;
    549                 }
    550             }
    551         }
    552         if ((my_station_config == 0) && (l2caddr->station_flags != 0)) {
    553             return BCM_E_PARAM;
    554         }
    555 #endif
    556 
    557         if (BCM_GPORT_IS_SET(l2caddr->dest_port) ||
    558             BCM_GPORT_IS_SET(l2caddr->src_port)) {
    559             BCM_IF_ERROR_RETURN(_bcm_l2_cache_gport_resolve(unit, l2caddr));
    560             isGport = 1;
    561         } else {
    562             isGport = 0;
    563         }
    564 
    565         sal_memset(l2u_entry, 0, sizeof (*l2u_entry));
    566         sal_memset(&l2u_mask_entry, 0, sizeof (l2u_mask_entry));
    567 
    568         valid_bit = 1 <<  soc_mem_field_length(unit, L2_USER_ENTRYm, VALIDf);
    569         valid_bit -= 1;
    570         _l2u_field32_set(unit, l2u_entry, VALIDf, valid_bit);
    571 
    572         vlan = l2caddr->vlan;
    573         if (soc_mem_field_valid(unit, L2_USER_ENTRYm, KEY_TYPEf)) {
    574             if (_BCM_VPN_IS_SET(l2caddr->vlan)) {
    575                 _l2u_field32_set(unit, l2u_entry, KEY_TYPEf, 1);
    576                 _BCM_VPN_GET(vlan, _BCM_VPN_TYPE_VFI, l2caddr->vlan);
    577             }
    578             _l2u_field32_set(unit, &l2u_mask_entry, KEY_TYPEf, 1);
    579 
    580             if (l2caddr->flags & BCM_L2_CACHE_PROTO_PKT) {
    581                 if (soc_mem_field_valid(unit, L2_USER_ENTRYm, 
    582                                         L2_PROTOCOL_PKTf)) {
    583                     _l2u_field32_set(unit, l2u_entry, L2_PROTOCOL_PKTf, 1);
    584                 } else {
    585                   return BCM_E_UNAVAIL;
    586                 }
    587             }
    588 
    589         } else {
    590             if (_BCM_VPN_IS_SET(l2caddr->vlan)) {
    591                 return BCM_E_CONFIG;
    592             }
    593         }
    594 
    595 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
    596         if (_BCM_VPN_IS_SET(l2caddr->vlan) &&
    597             (SOC_IS_TD2P_TT2P(unit) || SOC_IS_APACHE(unit))) {
    598             _BCM_VPN_GET(vlan, _BCM_VPN_TYPE_VFI, l2caddr->vlan);
    599             _l2u_field32_set(unit, l2u_entry, VFIf, vlan);
    600             if(l2caddr->vlan_mask != 0) {
    601                 _BCM_VPN_GET(vlan, _BCM_VPN_TYPE_VFI, l2caddr->vlan_mask);
    602                 _l2u_field32_set(unit, &l2u_mask_entry, VFIf, vlan);
    603             }
    604         }
    605         else
    606 #endif
    607         {
    608             _l2u_field32_set(unit, l2u_entry, VLAN_IDf, vlan);
    609             _l2u_field32_set(unit, &l2u_mask_entry, VLAN_IDf, l2caddr->vlan_mask);
    610         }
    611         _l2u_mac_addr_set(unit, l2u_entry, MAC_ADDRf, l2caddr->mac);
    612         _l2u_mac_addr_set(unit, &l2u_mask_entry, MAC_ADDRf, l2caddr->mac_mask);
    613 
    614         if (soc_mem_field_valid(unit, L2_USER_ENTRYm, KEYf)) {
    615             _l2u_field_get(unit, &l2u_mask_entry, KEYf, mask);
    616         } else {
    617             /* key fields start from bit 1 */
    618             mask[0] = (l2u_mask_entry.entry_data[1] << 31) | 
    619                 (l2u_mask_entry.entry_data[0] >> 1); 
    620             mask[1] = (l2u_mask_entry.entry_data[2] << 31) | 
    621                 (l2u_mask_entry.entry_data[1] >> 1); 
    622         }
    623         _l2u_field_set(unit, l2u_entry, MASKf, mask);
    624 
    625         if (l2caddr->flags & BCM_L2_CACHE_SETPRI) {
    626             _l2u_field32_set(unit, l2u_entry, PRIf, l2caddr->prio);
    627             _l2u_field32_set(unit, l2u_entry, RPEf, 1);
    628         }
    629 
    630 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT) \
    631  || defined(BCM_RAVEN_SUPPORT)
    632         if ((SOC_IS_FIREBOLT2(unit) || SOC_IS_TRX(unit)
    633              || SOC_IS_RAVEN(unit) || SOC_IS_HAWKEYE(unit)) &&
    634             (l2caddr->flags & BCM_L2_CACHE_LEARN_DISABLE)) {
    635             _l2u_field32_set(unit, l2u_entry, DO_NOT_LEARN_MACSAf, 1);
    636         }
    637 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT || BCM_RAVEN_SUPPORT */
    638 
    639         if (l2caddr->flags & BCM_L2_CACHE_CPU) {
    640             _l2u_field32_set(unit, l2u_entry, CPUf, 1);
    641         }
    642 
    643         if (l2caddr->flags & BCM_L2_CACHE_BPDU) {
    644             _l2u_field32_set(unit, l2u_entry, BPDUf, 1);
    645         }
    646 
    647         if (l2caddr->flags & BCM_L2_CACHE_DISCARD) {
    648             _l2u_field32_set(unit, l2u_entry, DST_DISCARDf, 1);
    649         }
    650 
    651         if (soc_feature(unit, soc_feature_trunk_group_overlay)) {
    652             if (l2caddr->flags & BCM_L2_CACHE_TRUNK) {
    653                 if (soc_feature(unit, soc_feature_generic_dest)) {
    654                     soc_mem_field32_dest_set(unit, L2_USER_ENTRYm, l2u_entry,
    655                         DESTINATIONf, SOC_MEM_FIF_DEST_LAG, l2caddr->dest_trunk);
    656                 } else {
    657                     _l2u_field32_set(unit, l2u_entry, Tf, 1);
    658                     _l2u_field32_set(unit, l2u_entry, TGIDf, l2caddr->dest_trunk);
    659                 }
    660             } else {
    661                 port_field = PORT_NUMf;
    662             }
    663         } else {
    664             if (SOC_IS_TOMAHAWKX(unit)) {
    665                 /*
    666                  * implies the switch has a latency mode enabled. trunking is
    667                  * not supported in any latency mode in TH.
    668                  */
    669                 port_field = PORT_NUMf;
    670             } else {
    671                 if (l2caddr->flags & BCM_L2_CACHE_TRUNK) {
    672                     _l2u_field32_set(unit, l2u_entry, MODULE_IDf,
    673                                      BCM_TRUNK_TO_MODIDf(unit,
    674                                                          l2caddr->dest_trunk));
    675                     _l2u_field32_set(unit, l2u_entry, PORT_TGIDf,
    676                                      BCM_TRUNK_TO_TGIDf(unit,
    677                                                         l2caddr->dest_trunk));
    678                 } else {
    679                     port_field = PORT_TGIDf;
    680                 }
    681             }
    682         }
    683 
    684         if (!((l2caddr->flags & BCM_L2_CACHE_TRUNK) ||
    685             (l2caddr->flags & BCM_L2_CACHE_MULTICAST))) {
    686             mod_in = l2caddr->dest_modid;
    687             port_in = l2caddr->dest_port;
    688             if (!isGport) {
    689             PORT_DUALMODID_VALID(unit, port_in);
    690             }
    691             BCM_IF_ERROR_RETURN
    692                 (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_SET,
    693                                         mod_in, port_in, &mod_out, &port_out));
    694             if (!SOC_MODID_ADDRESSABLE(unit, mod_out)) {
    695                 return BCM_E_BADID;
    696             }
    697             if (!SOC_PORT_ADDRESSABLE(unit, port_out)) {
    698                 return BCM_E_PORT;
    699             }
    700 
    701             if (soc_feature(unit, soc_feature_generic_dest)) {
    702                 soc_mem_field32_dest_set(unit, L2_USER_ENTRYm, l2u_entry,
    703                     DESTINATIONf, SOC_MEM_FIF_DEST_DGPP,
    704                     mod_out << SOC_MEM_FIF_DGPP_MOD_ID_SHIFT_BITS | port_out);
    705             } else {
    706                 _l2u_field32_set(unit, l2u_entry, MODULE_IDf, mod_out);
    707                 _l2u_field32_set(unit, l2u_entry, port_field, port_out);
    708             }
    709         }
    710 
    711         if ((l2caddr->flags & BCM_L2_CACHE_MULTICAST) &&
    712             !_BCM_VPN_IS_SET(l2caddr->vlan)) {
    713             if (_BCM_MULTICAST_IS_SET(l2caddr->group)) {
    714                 if (_BCM_MULTICAST_IS_L2(l2caddr->group)) {
    715                     port_field_len = soc_mem_field_length(unit, L2_USER_ENTRYm,
    716                                                           port_field);
    717                     modid_field_len = soc_mem_field_length(unit, L2_USER_ENTRYm,
    718                                                            MODULE_IDf);
    719                     /* If MACDA is MC, HW interprets value encoded in MODULE_IDf
    720                        and PORT_FIELD as L2MC_INDEX */
    721                     _l2u_field32_set(unit, l2u_entry, port_field,
    722                                      (_BCM_MULTICAST_ID_GET(l2caddr->group) &
    723                                      ((1 << port_field_len) - 1)));
    724                     _l2u_field32_set(unit, l2u_entry, MODULE_IDf,
    725                                      ((_BCM_MULTICAST_ID_GET(l2caddr->group) >>
    726                                      port_field_len) &
    727                                      ((1 << modid_field_len) - 1)));
    728                 } else {
    729                     return BCM_E_PARAM;
    730                 }
    731             }
    732         }
    733 
    734         if (l2caddr->flags & BCM_L2_CACHE_L3) {
    735             if (SOC_MEM_FIELD_VALID(unit, L2_USER_ENTRYm, L3f)) {
    736                 _l2u_field32_set(unit, l2u_entry, L3f, 1);
    737             } else if (SOC_MEM_FIELD_VALID(unit, L2_USER_ENTRYm,
    738                                            RESERVED_0f)) {
    739                 _l2u_field32_set(unit, l2u_entry, RESERVED_0f, 1);
    740             }
    741         }
    742 
    743         if (l2caddr->flags & BCM_L2_CACHE_MIRROR) {
    744             if (SOC_MEM_FIELD_VALID(unit, L2_USER_ENTRYm, MIRRORf)) {
    745                 _l2u_field32_set(unit, l2u_entry, MIRRORf, 1);
    746             }
    747         }
    748 
    749 #if defined(BCM_TRX_SUPPORT) 
    750         if (SOC_MEM_FIELD_VALID(unit, L2_USER_ENTRYm, CLASS_IDf)) {
    751             _l2u_field32_set(unit, l2u_entry, CLASS_IDf, l2caddr->lookup_class);
    752         }
    753 #endif /* BCM_TRX_SUPPORT */
    754 
    755 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
    756         if (my_station_config != 0 && soc_feature(unit, soc_feature_l2_entry_used_as_my_station)) {
    757 #if defined(BCM_TRIDENT3_SUPPORT)
    758             if (soc_feature(unit, soc_feature_mysta_profile)) {
    759                 uint32 mysta_profile_id;
    760                 bcm_l2_station_t station;
    761                 my_station_profile_2_entry_t entry;
    762 
    763                 sal_memset(&station, 0, sizeof(bcm_l2_station_t));
    764                 sal_memset(&entry, 0, sizeof(entry));
    765                 station.flags = l2caddr->station_flags;
    766                 if (l2caddr->station_flags != 0) {
    767                     _bcm_l2_mysta_station_to_entry(unit, &station, MY_STATION_PROFILE_2m, &entry);
    768                     BCM_IF_ERROR_RETURN(
    769                         _bcm_l2_mysta_profile_entry_add(unit, &entry, 1,
    770                                                         &mysta_profile_id));
    771                     soc_mem_field32_dest_set(unit, L2_USER_ENTRYm, l2u_entry,
    772                         DESTINATIONf, SOC_MEM_FIF_DEST_MYSTA, mysta_profile_id);
    773                 }
    774             } else
    775 #endif
    776             {
    777                 _l2u_field32_set(unit, l2u_entry, DEST_TYPEf, 1);
    778 
    779                 dest_value = _BCM_L2_DEST_STATION_HIT;
    780 
    781                 if (l2caddr->station_flags & BCM_L2_STATION_IPV4) {
    782                     dest_value |= _BCM_L2_DEST_STATION_IPV4;
    783                 }
    784 
    785                 if (l2caddr->station_flags & BCM_L2_STATION_IPV6) {
    786                     dest_value |= _BCM_L2_DEST_STATION_IPV6;
    787                 }
    788 
    789                 if (l2caddr->station_flags & BCM_L2_STATION_ARP_RARP) {
    790                     dest_value |= _BCM_L2_DEST_STATION_ARP_RARP;
    791                 }
    792 
    793                 if (l2caddr->station_flags & BCM_L2_STATION_OAM) {
    794                     dest_value |= _BCM_L2_DEST_STATION_OAM;
    795                 }
    796 
    797                 if (l2caddr->station_flags & BCM_L2_STATION_FCOE) {
    798                     dest_value |= _BCM_L2_DEST_STATION_FCOE;
    799                 }
    800 
    801                 if (l2caddr->station_flags & BCM_L2_STATION_IPV4_MCAST) {
    802                     dest_value |= _BCM_L2_DEST_STATION_IPV4_MCAST;
    803                 }
    804 
    805                 if (l2caddr->station_flags & BCM_L2_STATION_IPV6_MCAST) {
    806                     dest_value |= _BCM_L2_DEST_STATION_IPV6_MCAST;
    807                 }
    808                 _l2u_field32_set(unit, l2u_entry, DESTINATIONf, dest_value);
    809             }
    810         }
    811 #endif /* BCM_TRIDENT2PLUS_SUPPORT */
    812 
    813         return BCM_E_NONE;
    814     }
    815     return BCM_E_UNAVAIL;
    816 }
    817 #endif /* BCM_XGS3_SWITCH_SUPPORT */
    818 
    819 /*
    820  * Function:
    821  *      bcm_esw_l2_cache_init
    822  * Purpose:
    823  *      Initialize the L2 cache
    824  * Parameters:
    825  *      unit - device number
    826  * Returns:
    827  *      BCM_E_XXX
    828  * Notes:
    829  *      Clears all entries and preloads a few BCM_L2_CACHE_BPDU
    830  *      entries to match previous generation of devices.
    831  */
    832 int
    833 bcm_esw_l2_cache_init(int unit)
    834 {
    835 #ifdef BCM_XGS3_SWITCH_SUPPORT
    836     int     skip_l2u;
    837 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
    838     uint64  regval64;
    839     int     my_station_config = 0;
    840 #endif
    841 
    842 #if defined(BCM_TOMAHAWK3_SUPPORT)
    843     /* Added to handle SDK functions calling esw version,
    844      * instead of Tomahawk3's version
    845      */
    846     if (SOC_IS_TOMAHAWK3(unit)) {
    847         return bcm_tomahawk3_l2_cache_init(unit);
    848     }
    849 #endif /* BCM_TOMAHAWK3_SUPPORT  */
    850 
    851     if (!SOC_UNIT_VALID(unit)) {
    852         return BCM_E_UNIT;
    853     }
    854 
    855 #if defined(BCM_TRIUMPH3_SUPPORT)
    856     if (soc_feature(unit, soc_feature_ism_memory)) {
    857         return bcm_tr3_l2_cache_init(unit);
    858     }
    859 #endif /* BCM_TRIUMPH3_SUPPORT */
    860 
    861     skip_l2u = soc_property_get(unit, spn_SKIP_L2_USER_ENTRY, 0);
    862 
    863     if (soc_feature(unit, soc_feature_l2_user_table) && !skip_l2u) {
    864         bcm_l2_cache_addr_t addr;
    865         l2u_entry_t entry;
    866         int index;
    867 
    868         if (!SAL_BOOT_QUICKTURN && !SAL_BOOT_XGSSIM) {
    869             SOC_IF_ERROR_RETURN
    870                 (soc_mem_clear(unit, L2_USER_ENTRYm, COPYNO_ALL, TRUE));
    871         }
    872 
    873 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
    874         COMPILER_64_ZERO(regval64);
    875         /* Enable L2 entry used as my station hit */
    876         my_station_config = soc_property_get(unit,
    877                                        spn_L2_ENTRY_USED_AS_MY_STATION, 0);
    878         if (soc_feature(unit, soc_feature_l2_entry_used_as_my_station)) {
    879             SOC_IF_ERROR_RETURN(READ_ING_CONFIG_64r(unit, &regval64));
    880             if (my_station_config != soc_reg64_field32_get(unit, ING_CONFIG_64r,
    881                 regval64, L2_ENTRY_USED_AS_MY_STATIONf)) {
    882                 BCM_IF_ERROR_RETURN
    883                    (soc_reg_field32_modify(unit, ING_CONFIG_64r, REG_PORT_ANY,
    884                              L2_ENTRY_USED_AS_MY_STATIONf, my_station_config));
    885             }
    886         }
    887 #endif
    888 
    889         bcm_l2_cache_addr_t_init(&addr);
    890         addr.flags = BCM_L2_CACHE_CPU | BCM_L2_CACHE_BPDU;
    891         /* Set default BPDU addresses (01:80:c2:00:00:00) */
    892         ENET_SET_MACADDR(addr.mac, _soc_mac_spanning_tree);
    893         ENET_SET_MACADDR(addr.mac_mask, _soc_mac_all_ones);
    894         BCM_IF_ERROR_RETURN (bcm_esw_stk_my_modid_get(unit, &addr.dest_modid));
    895         addr.dest_port = CMIC_PORT(unit);
    896         BCM_IF_ERROR_RETURN(_bcm_l2_cache_to_l2u(unit, &entry, &addr));
    897         SOC_IF_ERROR_RETURN(soc_l2u_insert(unit, &entry, -1, &index));
    898 
    899         if (soc_mem_field_valid(unit, L2_USER_ENTRYm, L2_PROTOCOL_PKTf)) {
    900             soc_mem_field32_set(unit, L2_USER_ENTRYm,
    901                                       &entry, L2_PROTOCOL_PKTf, 1);
    902             if (!soc_feature(unit, soc_feature_l2_no_vfi)) {
    903                 soc_mem_field32_set(unit, L2_USER_ENTRYm, &entry, KEY_TYPEf, 1);
    904             }
    905             if (soc_mem_field_valid(unit, L2_USER_ENTRYm, VFI_MASKf)) {
    906                soc_mem_field32_set(unit, L2_USER_ENTRYm, &entry, VFI_MASKf, 0);
    907             }
    908             SOC_IF_ERROR_RETURN(soc_l2u_insert(unit, &entry, -1, &index));
    909         }
    910 
    911         if (!SAL_BOOT_QUICKTURN && !SAL_BOOT_XGSSIM) {
    912             /* Set 01:80:c2:00:00:10 */
    913             addr.mac[5] = 0x10;
    914             BCM_IF_ERROR_RETURN(_bcm_l2_cache_to_l2u(unit, &entry, &addr));
    915             SOC_IF_ERROR_RETURN(soc_l2u_insert(unit, &entry, -1, &index));
    916             /* Set 01:80:c2:00:00:0x */
    917             addr.mac[5] = 0x00;
    918             addr.mac_mask[5] = 0xf0;
    919             BCM_IF_ERROR_RETURN(_bcm_l2_cache_to_l2u(unit, &entry, &addr));
    920             SOC_IF_ERROR_RETURN(soc_l2u_insert(unit, &entry, -1, &index));
    921             /* Set 01:80:c2:00:00:2x */
    922             addr.mac[5] = 0x20;
    923             BCM_IF_ERROR_RETURN(_bcm_l2_cache_to_l2u(unit, &entry, &addr));
    924             SOC_IF_ERROR_RETURN(soc_l2u_insert(unit, &entry, -1, &index));
    925         }
    926 
    927         return BCM_E_NONE;
    928     }
    929 #endif /* BCM_XGS3_SWITCH_SUPPORT */
    930     return BCM_E_UNAVAIL;
    931 }
    932 
    933 
    934 /*
    935  * Function:
    936  *      bcm_esw_l2_cache_size_get
    937  * Purpose:
    938  *      Get number of L2 cache entries
    939  * Parameters:
    940  *      unit - device number
    941  *      size - (OUT) number of entries in cache
    942  * Returns:
    943  *      BCM_E_XXX
    944  */
    945 int
    946 bcm_esw_l2_cache_size_get(int unit, int *size)
    947 {
    948 #ifdef BCM_XGS3_SWITCH_SUPPORT
    949     int skip_l2u;
    950 
    951 #if defined(BCM_TOMAHAWK3_SUPPORT)
    952     /* Added to handle SDK functions calling esw version,
    953      * instead of Tomahawk3's version
    954      */
    955     if (SOC_IS_TOMAHAWK3(unit)) {
    956         return bcm_tomahawk3_l2_cache_size_get(unit, size);
    957     }
    958 #endif /* BCM_TOMAHAWK3_SUPPORT  */
    959 
    960     if (!SOC_UNIT_VALID(unit)) {
    961         return BCM_E_UNIT;
    962     }
    963 
    964     skip_l2u = soc_property_get(unit, spn_SKIP_L2_USER_ENTRY, 0);
    965 
    966     if (soc_feature(unit, soc_feature_l2_user_table) && !skip_l2u) {
    967         *size = soc_mem_index_count(unit, L2_USER_ENTRYm);
    968 
    969         return 0;
    970     }
    971 #endif /* BCM_XGS3_SWITCH_SUPPORT */
    972     return BCM_E_UNAVAIL;
    973 }
    974 
    975 /*
    976  * Function:
    977  *      bcm_esw_l2_cache_set
    978  * Purpose:
    979  *      Set an L2 cache entry
    980  * Parameters:
    981  *      unit - device number
    982  *      index - l2 cache entry number (or -1)
    983  *              If -1 is given then the entry used will be the first
    984  *              available entry if the l2 cache address mac_mask
    985  *              field is all ones, or the last available entry if
    986  *              the mac_mask field has some zeros.  Cache entries
    987  *              are matched from lowest entry to highest entry.
    988  *      addr - l2 cache address
    989  *      index_used - (OUT) l2 cache entry number actually used
    990  * Returns:
    991  *      BCM_E_XXX
    992  */
    993 int
    994 bcm_esw_l2_cache_set(int unit, int index, bcm_l2_cache_addr_t *addr,
    995                  int *index_used)
    996 {
    997 #ifdef BCM_XGS3_SWITCH_SUPPORT
    998     int skip_l2u;
    999     l2u_entry_t l2u_entry;
   1000     bcm_l2_cache_addr_t l2_addr;
   1001 
   1002 #if defined(BCM_TOMAHAWK3_SUPPORT)
   1003     /* Added to handle SDK functions calling esw version,
   1004      * instead of Tomahawk3's version
   1005      */
   1006     if (SOC_IS_TOMAHAWK3(unit)) {
   1007         return bcm_tomahawk3_l2_cache_set(unit, index, addr, index_used);
   1008     }
   1009 #endif /* BCM_TOMAHAWK3_SUPPORT  */
   1010 
   1011     if (!SOC_UNIT_VALID(unit)) {
   1012         return BCM_E_UNIT;
   1013     }
   1014     L2_INIT(unit);
   1015 
   1016 #if defined(BCM_TRIUMPH3_SUPPORT)
   1017     if (soc_feature(unit, soc_feature_ism_memory)) {
   1018         return bcm_tr3_l2_cache_set(unit, index, addr, index_used);
   1019     }
   1020 #endif /* BCM_TRIUMPH3_SUPPORT */
   1021 
   1022     skip_l2u = soc_property_get(unit, spn_SKIP_L2_USER_ENTRY, 0);
   1023 
   1024     if (soc_feature(unit, soc_feature_l2_user_table) && !skip_l2u) {
   1025         if (index < -1 || index > soc_mem_index_max(unit, L2_USER_ENTRYm)) {
   1026             return BCM_E_PARAM;
   1027         }
   1028 
   1029         sal_memcpy(&l2_addr, addr, sizeof(bcm_l2_cache_addr_t));
   1030 
   1031         if (soc_feature(unit, soc_feature_overlaid_address_class)) {
   1032             if ((l2_addr.lookup_class > SOC_OVERLAID_ADDR_CLASS_MAX(unit)) ||
   1033                 (l2_addr.lookup_class < 0)) {
   1034                 return (BCM_E_PARAM);
   1035             }
   1036         } else if ((l2_addr.lookup_class > SOC_ADDR_CLASS_MAX(unit)) || 
   1037                    (l2_addr.lookup_class < 0)) {
   1038             return (BCM_E_PARAM);
   1039         }
   1040 
   1041         /* ESW architecture can't support multiple destinations */
   1042         if (BCM_PBMP_NOT_NULL(l2_addr.dest_ports)) {
   1043             return BCM_E_PARAM;
   1044         }
   1045 
   1046         BCM_IF_ERROR_RETURN(
   1047             _bcm_l2_cache_to_l2u(unit, &l2u_entry, &l2_addr));
   1048         
   1049 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_GREYHOUND2_SUPPORT)
   1050         if (soc_mem_is_valid(unit, MY_STATION_TCAMm) &&
   1051             (addr->flags & BCM_L2_CACHE_L3)) {
   1052             int rv;
   1053             if (index == -1) {
   1054                 rv = bcm_td_l2cache_myStation_lookup(unit, &l2_addr, &index);
   1055                 if (BCM_FAILURE(rv)) {
   1056                     /* find the first free index in L2_USER_ENTRY */
   1057                     BCM_IF_ERROR_RETURN
   1058                         (soc_l2u_find_free_entry(unit, &l2u_entry, &index));
   1059                 }
   1060             }
   1061 
   1062             rv = bcm_td_l2cache_myStation_set(unit, index, &l2_addr);
   1063         }
   1064 #endif /* BCM_TRIDENT_SUPPORT || BCM_GREYHOUND2_SUPPORT */
   1065 
   1066         SOC_IF_ERROR_RETURN
   1067             (soc_l2u_insert(unit, &l2u_entry, index, index_used));
   1068 
   1069         return BCM_E_NONE;
   1070     }
   1071 #endif /* BCM_XGS3_SWITCH_SUPPORT */
   1072     return BCM_E_UNAVAIL;
   1073 }
   1074 
   1075 /*
   1076  * Function:
   1077  *      bcm_esw_l2_cache_get
   1078  * Purpose:
   1079  *      Get an L2 cache entry
   1080  * Parameters:
   1081  *      unit - device number
   1082  *      index - l2 cache entry index
   1083  *      size - (OUT) l2 cache address
   1084  * Returns:
   1085  *      BCM_E_XXX
   1086  */
   1087 int
   1088 bcm_esw_l2_cache_get(int unit, int index, bcm_l2_cache_addr_t *addr)
   1089 {
   1090 #ifdef BCM_XGS3_SWITCH_SUPPORT
   1091     int skip_l2u;
   1092     l2u_entry_t l2u_entry;
   1093 
   1094 #if defined(BCM_TOMAHAWK3_SUPPORT)
   1095     /* Added to handle SDK functions calling esw version,
   1096      * instead of Tomahawk3's version
   1097      */
   1098     if (SOC_IS_TOMAHAWK3(unit)) {
   1099         return bcm_tomahawk3_l2_cache_get(unit, index, addr);
   1100     }
   1101 #endif /* BCM_TOMAHAWK3_SUPPORT */
   1102 
   1103     if (!SOC_UNIT_VALID(unit)) {
   1104         return BCM_E_UNIT;
   1105     }
   1106 
   1107     L2_INIT(unit)
   1108 
   1109 #if defined(BCM_TRIUMPH3_SUPPORT)
   1110     if (soc_feature(unit, soc_feature_ism_memory)) {
   1111         return bcm_tr3_l2_cache_get(unit, index, addr);
   1112     }
   1113 #endif /* BCM_TRIUMPH3_SUPPORT */
   1114 
   1115     skip_l2u = soc_property_get(unit, spn_SKIP_L2_USER_ENTRY, 0);
   1116 
   1117     if (soc_feature(unit, soc_feature_l2_user_table) && !skip_l2u) {
   1118         if (index < 0 || index > soc_mem_index_max(unit, L2_USER_ENTRYm)) {
   1119             return BCM_E_PARAM;
   1120         }
   1121 
   1122         SOC_IF_ERROR_RETURN(
   1123             soc_l2u_get(unit, &l2u_entry, index));
   1124 
   1125         BCM_IF_ERROR_RETURN(
   1126             _bcm_l2_cache_from_l2u(unit, addr, &l2u_entry));
   1127 
   1128 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_GREYHOUND2_SUPPORT)
   1129         if (soc_mem_is_valid(unit, MY_STATION_TCAMm) &&
   1130             (addr->flags & BCM_L2_CACHE_L3)) {
   1131             BCM_IF_ERROR_RETURN
   1132                 (bcm_td_l2cache_myStation_get(unit, index, addr));
   1133         }
   1134 #endif /* BCM_TRIDENT_SUPPORT || BCM_GREYHOUND2_SUPPORT */
   1135 
   1136         return BCM_E_NONE;
   1137     }
   1138 #endif /* BCM_XGS3_SWITCH_SUPPORT */
   1139     return BCM_E_UNAVAIL;
   1140 }
   1141 
   1142 /*
   1143  * Function:
   1144  *      bcm_esw_l2_cache_delete
   1145  * Purpose:
   1146  *      Clear an L2 cache entry
   1147  * Parameters:
   1148  *      unit - device number
   1149  *      index - l2 cache entry index
   1150  * Returns:
   1151  *      BCM_E_XXX
   1152  */
   1153 int
   1154 bcm_esw_l2_cache_delete(int unit, int index)
   1155 {
   1156 #ifdef BCM_XGS3_SWITCH_SUPPORT
   1157     int skip_l2u, rv;
   1158 
   1159 #if defined(BCM_TOMAHAWK3_SUPPORT)
   1160     /* Added to handle SDK functions calling esw version,
   1161      * instead of Tomahawk3's version
   1162      */
   1163     if (SOC_IS_TOMAHAWK3(unit)) {
   1164         return bcm_tomahawk3_l2_cache_delete(unit, index);
   1165     }
   1166 #endif /* BCM_TOMAHAWK3_SUPPORT  */
   1167 
   1168     if (!SOC_UNIT_VALID(unit)) {
   1169         return BCM_E_UNIT;
   1170     }
   1171 
   1172     L2_INIT(unit);
   1173 
   1174 #if defined(BCM_TRIUMPH3_SUPPORT)
   1175     if (soc_feature(unit, soc_feature_ism_memory)) {
   1176         return bcm_tr3_l2_cache_delete(unit, index);
   1177     }
   1178 #endif /* BCM_TRIUMPH3_SUPPORT */
   1179 
   1180     skip_l2u = soc_property_get(unit, spn_SKIP_L2_USER_ENTRY, 0);
   1181 
   1182     if (soc_feature(unit, soc_feature_l2_user_table) && !skip_l2u) {
   1183         if (index < 0 || index > soc_mem_index_max(unit, L2_USER_ENTRYm)) {
   1184             return BCM_E_PARAM;
   1185         }
   1186 
   1187         rv = BCM_E_NONE;
   1188         soc_mem_lock(unit, L2_USER_ENTRYm);
   1189 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_GREYHOUND2_SUPPORT)
   1190         if (soc_mem_is_valid(unit, MY_STATION_TCAMm)) {
   1191             l2u_entry_t l2u_entry;
   1192             rv = soc_l2u_get(unit, &l2u_entry, index);
   1193             if (BCM_SUCCESS(rv))  {
   1194                 if ((SOC_MEM_FIELD_VALID(unit, L2_USER_ENTRYm, L3f) &&
   1195                      _l2u_field32_get(unit, &l2u_entry, L3f)) ||
   1196                     (SOC_MEM_FIELD_VALID(unit, L2_USER_ENTRYm, RESERVED_0f) &&
   1197                      _l2u_field32_get(unit, &l2u_entry, RESERVED_0f))) {
   1198                      rv = bcm_td_l2cache_myStation_delete(unit, index);
   1199                 } else if (SOC_IS_KATANAX(unit) || 
   1200                     soc_feature(unit, soc_feature_my_station_tcam_check) ||
   1201                     soc_feature(unit, soc_feature_gh2_my_station)) {
   1202 	                   /* Katana doesn't has L3,RESERVED_0 fields
   1203                               so ignoring return value ! */
   1204                            bcm_td_l2cache_myStation_delete(unit, index);
   1205                 } /* Nothing can be done..!! */
   1206             }
   1207         }
   1208 #endif /* BCM_TRIDENT_SUPPORT || BCM_GREYHOUND2_SUPPORT */
   1209         if (BCM_SUCCESS(rv)) {
   1210             rv = soc_l2u_delete(unit, NULL, index, &index);
   1211         }
   1212         soc_mem_unlock(unit, L2_USER_ENTRYm);
   1213         return rv;
   1214     }
   1215 #endif /* BCM_XGS3_SWITCH_SUPPORT */
   1216     return BCM_E_UNAVAIL;
   1217 }
   1218 
   1219 /*
   1220  * Function:
   1221  *      bcm_esw_l2_cache_delete_all
   1222  * Purpose:
   1223  *      Clear all L2 cache entries
   1224  * Parameters:
   1225  *      unit - device number
   1226  * Returns:
   1227  *      BCM_E_XXX
   1228  */
   1229 int
   1230 bcm_esw_l2_cache_delete_all(int unit)
   1231 {
   1232 #ifdef BCM_XGS3_SWITCH_SUPPORT
   1233     int skip_l2u, rv, index, index_max;
   1234     l2u_entry_t entry;
   1235 
   1236 #if defined(BCM_TOMAHAWK3_SUPPORT)
   1237     /* Added to handle SDK functions calling esw version,
   1238      * instead of Tomahawk3's version
   1239      */
   1240     if (SOC_IS_TOMAHAWK3(unit)) {
   1241         return bcm_tomahawk3_l2_cache_delete_all(unit);
   1242     }
   1243 #endif /* BCM_TOMAHAWK3_SUPPORT  */
   1244 
   1245     if (!SOC_UNIT_VALID(unit)) {
   1246         return BCM_E_UNIT;
   1247     }
   1248 
   1249     L2_INIT(unit);
   1250 
   1251 #if defined(BCM_TRIUMPH3_SUPPORT)
   1252     if (soc_feature(unit, soc_feature_ism_memory)) {
   1253         return bcm_tr3_l2_cache_delete_all(unit);
   1254     }
   1255 #endif /* BCM_TRIUMPH3_SUPPORT */
   1256 
   1257     skip_l2u = soc_property_get(unit, spn_SKIP_L2_USER_ENTRY, 0);
   1258 
   1259     if (soc_feature(unit, soc_feature_l2_user_table) && !skip_l2u) {
   1260         index_max = soc_mem_index_max(unit, L2_USER_ENTRYm);
   1261 
   1262         rv = BCM_E_NONE;
   1263         soc_mem_lock(unit, L2_USER_ENTRYm);
   1264         for (index = 0; index <= index_max; index++) {
   1265 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_GREYHOUND2_SUPPORT)
   1266             if (soc_mem_is_valid(unit, MY_STATION_TCAMm)) {
   1267                 rv = READ_L2_USER_ENTRYm(unit, MEM_BLOCK_ALL, index, &entry);
   1268                 if (BCM_SUCCESS(rv)) {
   1269                     rv = bcm_td_l2cache_myStation_delete(unit, index);
   1270                     /* Ignore entry not found case */
   1271                     if (rv == BCM_E_NOT_FOUND) {
   1272                         rv = BCM_E_NONE;
   1273                     }
   1274                 }
   1275             }
   1276 #endif /* BCM_TRIDENT_SUPPORT || BCM_GREYHOUND2_SUPPORT */
   1277             if (BCM_SUCCESS(rv)) {
   1278                 sal_memset(&entry, 0, sizeof(entry));
   1279                 rv = WRITE_L2_USER_ENTRYm(unit, MEM_BLOCK_ALL, index, &entry);
   1280             }
   1281             if (BCM_FAILURE(rv)) {
   1282                 break;
   1283             }
   1284         }
   1285         soc_mem_unlock(unit, L2_USER_ENTRYm);
   1286         return rv;
   1287     }
   1288 #endif /* BCM_XGS3_SWITCH_SUPPORT */
   1289     return BCM_E_UNAVAIL;
   1290 }