l2cache.c (23267B)
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 <soc/mem.h> 13 #include <soc/debug.h> 14 #include <soc/drv.h> 15 #include <soc/l2u.h> 16 17 #include <bcm/l2.h> 18 #include <bcm/error.h> 19 #include <bcm_int/common/multicast.h> 20 21 #include <bcm_int/esw/port.h> 22 #include <bcm_int/esw/trunk.h> 23 #include <bcm_int/esw/vlan.h> 24 #include <bcm_int/esw/vpn.h> 25 #include <bcm_int/esw/virtual.h> 26 #include <bcm_int/esw/l2.h> 27 #include <bcm_int/esw/stack.h> 28 #ifdef BCM_TRIDENT_SUPPORT 29 #include <bcm_int/esw/trident.h> 30 #endif 31 #if defined(BCM_TRIUMPH3_SUPPORT) 32 #include <bcm_int/esw/triumph3.h> 33 #endif /* BCM_TRIUMPH3_SUPPORT */ 34 35 #include <bcm_int/esw_dispatch.h> 36 #if defined(BCM_TOMAHAWK3_SUPPORT) 37 #include <include/bcm_int/esw/tomahawk3.h> 38 #ifdef BCM_XGS3_SWITCH_SUPPORT 39 40 /* 41 * Function: 42 * _bcm_th3_cache_gport_resolve 43 * Purpose: 44 * Convert destination in a GPORT format to modid port pair or trunk id 45 * Parameters: 46 * unit - Unit number 47 * l2caddr - (IN/OUT) Hardware-independent L2 entry 48 * Returns: 49 * BCM_E_XXX 50 */ 51 STATIC int 52 _bcm_th3_cache_gport_resolve(int unit, bcm_l2_cache_addr_t *l2caddr) 53 { 54 bcm_port_t port; 55 bcm_module_t modid; 56 bcm_trunk_t tgid; 57 int id; 58 59 60 if (BCM_GPORT_IS_SET(l2caddr->dest_port)) { 61 BCM_IF_ERROR_RETURN(_bcm_esw_gport_resolve(unit, l2caddr->dest_port, 62 &modid, &port, &tgid, &id)); 63 64 if (-1 != id) { 65 return (BCM_E_UNAVAIL); 66 } 67 68 /* Trunk GPORT */ 69 if (BCM_TRUNK_INVALID != tgid) { 70 l2caddr->flags |= BCM_L2_CACHE_TRUNK; 71 l2caddr->dest_trunk = tgid; 72 } else { /* MODPORT GPORT */ 73 l2caddr->dest_port = port; 74 l2caddr->dest_modid = modid; /* This may be set to 0 - check */ 75 } 76 } 77 if (BCM_GPORT_IS_SET(l2caddr->src_port)) { 78 BCM_IF_ERROR_RETURN(bcm_esw_port_local_get(unit, l2caddr->src_port, 79 &port)); 80 l2caddr->src_port = port; 81 } 82 83 return BCM_E_NONE; 84 } 85 86 /* 87 * Function: 88 * _bcm_th3_cache_gport_construct 89 * Purpose: 90 * Constract a GPORT destination format from modid port pair or trunk id 91 * Parameters: 92 * unit - Unit number 93 * l2caddr - (IN/OUT) Hardware-independent L2 entry 94 * Returns: 95 * BCM_E_XXX 96 */ 97 STATIC int 98 _bcm_th3_cache_gport_construct(int unit, bcm_l2_cache_addr_t *l2caddr) 99 { 100 bcm_gport_t gport; 101 _bcm_gport_dest_t gport_dst; 102 103 _bcm_gport_dest_t_init(&gport_dst); 104 105 if (l2caddr->flags & BCM_L2_CACHE_TRUNK) { 106 gport_dst.gport_type = BCM_GPORT_TYPE_TRUNK; 107 gport_dst.tgid = l2caddr->dest_trunk; 108 } else { 109 gport_dst.gport_type = BCM_GPORT_TYPE_MODPORT; 110 gport_dst.modid = l2caddr->dest_modid; 111 gport_dst.port = l2caddr->dest_port; 112 } 113 114 115 BCM_IF_ERROR_RETURN(_bcm_esw_gport_construct(unit, &gport_dst, &gport)); 116 117 l2caddr->dest_port = gport; 118 119 gport_dst.gport_type = BCM_GPORT_TYPE_MODPORT; 120 gport_dst.port = l2caddr->src_port; 121 gport_dst.modid = SOC_BASE_MODID(unit); 122 if (gport_dst.modid < 0) { 123 return BCM_E_UNAVAIL; 124 } 125 126 127 BCM_IF_ERROR_RETURN(_bcm_esw_gport_construct(unit, &gport_dst, &gport)); 128 129 l2caddr->src_port = gport; 130 131 return BCM_E_NONE; 132 } 133 134 /* 135 * Function: 136 * _bcm_th3_l2_cache_from_l2u 137 * Purpose: 138 * Convert L2 User table entry to a hardware-independent L2 cache entry. 139 * Parameters: 140 * unit - Unit number 141 * l2caddr - (OUT) Hardware-independent L2 entry 142 * l2u_entry - Firebolt L2 User entry 143 * Returns: 144 * BCM_E_XXX 145 */ 146 STATIC int 147 _bcm_th3_l2_cache_from_l2u(int unit, 148 bcm_l2_cache_addr_t *l2caddr, l2u_entry_t *l2u_entry) 149 { 150 l2u_entry_t l2u_mask_entry; 151 bcm_module_t mod_in = 0; 152 bcm_port_t port_in = 0, port_out; 153 uint32 mask[SOC_MAX_MEM_WORDS]; 154 int skip_l2u, isGport, port_field_len, rval; 155 bcm_vlan_t vlan; 156 soc_field_t port_field = 0; 157 158 skip_l2u = soc_property_get(unit, spn_SKIP_L2_USER_ENTRY, 0); 159 160 if (soc_feature(unit, soc_feature_l2_user_table) && !skip_l2u) { 161 162 if (!_l2u_field32_get(unit, l2u_entry, VALIDf)) { 163 return BCM_E_NOT_FOUND; 164 } 165 166 sal_memset(l2caddr, 0, sizeof (*l2caddr)); 167 sal_memset(&l2u_mask_entry, 0, sizeof (l2u_mask_entry)); 168 169 _l2u_field_get(unit, l2u_entry, MASKf, mask); 170 _l2u_field_set(unit, &l2u_mask_entry, KEYf, mask); 171 172 _l2u_mac_addr_get(unit, l2u_entry, MAC_ADDRf, l2caddr->mac); 173 _l2u_mac_addr_get(unit, &l2u_mask_entry, MAC_ADDRf, l2caddr->mac_mask); 174 175 vlan = _l2u_field32_get(unit, l2u_entry, VLAN_IDf); 176 l2caddr->vlan_mask = _l2u_field32_get(unit, &l2u_mask_entry, VLAN_IDf); 177 178 #if defined(INCLUDE_L3) 179 _l2u_field32_get(unit, l2u_entry, KEY_TYPEf); 180 #endif 181 182 l2caddr->vlan = vlan; 183 184 l2caddr->prio = _l2u_field32_get(unit, l2u_entry, PRIf); 185 186 if (_l2u_field32_get(unit, l2u_entry, RPEf)) { 187 l2caddr->flags |= BCM_L2_CACHE_SETPRI; 188 } 189 190 if (_l2u_field32_get(unit, l2u_entry, DO_NOT_LEARN_MACSAf)) { 191 l2caddr->flags |= BCM_L2_CACHE_LEARN_DISABLE; 192 } 193 194 if (_l2u_field32_get(unit, l2u_entry, CPUf)) { 195 l2caddr->flags |= BCM_L2_CACHE_CPU; 196 } 197 198 if (_l2u_field32_get(unit, l2u_entry, BPDUf)) { 199 l2caddr->flags |= BCM_L2_CACHE_BPDU; 200 } 201 202 if (_l2u_field32_get(unit, l2u_entry, L2_PROTOCOL_PKTf)) { 203 l2caddr->flags |= BCM_L2_CACHE_PROTO_PKT; 204 } 205 206 if (_l2u_field32_get(unit, l2u_entry, DST_DISCARDf)) { 207 l2caddr->flags |= BCM_L2_CACHE_DISCARD; 208 } 209 210 if (soc_feature(unit, soc_feature_trunk_group_overlay)) { 211 if (_l2u_field32_get(unit, l2u_entry, Tf)) { 212 l2caddr->flags |= BCM_L2_CACHE_TRUNK; 213 l2caddr->dest_trunk = _l2u_field32_get(unit, l2u_entry, TGIDf); 214 } else { 215 mod_in = 0; 216 port_in = _l2u_field32_get(unit, l2u_entry, PORT_NUMf); 217 port_field = PORT_NUMf; 218 } 219 } 220 221 222 if (BCM_MAC_IS_MCAST(l2caddr->mac)) { 223 l2caddr->flags |= BCM_L2_CACHE_MULTICAST; 224 l2caddr->dest_modid = mod_in; 225 l2caddr->dest_port = port_in; 226 port_field_len = soc_mem_field_length(unit, L2_USER_ENTRYm, 227 port_field); 228 229 /* If MACDA is MC, HW interprets value encoded in MODULE_IDf 230 and PORT_FIELD as L2MC_INDEX */ 231 l2caddr->group = (port_in & ((1 << port_field_len) - 1)); 232 /* Translate l2mc index */ 233 BCM_IF_ERROR_RETURN( 234 bcm_esw_switch_control_get(unit, bcmSwitchL2McIdxRetType, 235 &rval)); 236 if (rval) { 237 _BCM_MULTICAST_GROUP_SET(l2caddr->group, _BCM_MULTICAST_TYPE_L2, 238 l2caddr->group); 239 } 240 } 241 242 if (!((l2caddr->flags & BCM_L2_CACHE_TRUNK) || 243 (l2caddr->flags & BCM_L2_CACHE_MULTICAST))) { 244 port_out = port_in; 245 l2caddr->dest_modid = 0; 246 l2caddr->dest_port = port_out; 247 } 248 BCM_IF_ERROR_RETURN( 249 bcm_esw_switch_control_get(unit, bcmSwitchUseGport, &isGport)); 250 251 if (isGport) { 252 BCM_IF_ERROR_RETURN(_bcm_th3_cache_gport_construct(unit, l2caddr)); 253 } 254 255 l2caddr->lookup_class = _l2u_field32_get(unit, l2u_entry, CLASS_IDf); 256 257 return BCM_E_NONE; 258 } 259 260 return BCM_E_UNAVAIL; 261 } 262 263 /* 264 * Function: 265 * _bcm_th3_l2_cache_to_l2u 266 * Purpose: 267 * Convert a hardware-independent L2 cache entry to a L2 User table entry. 268 * Parameters: 269 * unit - Unit number 270 * l2u_entry - (OUT) Firebolt L2 User entry 271 * l2caddr - Hardware-independent L2 entry 272 * Returns: 273 * BCM_E_XXX 274 * Note: 275 * BCM_L2_CACHE_L3, BCM_L2_CACHE_MIRROR are not supported 276 */ 277 STATIC int 278 _bcm_th3_l2_cache_to_l2u(int unit, 279 l2u_entry_t *l2u_entry, bcm_l2_cache_addr_t *l2caddr) 280 { 281 l2u_entry_t l2u_mask_entry; 282 bcm_module_t mod_in; 283 bcm_port_t port_in, port_out; 284 uint32 mask[SOC_MAX_MEM_WORDS]; 285 soc_field_t port_field = 0; 286 int skip_l2u, isGport; 287 bcm_vlan_t vlan; 288 int port_field_len; 289 290 int valid_bit = 0; 291 skip_l2u = soc_property_get(unit, spn_SKIP_L2_USER_ENTRY, 0); 292 293 if (soc_feature(unit, soc_feature_l2_user_table) && !skip_l2u) { 294 295 if (l2caddr->flags & BCM_L2_CACHE_SETPRI) { 296 if (l2caddr->prio < 0 || l2caddr->prio > 15) { 297 return BCM_E_PARAM; 298 } 299 } 300 301 if (BCM_GPORT_IS_SET(l2caddr->dest_port) || 302 BCM_GPORT_IS_SET(l2caddr->src_port)) { 303 BCM_IF_ERROR_RETURN(_bcm_th3_cache_gport_resolve(unit, l2caddr)); 304 isGport = 1; 305 } else { 306 isGport = 0; 307 } 308 309 sal_memset(l2u_entry, 0, sizeof (*l2u_entry)); 310 sal_memset(&l2u_mask_entry, 0, sizeof (l2u_mask_entry)); 311 312 valid_bit = 1 << soc_mem_field_length(unit, L2_USER_ENTRYm, VALIDf); 313 valid_bit -= 1; 314 _l2u_field32_set(unit, l2u_entry, VALIDf, valid_bit); 315 316 vlan = l2caddr->vlan; 317 318 _l2u_field32_set(unit, l2u_entry, KEY_TYPEf, 0); 319 _l2u_field32_set(unit, &l2u_mask_entry, KEY_TYPEf, 0); 320 321 if (l2caddr->flags & BCM_L2_CACHE_PROTO_PKT) { 322 _l2u_field32_set(unit, l2u_entry, L2_PROTOCOL_PKTf, 1); 323 } 324 325 _l2u_field32_set(unit, l2u_entry, VLAN_IDf, vlan); 326 _l2u_field32_set(unit, &l2u_mask_entry, VLAN_IDf, l2caddr->vlan_mask); 327 328 _l2u_mac_addr_set(unit, l2u_entry, MAC_ADDRf, l2caddr->mac); 329 _l2u_mac_addr_set(unit, &l2u_mask_entry, MAC_ADDRf, l2caddr->mac_mask); 330 331 _l2u_field_get(unit, &l2u_mask_entry, KEYf, mask); 332 333 _l2u_field_set(unit, l2u_entry, MASKf, mask); 334 335 if (l2caddr->flags & BCM_L2_CACHE_SETPRI) { 336 _l2u_field32_set(unit, l2u_entry, PRIf, l2caddr->prio); 337 _l2u_field32_set(unit, l2u_entry, RPEf, 1); 338 } 339 340 if (l2caddr->flags & BCM_L2_CACHE_LEARN_DISABLE) { 341 _l2u_field32_set(unit, l2u_entry, DO_NOT_LEARN_MACSAf, 1); 342 } 343 344 if (l2caddr->flags & BCM_L2_CACHE_CPU) { 345 _l2u_field32_set(unit, l2u_entry, CPUf, 1); 346 } 347 348 if (l2caddr->flags & BCM_L2_CACHE_BPDU) { 349 _l2u_field32_set(unit, l2u_entry, BPDUf, 1); 350 } 351 352 if (l2caddr->flags & BCM_L2_CACHE_DISCARD) { 353 _l2u_field32_set(unit, l2u_entry, DST_DISCARDf, 1); 354 } 355 356 if (soc_feature(unit, soc_feature_trunk_group_overlay)) { 357 if (l2caddr->flags & BCM_L2_CACHE_TRUNK) { 358 _l2u_field32_set(unit, l2u_entry, Tf, 1); 359 _l2u_field32_set(unit, l2u_entry, TGIDf, l2caddr->dest_trunk); 360 } else { 361 port_field = PORT_NUMf; 362 } 363 } 364 365 if (!((l2caddr->flags & BCM_L2_CACHE_TRUNK) || 366 (l2caddr->flags & BCM_L2_CACHE_MULTICAST))) { 367 mod_in = l2caddr->dest_modid; 368 port_in = l2caddr->dest_port; 369 if (!isGport) { 370 PORT_DUALMODID_VALID(unit, port_in); 371 } 372 373 if (!SOC_MODID_ADDRESSABLE(unit, mod_in)) { 374 return BCM_E_BADID; 375 } 376 377 if (!SOC_PORT_ADDRESSABLE(unit, port_in)) { 378 return BCM_E_PORT; 379 } 380 381 port_out = port_in; 382 383 _l2u_field32_set(unit, l2u_entry, port_field, port_out); 384 } 385 386 387 if (l2caddr->flags & BCM_L2_CACHE_MULTICAST) { 388 if (_BCM_MULTICAST_IS_SET(l2caddr->group)) { 389 if (_BCM_MULTICAST_IS_L2(l2caddr->group)) { 390 port_field_len = soc_mem_field_length(unit, L2_USER_ENTRYm, 391 port_field); 392 /* If MACDA is MC, HW interprets value encoded in 393 * PORT_FIELD as L2MC_INDEX 394 */ 395 _l2u_field32_set(unit, l2u_entry, port_field, 396 (_BCM_MULTICAST_ID_GET(l2caddr->group) & 397 ((1 << port_field_len) - 1))); 398 } else { 399 return BCM_E_PARAM; 400 } 401 } 402 } 403 404 _l2u_field32_set(unit, l2u_entry, CLASS_IDf, l2caddr->lookup_class); 405 406 return BCM_E_NONE; 407 } 408 409 return BCM_E_UNAVAIL; 410 } 411 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 412 413 /* 414 * Function: 415 * bcm_th3_l2_cache_init 416 * Purpose: 417 * Initialize the L2 cache 418 * Parameters: 419 * unit - device number 420 * Returns: 421 * BCM_E_XXX 422 * Notes: 423 * Clears all entries and preloads a few BCM_L2_CACHE_BPDU 424 * entries to match previous generation of devices. 425 */ 426 int 427 bcm_th3_l2_cache_init(int unit) 428 { 429 #ifdef BCM_XGS3_SWITCH_SUPPORT 430 int skip_l2u; 431 432 if (!SOC_UNIT_VALID(unit)) { 433 return BCM_E_UNIT; 434 } 435 436 skip_l2u = soc_property_get(unit, spn_SKIP_L2_USER_ENTRY, 0); 437 438 if (soc_feature(unit, soc_feature_l2_user_table) && !skip_l2u) { 439 bcm_l2_cache_addr_t addr; 440 l2u_entry_t entry; 441 int index; 442 443 if (!SAL_BOOT_QUICKTURN && !SAL_BOOT_XGSSIM) { 444 SOC_IF_ERROR_RETURN 445 (soc_mem_clear(unit, L2_USER_ENTRYm, COPYNO_ALL, TRUE)); 446 } 447 448 bcm_l2_cache_addr_t_init(&addr); 449 addr.flags = BCM_L2_CACHE_CPU | BCM_L2_CACHE_BPDU; 450 /* Set default BPDU addresses (01:80:c2:00:00:00) */ 451 ENET_SET_MACADDR(addr.mac, _soc_mac_spanning_tree); 452 ENET_SET_MACADDR(addr.mac_mask, _soc_mac_all_ones); 453 addr.dest_modid = 0; 454 addr.dest_port = CMIC_PORT(unit); 455 BCM_IF_ERROR_RETURN(_bcm_th3_l2_cache_to_l2u(unit, &entry, &addr)); 456 SOC_IF_ERROR_RETURN(soc_l2u_insert(unit, &entry, -1, &index)); 457 458 soc_mem_field32_set(unit, L2_USER_ENTRYm, &entry, L2_PROTOCOL_PKTf, 1); 459 soc_mem_field32_set(unit, L2_USER_ENTRYm, &entry, KEY_TYPEf, 0); 460 SOC_IF_ERROR_RETURN(soc_l2u_insert(unit, &entry, -1, &index)); 461 462 if (!SAL_BOOT_QUICKTURN && !SAL_BOOT_XGSSIM) { 463 /* Set 01:80:c2:00:00:10 */ 464 addr.mac[5] = 0x10; 465 BCM_IF_ERROR_RETURN(_bcm_th3_l2_cache_to_l2u(unit, &entry, &addr)); 466 SOC_IF_ERROR_RETURN(soc_l2u_insert(unit, &entry, -1, &index)); 467 /* Set 01:80:c2:00:00:0x */ 468 addr.mac[5] = 0x00; 469 addr.mac_mask[5] = 0xf0; 470 BCM_IF_ERROR_RETURN(_bcm_th3_l2_cache_to_l2u(unit, &entry, &addr)); 471 SOC_IF_ERROR_RETURN(soc_l2u_insert(unit, &entry, -1, &index)); 472 /* Set 01:80:c2:00:00:2x */ 473 addr.mac[5] = 0x20; 474 BCM_IF_ERROR_RETURN(_bcm_th3_l2_cache_to_l2u(unit, &entry, &addr)); 475 SOC_IF_ERROR_RETURN(soc_l2u_insert(unit, &entry, -1, &index)); 476 } 477 478 return BCM_E_NONE; 479 } 480 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 481 return BCM_E_UNAVAIL; 482 } 483 484 /* 485 * Function: 486 * bcm_tomahawk3_l2_cache_set 487 * Purpose: 488 * Set an L2 cache entry 489 * Parameters: 490 * unit - device number 491 * index - l2 cache entry number (or -1) 492 * If -1 is given then the entry used will be the first 493 * available entry if the l2 cache address mac_mask 494 * field is all ones, or the last available entry if 495 * the mac_mask field has some zeros. Cache entries 496 * are matched from lowest entry to highest entry. 497 * addr - l2 cache address 498 * index_used - (OUT) l2 cache entry number actually used 499 * Returns: 500 * BCM_E_XXX 501 */ 502 int 503 bcm_tomahawk3_l2_cache_set(int unit, int index, bcm_l2_cache_addr_t *addr, 504 int *index_used) 505 { 506 #ifdef BCM_XGS3_SWITCH_SUPPORT 507 int skip_l2u; 508 l2u_entry_t l2u_entry; 509 bcm_l2_cache_addr_t l2_addr; 510 511 if (!SOC_UNIT_VALID(unit)) { 512 return BCM_E_UNIT; 513 } 514 515 TH3_L2_INIT(unit); 516 517 skip_l2u = soc_property_get(unit, spn_SKIP_L2_USER_ENTRY, 0); 518 519 if (soc_feature(unit, soc_feature_l2_user_table) && !skip_l2u) { 520 if (index < -1 || index > soc_mem_index_max(unit, L2_USER_ENTRYm)) { 521 return BCM_E_PARAM; 522 } 523 524 sal_memcpy(&l2_addr, addr, sizeof(bcm_l2_cache_addr_t)); 525 526 if (soc_feature(unit, soc_feature_overlaid_address_class)) { 527 if ((l2_addr.lookup_class > SOC_OVERLAID_ADDR_CLASS_MAX(unit)) || 528 (l2_addr.lookup_class < 0)) { 529 return (BCM_E_PARAM); 530 } 531 } else if ((l2_addr.lookup_class > SOC_ADDR_CLASS_MAX(unit)) || 532 (l2_addr.lookup_class < 0)) { 533 return (BCM_E_PARAM); 534 } 535 536 /* ESW architecture can't support multiple destinations */ 537 if (BCM_PBMP_NOT_NULL(l2_addr.dest_ports)) { 538 return BCM_E_PARAM; 539 } 540 541 BCM_IF_ERROR_RETURN(_bcm_th3_l2_cache_to_l2u(unit, &l2u_entry, 542 &l2_addr)); 543 544 #if defined(BCM_TRIDENT_SUPPORT) 545 if (addr->flags & BCM_L2_CACHE_L3) { 546 int rv; 547 if (index == -1) { 548 rv = bcm_td_l2cache_myStation_lookup(unit, &l2_addr, &index); 549 if (BCM_FAILURE(rv)) { 550 /* Find the first free index in L2_USER_ENTRY */ 551 BCM_IF_ERROR_RETURN 552 (soc_l2u_find_free_entry(unit, &l2u_entry, &index)); 553 } 554 } 555 556 rv = bcm_td_l2cache_myStation_set(unit, index, &l2_addr); 557 } 558 #endif /* BCM_TRIDENT_SUPPORT*/ 559 560 SOC_IF_ERROR_RETURN 561 (soc_l2u_insert(unit, &l2u_entry, index, index_used)); 562 563 return BCM_E_NONE; 564 } 565 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 566 return BCM_E_UNAVAIL; 567 } 568 569 /* 570 * Function: 571 * bcm_tomahawk3_l2_cache_get 572 * Purpose: 573 * Get an L2 cache entry 574 * Parameters: 575 * unit - device number 576 * index - l2 cache entry index 577 * size - (OUT) l2 cache address 578 * Returns: 579 * BCM_E_XXX 580 */ 581 int 582 bcm_tomahawk3_l2_cache_get(int unit, int index, bcm_l2_cache_addr_t *addr) 583 { 584 #ifdef BCM_XGS3_SWITCH_SUPPORT 585 int skip_l2u; 586 l2u_entry_t l2u_entry; 587 588 if (!SOC_UNIT_VALID(unit)) { 589 return BCM_E_UNIT; 590 } 591 592 TH3_L2_INIT(unit) 593 594 skip_l2u = soc_property_get(unit, spn_SKIP_L2_USER_ENTRY, 0); 595 596 if (soc_feature(unit, soc_feature_l2_user_table) && !skip_l2u) { 597 if (index < 0 || index > soc_mem_index_max(unit, L2_USER_ENTRYm)) { 598 return BCM_E_PARAM; 599 } 600 601 SOC_IF_ERROR_RETURN(soc_l2u_get(unit, &l2u_entry, index)); 602 603 BCM_IF_ERROR_RETURN(_bcm_th3_l2_cache_from_l2u(unit, addr, &l2u_entry)); 604 605 #if defined(BCM_TRIDENT_SUPPORT) 606 if (addr->flags & BCM_L2_CACHE_L3) { 607 BCM_IF_ERROR_RETURN(bcm_td_l2cache_myStation_get(unit, index, 608 addr)); 609 } 610 #endif /* BCM_TRIDENT_SUPPORT || BCM_GREYHOUND2_SUPPORT */ 611 612 return BCM_E_NONE; 613 } 614 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 615 return BCM_E_UNAVAIL; 616 } 617 618 /* 619 * Function: 620 * bcm_tomahawk3_l2_cache_size_get 621 * Purpose: 622 * Get number of L2 cache entries 623 * Parameters: 624 * unit - device number 625 * size - (OUT) number of entries in cache 626 * Returns: 627 * BCM_E_XXX 628 */ 629 int 630 bcm_tomahawk3_l2_cache_size_get(int unit, int *size) 631 { 632 #ifdef BCM_XGS3_SWITCH_SUPPORT 633 int skip_l2u; 634 635 if (!SOC_UNIT_VALID(unit)) { 636 return BCM_E_UNIT; 637 } 638 639 skip_l2u = soc_property_get(unit, spn_SKIP_L2_USER_ENTRY, 0); 640 641 if (soc_feature(unit, soc_feature_l2_user_table) && !skip_l2u) { 642 *size = soc_mem_index_count(unit, L2_USER_ENTRYm); 643 644 return 0; 645 } 646 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 647 return BCM_E_UNAVAIL; 648 } 649 650 int 651 bcm_tomahawk3_l2_cache_init(int unit) 652 { 653 return bcm_th3_l2_cache_init(unit); 654 } 655 656 /* 657 * Function: 658 * bcm_tomahawk3_l2_cache_delete 659 * Purpose: 660 * Clear an L2 cache entry 661 * Parameters: 662 * unit - device number 663 * index - l2 cache entry index 664 * Returns: 665 * BCM_E_XXX 666 */ 667 int 668 bcm_tomahawk3_l2_cache_delete(int unit, int index) 669 { 670 #ifdef BCM_XGS3_SWITCH_SUPPORT 671 int skip_l2u, rv; 672 673 if (!SOC_UNIT_VALID(unit)) { 674 return BCM_E_UNIT; 675 } 676 677 TH3_L2_INIT(unit); 678 679 skip_l2u = soc_property_get(unit, spn_SKIP_L2_USER_ENTRY, 0); 680 681 if (soc_feature(unit, soc_feature_l2_user_table) && !skip_l2u) { 682 l2u_entry_t l2u_entry; 683 684 if (index < 0 || index > soc_mem_index_max(unit, L2_USER_ENTRYm)) { 685 return BCM_E_PARAM; 686 } 687 688 rv = BCM_E_NONE; 689 soc_mem_lock(unit, L2_USER_ENTRYm); 690 691 #if defined(BCM_TRIDENT_SUPPORT) 692 rv = soc_l2u_get(unit, &l2u_entry, index); 693 if (BCM_SUCCESS(rv)) { 694 /* TH3 doesn't have L3,RESERVED_0 fields, ignoring return value, 695 * as done in legacy code 696 */ 697 bcm_td_l2cache_myStation_delete(unit, index); 698 } 699 #endif /* BCM_TRIDENT_SUPPORT */ 700 701 if (BCM_SUCCESS(rv)) { 702 rv = soc_l2u_delete(unit, NULL, index, &index); 703 } 704 705 soc_mem_unlock(unit, L2_USER_ENTRYm); 706 return rv; 707 } 708 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 709 return BCM_E_UNAVAIL; 710 } 711 712 /* 713 * Function: 714 * bcm_tomahawk3_l2_cache_delete_all 715 * Purpose: 716 * Clear all L2 cache entries 717 * Parameters: 718 * unit - device number 719 * Returns: 720 * BCM_E_XXX 721 */ 722 int 723 bcm_tomahawk3_l2_cache_delete_all(int unit) 724 { 725 #ifdef BCM_XGS3_SWITCH_SUPPORT 726 int skip_l2u, rv, index, index_max; 727 l2u_entry_t entry; 728 729 if (!SOC_UNIT_VALID(unit)) { 730 return BCM_E_UNIT; 731 } 732 733 TH3_L2_INIT(unit); 734 735 skip_l2u = soc_property_get(unit, spn_SKIP_L2_USER_ENTRY, 0); 736 737 if (soc_feature(unit, soc_feature_l2_user_table) && !skip_l2u) { 738 index_max = soc_mem_index_max(unit, L2_USER_ENTRYm); 739 740 rv = BCM_E_NONE; 741 soc_mem_lock(unit, L2_USER_ENTRYm); 742 for (index = 0; index <= index_max; index++) { 743 #if defined(BCM_TRIDENT_SUPPORT) 744 rv = READ_L2_USER_ENTRYm(unit, MEM_BLOCK_ALL, index, &entry); 745 if (BCM_SUCCESS(rv)) { 746 rv = bcm_td_l2cache_myStation_delete(unit, index); 747 /* Ignore entry not found case 748 * (same action as legacy code) 749 */ 750 if (rv == BCM_E_NOT_FOUND) { 751 rv = BCM_E_NONE; 752 } 753 } 754 #endif /* BCM_TRIDENT_SUPPORT */ 755 if (BCM_SUCCESS(rv)) { 756 sal_memset(&entry, 0, sizeof(entry)); 757 rv = WRITE_L2_USER_ENTRYm(unit, MEM_BLOCK_ALL, index, &entry); 758 } 759 if (BCM_FAILURE(rv)) { 760 break; 761 } 762 } 763 soc_mem_unlock(unit, L2_USER_ENTRYm); 764 return rv; 765 } 766 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 767 return BCM_E_UNAVAIL; 768 } 769 #endif /* BCM_TOMAHAWK3_SUPPORT */