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, ®val64)); 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 }