l2.c (282044B)
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 - Broadcom StrataSwitch Layer-2 switch API. 8 */ 9 10 #include <sal/core/libc.h> 11 #include <shared/bsl.h> 12 #include <soc/mem.h> 13 #include <soc/profile_mem.h> 14 #include <soc/debug.h> 15 #include <soc/drv.h> 16 #include <soc/l2x.h> 17 #if defined(BCM_TRIUMPH3_SUPPORT) 18 #include <soc/triumph3.h> 19 #endif /* BCM_TRIUMPH3_SUPPORT */ 20 #ifdef BCM_WARM_BOOT_SUPPORT 21 #include <soc/scache.h> 22 #endif /* BCM_WARM_BOOT_SUPPORT */ 23 24 #include <bcm/l2.h> 25 #include <bcm/error.h> 26 27 #include <bcm_int/esw/mbcm.h> 28 #include <bcm_int/esw/l2.h> 29 #include <bcm_int/esw/vlan.h> 30 #include <bcm_int/esw/trunk.h> 31 #include <bcm_int/esw/stack.h> 32 #if defined(BCM_FIREBOLT_SUPPORT) 33 #include <bcm_int/esw/firebolt.h> 34 #endif /* BCM_FIREBOLT_SUPPORT */ 35 #if defined(BCM_TRX_SUPPORT) 36 #include <bcm_int/esw/triumph.h> 37 #include <bcm_int/esw/trx.h> 38 #include <bcm_int/esw/virtual.h> 39 #include <soc/triumph.h> 40 #endif /* BCM_TRX_SUPPORT */ 41 #include <bcm_int/esw/mpls.h> 42 #include <bcm_int/esw/mim.h> 43 #include <bcm_int/esw/trident.h> 44 #if defined(BCM_TRIUMPH3_SUPPORT) 45 #include <bcm_int/esw/triumph3.h> 46 #endif /* BCM_TRIUMPH3_SUPPORT */ 47 #if defined(BCM_TRIDENT2_SUPPORT) 48 #include <soc/trident2.h> 49 #include <bcm_int/esw/trident2.h> 50 #endif /* BCM_TRIDENT2_SUPPORT */ 51 #if defined(BCM_KATANA2_SUPPORT) 52 #include <bcm_int/esw/subport.h> 53 #include <bcm_int/esw/katana2.h> 54 #endif /* BCM_KATANA2_SUPPORT */ 55 #if defined(BCM_HURRICANE3_SUPPORT) 56 #include <soc/hurricane3.h> 57 #endif /* BCM_HURRICANE3_SUPPORT */ 58 #if defined(BCM_GREYHOUND2_SUPPORT) 59 #include <soc/greyhound2.h> 60 #endif /* BCM_GREYHOUND2_SUPPORT */ 61 #if defined(BCM_HGPROXY_COE_SUPPORT) 62 #include <bcm_int/esw/xgs5.h> 63 #endif /* BCM_HGPROXY_COE_SUPPORT */ 64 #ifdef BCM_WARM_BOOT_SUPPORT 65 #include <bcm_int/esw/switch.h> 66 #endif /* BCM_WARM_BOOT_SUPPORT */ 67 #if defined(BCM_TRIDENT3_SUPPORT) 68 #include <soc/esw/flow_db.h> 69 #include <bcm_int/esw/trident3.h> 70 #endif /* BCM_TRIDENT3_SUPPORT */ 71 72 #if defined(BCM_TSN_SUPPORT) 73 #include <bcm_int/esw/tsn.h> 74 #endif /* BCM_TSN_SUPPORT */ 75 76 #include <bcm_int/esw_dispatch.h> 77 #if defined(BCM_TOMAHAWK3_SUPPORT) 78 #include <bcm_int/tomahawk3_dispatch.h> 79 #include <bcm_int/esw/tomahawk3.h> 80 #endif /* BCM_TOMAHAWK3_SUPPORT */ 81 82 /**************************************************************** 83 * 84 * L2 software tables, per unit. 85 */ 86 87 int _l2_init[BCM_MAX_NUM_UNITS]; 88 89 #if defined(BCM_TRX_SUPPORT) 90 STATIC soc_profile_mem_t *_bcm_l2_port_cbl_profile[BCM_MAX_NUM_UNITS]; 91 #endif /* BCM_TRX_SUPPORT */ 92 _bcm_l2_match_ctrl_t *_bcm_l2_match_ctrl[BCM_MAX_NUM_UNITS]; 93 94 /**************************************************************** 95 * 96 * L2 learn limit software representation, per unit. 97 */ 98 99 #define BCM_MAC_LIMIT_MAX (soc_mem_index_count(unit, L2Xm) - 1) 100 101 /* forward declaration */ 102 static int _bcm_l2_bpdu_init(int unit); 103 STATIC int _bcm_esw_l2_replace(int unit, uint32 flags, uint32 int_flags, 104 bcm_l2_addr_t *match_addr, 105 bcm_module_t new_module, bcm_port_t new_port, 106 bcm_trunk_t new_trunk, 107 bcm_l2_traverse_cb trav_fn, void *user_data); 108 #if defined(BCM_TRX_SUPPORT) || defined(BCM_RAPTOR_SUPPORT) 109 STATIC int _bcm_l2_learn_limit_init(int unit); 110 STATIC int _bcm_l2_learn_limit_porttrunk_set(int unit, int port_tgid, 111 uint32 flags, int limit); 112 STATIC int _bcm_l2_learn_limit_port_set(int unit, bcm_port_t port, 113 uint32 flags, int limit); 114 STATIC int _bcm_l2_learn_limit_trunk_set(int unit, bcm_trunk_t trunk, 115 uint32 flags, int limit); 116 #endif /* BCM_TRX_SUPPORT || BCM_RAPTOR_SUPPORT */ 117 118 /* L2 (vlan, port) tuple structure */ 119 typedef struct _bcm_l2_vlan_port_pair_s { 120 /* Array of PBMP with max VLAN size, the first 0-4095 PBMP entries 121 in the array are for max number of VLANs supported, the 4096th 122 i.e pbm[BCM_VLAN_MAX+1]th entry in the array is to maintain a list 123 of PBMPs for invalid VLANs (used for delete by gport operation). */ 124 bcm_pbmp_t pbm[BCM_VLAN_MAX+2]; 125 } _bcm_l2_vlan_port_pair_t; 126 127 typedef struct _bcm_l2_vlan_trunk_pair_s { 128 SHR_BITDCL *tbm[BCM_VLAN_MAX+2]; 129 } _bcm_l2_vlan_trunk_pair_t; 130 131 typedef struct _bcm_l2_vlan_vp_pair_s { 132 SHR_BITDCL *vpbm[BCM_VLAN_MAX+2]; 133 } _bcm_l2_vlan_vp_pair_t; 134 135 typedef struct _bcm_l2_del_vlan_port_pair_s { 136 uint32 flags; /* BCM_L2_AUTH_XXX flags. */ 137 uint32 replace_flags; /* BCM_L2_REPLACE_XXX flags */ 138 bcm_vlan_vector_t del_by_vlan_vec; /* Vlan vector represents 139 delete by vlan */ 140 _bcm_l2_vlan_port_pair_t *mod_pair_arr; /* Reference to Array of 141 (vlan,port) for max modules */ 142 _bcm_l2_vlan_trunk_pair_t *unit_pair_arr; /* Reference to Array of 143 (vlan,tid) for each unit */ 144 _bcm_l2_vlan_vp_pair_t *vp_pair_arr; /* Reference to Array of 145 (vlan,vp) for each unit */ 146 SHR_BITDCL **vfi_pair_arr; /* Reference to Array of 147 (vfi,vp) for each unit */ 148 SHR_BITDCL *del_by_vfi_vec; /* VFI vector */ 149 } _bcm_l2_del_vlan_port_pair_t; 150 151 typedef enum l2x_memacc_field_e { 152 _BCM_L2_MEMACC_VALID, 153 _BCM_L2_MEMACC_KEY_TYPE, 154 _BCM_L2_MEMACC_NUM 155 } l2x_memacc_field_t; 156 157 STATIC uint32 _l2_dbg_matched_entries[SOC_MAX_NUM_DEVICES], 158 _l2_dbg_unmatched_entries[SOC_MAX_NUM_DEVICES]; 159 160 #ifdef BCM_WARM_BOOT_SUPPORT 161 STATIC int _bcm_esw_l2_wb_alloc(int unit); 162 STATIC int _bcm_esw_l2_wb_recover(int unit); 163 #endif /* BCM_WARM_BOOT_SUPPORT */ 164 165 /* just need to clear SRC or DES hit bit. Customers may call API bcm_esw_l2_replace 166 * with parameter *match_addr which value is NULL */ 167 #define _CLEAR_ALL_ENTRIES_SRC_OR_DES_HIT_BIT(flag) \ 168 (!(flag & (BCM_L2_REPLACE_MATCH_VLAN |\ 169 BCM_L2_REPLACE_MATCH_MAC |\ 170 BCM_L2_REPLACE_MATCH_DEST)) &&\ 171 (flag & (BCM_L2_REPLACE_DES_HIT_CLEAR |\ 172 BCM_L2_REPLACE_SRC_HIT_CLEAR))) 173 /* 174 * Function: 175 * _bcm_esw_l2_gport_parse 176 * Description: 177 * Parse gport in the l2 table 178 * Parameters: 179 * unit - [IN] StrataSwitch PCI device unit number (driver internal). 180 * l2addr - [IN/OUT] l2 addr structure to parse and fill 181 * sub_port - [OUT] Virtual port group (-1 if not supported) 182 * mpls_port - [OUT] MPLS port (-1 if not supported) 183 * Returns: 184 * BCM_E_XXX 185 */ 186 int 187 _bcm_esw_l2_gport_parse(int unit, bcm_l2_addr_t *l2addr, 188 _bcm_l2_gport_params_t *params) 189 { 190 int id; 191 bcm_port_t _port; 192 bcm_trunk_t _trunk; 193 bcm_module_t _modid, _mymodid; 194 195 if ((NULL == l2addr) || (NULL == params)){ 196 return BCM_E_PARAM; 197 } 198 199 params->param0 = -1; 200 params->param1 = -1; 201 params->type = 0; 202 203 BCM_IF_ERROR_RETURN( 204 _bcm_esw_gport_resolve(unit, l2addr->port, &_modid, &_port, 205 &_trunk, &id)); 206 207 BCM_IF_ERROR_RETURN( 208 bcm_esw_stk_my_modid_get(unit, &_mymodid)); 209 210 211 if ((BCM_TRUNK_INVALID != _trunk) && (-1 == id)) { 212 params->param0 = _trunk; 213 params->type = _SHR_GPORT_TYPE_TRUNK; 214 return BCM_E_NONE; 215 } 216 217 if ((-1 != _port) && (-1 == id)) { 218 params->param0 = _port; 219 if ((_port == CMIC_PORT(unit)) && (_modid == _mymodid)) { 220 params->type = _SHR_GPORT_TYPE_LOCAL_CPU; 221 return BCM_E_NONE; 222 } 223 params->param1 = _modid; 224 params->type = _SHR_GPORT_TYPE_MODPORT; 225 return BCM_E_NONE; 226 } 227 228 if (-1 != id) { 229 params->param0 = id; 230 if (BCM_GPORT_IS_SUBPORT_GROUP(l2addr->port)) { 231 params->type = _SHR_GPORT_TYPE_SUBPORT_GROUP; 232 } else if (BCM_GPORT_IS_SUBPORT_PORT(l2addr->port)) { 233 params->type = _SHR_GPORT_TYPE_SUBPORT_PORT; 234 235 #if defined(BCM_HGPROXY_COE_SUPPORT) 236 if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) && 237 _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, l2addr->port)) { 238 params->param0 = _port; 239 params->param1 = _modid; 240 } 241 #endif 242 #if defined(BCM_KATANA2_SUPPORT) 243 if (_BCM_KT2_GPORT_IS_LINKPHY_OR_SUBTAG_SUBPORT_GPORT(unit, 244 l2addr->port)) { 245 params->param0 = _port; 246 params->param1 = _modid; 247 } 248 #endif 249 } else if (BCM_GPORT_IS_MPLS_PORT(l2addr->port)){ 250 params->type = _SHR_GPORT_TYPE_MPLS_PORT; 251 } else if (BCM_GPORT_IS_MIM_PORT(l2addr->port)){ 252 params->type = _SHR_GPORT_TYPE_MIM_PORT; 253 } else if (BCM_GPORT_IS_WLAN_PORT(l2addr->port)){ 254 params->type = _SHR_GPORT_TYPE_WLAN_PORT; 255 } else if (BCM_GPORT_IS_TRILL_PORT(l2addr->port)){ 256 params->type = _SHR_GPORT_TYPE_TRILL_PORT; 257 } else if (BCM_GPORT_IS_VLAN_PORT(l2addr->port)){ 258 params->type = _SHR_GPORT_TYPE_VLAN_PORT; 259 } else if (BCM_GPORT_IS_NIV_PORT(l2addr->port)){ 260 params->type = _SHR_GPORT_TYPE_NIV_PORT; 261 } else if (BCM_GPORT_IS_L2GRE_PORT(l2addr->port)){ 262 params->type = _SHR_GPORT_TYPE_L2GRE_PORT; 263 } else if (BCM_GPORT_IS_VXLAN_PORT(l2addr->port)){ 264 params->type = _SHR_GPORT_TYPE_VXLAN_PORT; 265 } else if (BCM_GPORT_IS_FLOW_PORT(l2addr->port)){ 266 params->type = _SHR_GPORT_TYPE_FLOW_PORT; 267 } else if (BCM_GPORT_IS_EXTENDER_PORT(l2addr->port)){ 268 params->type = _SHR_GPORT_TYPE_EXTENDER_PORT; 269 } 270 271 return BCM_E_NONE; 272 } else if (BCM_GPORT_IS_BLACK_HOLE(l2addr->port)) { 273 params->type = _SHR_GPORT_TYPE_BLACK_HOLE; 274 params->param0 = 0; 275 params->param1 = id; 276 277 return BCM_E_NONE; 278 } 279 280 return BCM_E_PORT; 281 } 282 283 /* 284 * Function: 285 * bcm_esw_l2_init 286 * Description: 287 * Perform required initializations to L2 table. 288 * Parameters: 289 * unit - StrataSwitch PCI device unit number (driver internal). 290 * Returns: 291 * BCM_E_XXX 292 */ 293 294 int 295 bcm_esw_l2_init(int unit) 296 { 297 int rv; 298 #ifdef BCM_XGS_SWITCH_SUPPORT 299 int frozen; 300 301 #if defined(BCM_TOMAHAWK3_SUPPORT) 302 /* Added to handle SDK functions calling esw version, 303 * instead of Tomahawk3's version 304 */ 305 if (SOC_IS_TOMAHAWK3(unit)) { 306 return bcm_tomahawk3_l2_init(unit); 307 } 308 #endif /* BCM_TOMAHAWK3_SUPPORT */ 309 310 #if defined(BCM_TRIUMPH3_SUPPORT) 311 if (soc_feature(unit, soc_feature_ism_memory)) { 312 BCM_IF_ERROR_RETURN(bcm_tr3_l2_init(unit)); 313 #ifdef BCM_WARM_BOOT_SUPPORT 314 if (SOC_WARM_BOOT(unit)) { 315 BCM_IF_ERROR_RETURN(_bcm_esw_l2_wb_recover(unit)); 316 } else { 317 BCM_IF_ERROR_RETURN(_bcm_esw_l2_wb_alloc(unit)); 318 } 319 #endif /* BCM_WARM_BOOT_SUPPORT */ 320 _l2_init[unit] = 1; /* some positive value */ 321 return BCM_E_NONE; 322 } 323 #endif /* BCM_TRIUMPH3_SUPPORT */ 324 325 BCM_IF_ERROR_RETURN( 326 soc_l2x_is_frozen(unit, SOC_L2X_FROZEN_WITH_LOCK, &frozen)); 327 if (TRUE == frozen) { 328 return BCM_E_BUSY; 329 } 330 #endif /* BCM_XGS_SWITCH_SUPPORT */ 331 _l2_init[unit] = 0; 332 333 #ifdef BCM_SHADOW_SUPPORT 334 if (soc_feature(unit, soc_feature_no_bridging)) { 335 return BCM_E_NONE; 336 } 337 #endif 338 339 if (SOC_IS_XGS_FABRIC(unit) && !SOC_IS_TITAN2X(unit)&& !SOC_IS_TOMAHAWK2(unit)) { 340 _l2_init[unit] = BCM_E_UNAVAIL; 341 return BCM_E_NONE; 342 } 343 344 if (!SOC_WARM_BOOT(unit) && !SOC_IS_RCPU_ONLY(unit)) { 345 /* Turn off arl aging */ 346 BCM_IF_ERROR_RETURN 347 (SOC_FUNCTIONS(unit)->soc_age_timer_set(unit, 0, 0)); 348 349 bcm_esw_l2_detach(unit); 350 } 351 /* Proposal: during warm boot, customer wants to freeze l2x. 352 * After warm boot, customer will restore l2x. 353 */ 354 #ifdef BCM_TRIDENT2_SUPPORT 355 if (SOC_IS_TD2_TT2(unit) && SOC_WARM_BOOT(unit) && 356 soc_l2x_cml_override_is_enabled(unit)) { 357 /* In this condition, soc_l2x_freeze does not change ING_MISC_CONFIG2r. 358 * It just wants to Increment l2 frozen indicator "f_l2->hw_frozen++". When we call 359 * bcm_esw_l2_age_timer_set, we won't enable SW aging by mistake. 360 */ 361 BCM_IF_ERROR_RETURN(soc_l2x_selective_freeze(unit, SOC_L2X_FROZEN_WITHOUT_LOCK)); 362 } 363 #endif /* BCM_TRIDENT2_SUPPORT */ 364 365 /* 366 * Call chip-dependent initialization 367 */ 368 BCM_IF_ERROR_RETURN 369 (mbcm_driver[unit]->mbcm_l2_init(unit)); 370 371 if (!SOC_WARM_BOOT(unit) && !SOC_IS_RCPU_ONLY(unit)) { 372 if (!soc_feature(unit, soc_feature_l2_user_table)) { 373 /* 374 * Init BPDU station address registers. 375 */ 376 rv = _bcm_l2_bpdu_init(unit); 377 if (BCM_FAILURE(rv) && (rv != BCM_E_UNAVAIL)) { 378 return rv; 379 } 380 } 381 382 /* 383 * Init L2 cache 384 */ 385 rv = bcm_esw_l2_cache_init(unit); 386 if (BCM_FAILURE(rv) && (rv != BCM_E_UNAVAIL)) { 387 return rv; 388 } 389 } 390 391 /* 392 * Init L2 learn limit 393 */ 394 #if defined(BCM_TRIUMPH_SUPPORT) || defined(BCM_RAPTOR_SUPPORT) 395 rv = _bcm_l2_learn_limit_init(unit); 396 if (BCM_FAILURE(rv) && (rv != BCM_E_UNAVAIL)) { 397 return rv; 398 } 399 #endif /* BCM_TRIUMPH_SUPPORT || BCM_RAPTOR_SUPPORT */ 400 #if defined(BCM_TRX_SUPPORT) 401 /* 402 * Init class based learning 403 */ 404 if (soc_feature(unit, soc_feature_class_based_learning)) { 405 soc_mem_t mem; 406 int entry_words; 407 int index_max; 408 int lclass; 409 union { 410 port_cbl_table_entry_t port_cbl[256]; 411 uint32 w[1]; 412 } entry; 413 void *entries[1]; 414 soc_profile_mem_t *profile; 415 int module; 416 uint32 profile_index; 417 int field_len; 418 419 /* Clear CBL attribute register and CBL table */ 420 if (SOC_REG_IS_VALID(unit, CBL_ATTRIBUTEr) && (!SOC_WARM_BOOT(unit))) { 421 for (lclass = 0; lclass < SOC_REG_NUMELS(unit, CBL_ATTRIBUTEr); 422 lclass++) { 423 BCM_IF_ERROR_RETURN(WRITE_CBL_ATTRIBUTEr(unit, lclass, 0)); 424 } 425 } 426 427 if (!SOC_WARM_BOOT(unit)) { 428 BCM_IF_ERROR_RETURN(soc_mem_clear(unit, PORT_CBL_TABLEm, 429 COPYNO_ALL, FALSE)); 430 } 431 if (soc_mem_is_valid(unit, PORT_CBL_TABLE_MODBASEm)) { 432 /* Create profile for PORT_CBL_TABLE table */ 433 if (_bcm_l2_port_cbl_profile[unit] == NULL) { 434 _bcm_l2_port_cbl_profile[unit] = 435 sal_alloc(sizeof(soc_profile_mem_t), 436 "PORT_CBL_TABLE profile"); 437 if (_bcm_l2_port_cbl_profile[unit] == NULL) { 438 return BCM_E_MEMORY; 439 } 440 soc_profile_mem_t_init(_bcm_l2_port_cbl_profile[unit]); 441 } 442 profile = _bcm_l2_port_cbl_profile[unit]; 443 mem = PORT_CBL_TABLEm; 444 entry_words = sizeof(port_cbl_table_entry_t) / sizeof(uint32); 445 field_len = soc_mem_field_length(unit, PORT_CBL_TABLE_MODBASEm, 446 BASEf); 447 index_max = (1 << field_len) - 1; 448 entries[0] = &entry; 449 sal_memset(&entry.port_cbl[0], 0, sizeof(entry.port_cbl[0])); 450 field_len = soc_mem_field_length(unit, PORT_CBL_TABLEm, 451 PORT_LEARNING_CLASSf); 452 soc_mem_field32_set(unit, PORT_CBL_TABLEm, &entry.port_cbl[0], 453 PORT_LEARNING_CLASSf, (1 << field_len) - 1); 454 455 BCM_IF_ERROR_RETURN 456 (soc_profile_mem_index_create(unit, &mem, &entry_words, NULL, 457 &index_max, entries, 1, 458 profile)); 459 460 if (!SOC_WARM_BOOT(unit)) { 461 BCM_IF_ERROR_RETURN(soc_mem_clear(unit, PORT_CBL_TABLE_MODBASEm, 462 COPYNO_ALL, FALSE)); 463 sal_memset(entry.port_cbl, 0, sizeof(entry.port_cbl)); 464 BCM_IF_ERROR_RETURN 465 (soc_profile_mem_add(unit, profile, entries, 466 SOC_PORT_ADDR_MAX(unit) + 1, 467 &profile_index)); 468 for (module = 1; module <= SOC_MODID_MAX(unit); module++) { 469 SOC_IF_ERROR_RETURN 470 (soc_profile_mem_reference 471 (unit, profile, profile_index, 472 SOC_PORT_ADDR_MAX(unit) + 1)); 473 } 474 } 475 #ifdef BCM_WARM_BOOT_SUPPORT 476 else { 477 port_cbl_table_modbase_entry_t base_entry; 478 479 for (module = 0; module <= SOC_MODID_MAX(unit); module++) { 480 SOC_IF_ERROR_RETURN 481 (soc_mem_read(unit, PORT_CBL_TABLE_MODBASEm, 482 MEM_BLOCK_ANY, module, &base_entry)); 483 profile_index = 484 soc_mem_field32_get(unit, PORT_CBL_TABLE_MODBASEm, 485 &base_entry, BASEf); 486 SOC_IF_ERROR_RETURN 487 (soc_profile_mem_reference 488 (unit, profile, profile_index, 489 SOC_PORT_ADDR_MAX(unit) + 1)); 490 } 491 } 492 #endif /* BCM_WARM_BOOT_SUPPORT */ 493 } 494 } 495 496 #endif /* BCM_TRX_SUPPORT */ 497 #ifdef BCM_WARM_BOOT_SUPPORT 498 if (SOC_WARM_BOOT(unit)) { 499 BCM_IF_ERROR_RETURN(_bcm_esw_l2_wb_recover(unit)); 500 } else { 501 BCM_IF_ERROR_RETURN(_bcm_esw_l2_wb_alloc(unit)); 502 } 503 #endif /* BCM_WARM_BOOT_SUPPORT */ 504 _l2_init[unit] = 1; /* some positive value */ 505 return BCM_E_NONE; 506 } 507 508 /* 509 * Function: 510 * bcm_esw_l2_detach 511 * Purpose: 512 * Clean up l2 bcm layer when unit is detached 513 * Parameters: 514 * unit - unit being detached 515 * Returns: 516 * BCM_E_XXX 517 */ 518 519 int 520 bcm_esw_l2_detach(int unit) 521 { 522 523 #ifdef BCM_XGS_SWITCH_SUPPORT 524 int frozen; 525 526 #if defined(BCM_TOMAHAWK3_SUPPORT) 527 /* Added to handle SDK functions calling esw version, 528 * instead of Tomahawk3's version 529 */ 530 if (SOC_IS_TOMAHAWK3(unit)) { 531 return bcm_tomahawk3_l2_detach(unit); 532 } 533 #endif /* BCM_TOMAHAWK3_SUPPORT */ 534 535 #if defined(BCM_TRIUMPH3_SUPPORT) 536 if (soc_feature(unit, soc_feature_ism_memory)) { 537 BCM_IF_ERROR_RETURN(bcm_tr3_l2_detach(unit)); 538 539 _l2_init[unit] = 0; 540 return BCM_E_NONE; 541 } 542 #endif /* BCM_TRIUMPH3_SUPPORT */ 543 544 /* Verify the table is not frozen */ 545 BCM_IF_ERROR_RETURN( 546 soc_l2x_is_frozen(unit, SOC_L2X_FROZEN_WITH_LOCK, &frozen)); 547 if (TRUE == frozen) { 548 return BCM_E_BUSY; 549 } 550 #endif /* BCM_XGS_SWITCH_SUPPORT */ 551 552 #ifdef BCM_SHADOW_SUPPORT 553 if (soc_feature(unit, soc_feature_no_bridging)) { 554 return BCM_E_NONE; 555 } 556 #endif 557 558 if (_bcm_l2_match_ctrl[unit] && _bcm_l2_match_ctrl[unit]->preserved) { 559 _l2_init[unit] = 0; 560 return BCM_E_NONE; 561 } 562 563 /* 564 * Call chip-dependent finalization. 565 */ 566 SOC_IF_ERROR_RETURN 567 (mbcm_driver[unit]->mbcm_l2_term(unit)); 568 569 _l2_init[unit] = 0; 570 return BCM_E_NONE; 571 } 572 573 574 /* 575 * Function: 576 * _bcm_esw_delete_replace_flags_convert 577 * Description: 578 * A helper function to all delete_by APIs to use bcm_l2_replace. 579 * Converts L2 flags to L2 replace flags compatable to use with bcm_l2_replace 580 * Parameters: 581 * unit [IN]- device unit 582 * flags [IN] - BCM_L2_DELETE_XXX 583 * repl_flags [OUT]- Vflags BCM_L2_REPLACE_XXX 584 * Returns: 585 * BCM_E_XXX 586 */ 587 588 int 589 _bcm_esw_delete_replace_flags_convert(int unit, uint32 flags, uint32 *repl_flags) 590 { 591 uint32 tmp_flags = BCM_L2_REPLACE_DELETE; 592 593 /* Age feature only supported by Bulk Control */ 594 if (soc_feature(unit, soc_feature_l2_bulk_control)) { 595 596 /* Both Age and Delete flags cannot be specified */ 597 if ( (flags & BCM_L2_REPLACE_AGE) && (flags & BCM_L2_REPLACE_DELETE) ){ 598 return BCM_E_PARAM; 599 } 600 601 if (flags & BCM_L2_REPLACE_AGE){ 602 tmp_flags = BCM_L2_REPLACE_AGE; 603 } 604 } else { 605 if (flags & BCM_L2_REPLACE_AGE){ 606 return BCM_E_UNAVAIL; 607 } 608 } 609 610 if (flags & BCM_L2_DELETE_PENDING) { 611 tmp_flags |= BCM_L2_REPLACE_PENDING; 612 } 613 if (flags & BCM_L2_DELETE_STATIC) { 614 tmp_flags |= BCM_L2_REPLACE_MATCH_STATIC; 615 } 616 if (flags & BCM_L2_DELETE_NO_CALLBACKS) { 617 tmp_flags |= BCM_L2_REPLACE_NO_CALLBACKS; 618 } 619 if (flags & BCM_L2_REPLACE_VPN_TYPE) { 620 tmp_flags |= BCM_L2_REPLACE_VPN_TYPE; 621 } 622 *repl_flags = tmp_flags; 623 return BCM_E_NONE; 624 } 625 626 /* 627 * Function: 628 * bcm_esw_l2_addr_add 629 * Description: 630 * Add a MAC address to the Switch Address Resolution Logic (ARL) 631 * port with the given VLAN ID and parameters. 632 * Parameters: 633 * unit - StrataSwitch PCI device unit number (driver internal). 634 * l2addr - Pointer to bcm_l2_addr_t containing all valid fields 635 * Returns: 636 * BCM_E_NONE Success 637 * BCM_E_INTERNAL Chip access failure 638 * Notes: 639 * Use CMIC_PORT(unit) to associate the entry with the CPU. 640 * Use flag of BCM_L2_COPY_TO_CPU to send a copy to the CPU. 641 * Use flag of BCM_L2_TRUNK_MEMBER to set trunking (TGID must be 642 * passed as well with non-zero trunk group ID) 643 */ 644 645 int 646 bcm_esw_l2_addr_add(int unit, bcm_l2_addr_t *l2addr) 647 { 648 #if defined(BCM_TOMAHAWK3_SUPPORT) 649 /* Added to handle SDK functions calling esw version, 650 * instead of Tomahawk3's version 651 */ 652 if (SOC_IS_TOMAHAWK3(unit)) { 653 return bcm_tomahawk3_l2_addr_add(unit, l2addr); 654 } 655 #endif /* BCM_TOMAHAWK3_SUPPORT */ 656 657 L2_INIT(unit); 658 659 #if defined(BCM_TRIUMPH3_SUPPORT) 660 if (soc_feature(unit, soc_feature_ism_memory)) { 661 return bcm_tr3_l2_addr_add(unit, l2addr); 662 } 663 #endif /* BCM_TRIUMPH3_SUPPORT */ 664 665 /* Input parameters check. */ 666 if (NULL == l2addr) { 667 return (BCM_E_PARAM); 668 } 669 670 if (!soc_feature(unit, soc_feature_l2_drop_mc_mac)) { 671 if (l2addr->flags & BCM_L2_DISCARD_DST) { 672 if (MAC_IS_MCAST(l2addr->mac)) { 673 return (BCM_E_UNAVAIL); 674 } 675 } 676 } 677 678 if (l2addr->flags & BCM_L2_LOCAL_CPU) { 679 l2addr->port = CMIC_PORT(unit); 680 BCM_IF_ERROR_RETURN(bcm_esw_stk_modid_get(unit, &l2addr->modid)); 681 } 682 683 if (l2addr->flags & BCM_L2_TRUNK_MEMBER) { 684 BCM_IF_ERROR_RETURN( 685 _bcm_trunk_id_validate(unit, l2addr->tgid)); 686 } 687 688 if (SOC_L2X_GROUP_ENABLE_GET(unit)) { 689 if (soc_feature(unit, soc_feature_overlaid_address_class) && 690 !BCM_L2_PRE_SET(l2addr->flags)) { 691 if ((l2addr->group > SOC_OVERLAID_ADDR_CLASS_MAX(unit)) || 692 (l2addr->group < 0)) { 693 return (BCM_E_PARAM); 694 } 695 } else if ((l2addr->group > SOC_ADDR_CLASS_MAX(unit)) || 696 (l2addr->group < 0)) { 697 return (BCM_E_PARAM); 698 } 699 if (!BCM_PBMP_IS_NULL(l2addr->block_bitmap)) { 700 return (BCM_E_PARAM); 701 } 702 } else { 703 if (l2addr->group) { 704 return (BCM_E_PARAM); 705 } 706 } 707 708 /* Input parameters check for TSN related parameters */ 709 if (!soc_feature(unit, soc_feature_tsn)) { 710 if (l2addr->tsn_flowset) { 711 return BCM_E_UNAVAIL; 712 } 713 } 714 715 /* Input parameters check for SR related parameters */ 716 if (!soc_feature(unit, soc_feature_tsn_sr)) { 717 if (l2addr->flags & BCM_L2_SR_SAN_DEST) { 718 return BCM_E_UNAVAIL; 719 } 720 if (!BCM_PBMP_IS_NULL(l2addr->sa_source_filter_pbmp)) { 721 return BCM_E_UNAVAIL; 722 } 723 if (l2addr->sr_flowset) { 724 return BCM_E_UNAVAIL; 725 } 726 } 727 728 SOC_IF_ERROR_RETURN 729 (mbcm_driver[unit]->mbcm_l2_addr_add(unit, l2addr)); 730 731 return BCM_E_NONE; 732 } 733 734 /* 735 * Function: 736 * bcm_esw_l2_addr_delete 737 * Description: 738 * Delete an L2 address (MAC+VLAN) from the device 739 * Parameters: 740 * unit - device unit 741 * mac - MAC address to delete 742 * vid - VLAN id 743 * Returns: 744 * BCM_E_XXX 745 */ 746 747 int 748 bcm_esw_l2_addr_delete(int unit, bcm_mac_t mac, bcm_vlan_t vid) 749 { 750 #if defined(BCM_TOMAHAWK3_SUPPORT) 751 /* Added to handle SDK functions calling esw version, 752 * instead of Tomahawk3's version 753 */ 754 if (SOC_IS_TOMAHAWK3(unit)) { 755 return bcm_tomahawk3_l2_addr_delete(unit, mac, vid); 756 } 757 #endif /* BCM_TOMAHAWK3_SUPPORT */ 758 759 L2_INIT(unit); 760 761 #if defined(BCM_TRIUMPH3_SUPPORT) 762 if (soc_feature(unit, soc_feature_ism_memory)) { 763 return bcm_tr3_l2_addr_delete(unit, mac, vid); 764 } 765 #endif /* BCM_TRIUMPH3_SUPPORT */ 766 767 return mbcm_driver[unit]->mbcm_l2_addr_delete(unit, mac, vid); 768 } 769 770 /* 771 * Function: 772 * bcm_esw_l2_addr_delete_by_port 773 * Description: 774 * Delete L2 addresses associated with a destination module/port. 775 * Parameters: 776 * unit - device unit 777 * mod - module id (or -1 for local unit) 778 * port - port 779 * flags - BCM_L2_DELETE_XXX 780 * Returns: 781 * BCM_E_XXX 782 * Notes: 783 * Static entries are removed only if BCM_L2_DELETE_STATIC flag is used. 784 * L2 aging and learning are disabled during this operation. 785 */ 786 787 int 788 bcm_esw_l2_addr_delete_by_port(int unit, 789 bcm_module_t mod, bcm_port_t port, 790 uint32 flags) 791 { 792 bcm_l2_addr_t match_addr; 793 uint32 repl_flags; 794 uint32 int_flags = 0; 795 #if defined(BCM_KATANA2_SUPPORT) || defined(BCM_HGPROXY_COE_SUPPORT) 796 int id = -1; 797 bcm_port_t _port = -1; 798 bcm_trunk_t _trunk = -1; 799 bcm_module_t _modid = -1; 800 #endif 801 802 #if defined(BCM_TOMAHAWK3_SUPPORT) 803 /* Added to handle SDK functions calling esw version, 804 * instead of Tomahawk3's version 805 */ 806 if (SOC_IS_TOMAHAWK3(unit)) { 807 return bcm_tomahawk3_l2_addr_delete_by_port(unit, mod, port, flags); 808 } 809 #endif /* BCM_TOMAHAWK3_SUPPORT */ 810 811 L2_INIT(unit); 812 813 #if defined(BCM_TRIUMPH3_SUPPORT) 814 if (soc_feature(unit, soc_feature_ism_memory)) { 815 return bcm_tr3_l2_addr_delete_by_port(unit, mod, port, flags); 816 } 817 #endif /* BCM_TRIUMPH3_SUPPORT */ 818 819 sal_memset(&match_addr, 0, sizeof(bcm_l2_addr_t)); 820 if (port == -1) { 821 match_addr.modid = mod; 822 match_addr.port = -1; 823 int_flags = _BCM_L2_REPLACE_IGNORE_PORTID; 824 } else if (!BCM_GPORT_IS_SET(port) && mod == -1) { 825 #ifdef BCM_KATANA2_SUPPORT 826 if ((soc_feature(unit, soc_feature_linkphy_coe) && 827 BCM_PBMP_MEMBER (SOC_INFO(unit).linkphy_pp_port_pbm, port)) || 828 (soc_feature(unit, soc_feature_subtag_coe) && 829 BCM_PBMP_MEMBER (SOC_INFO(unit).subtag_pp_port_pbm, port))) { 830 return BCM_E_PORT; 831 } else 832 #endif 833 if (!SOC_PORT_VALID(unit, port)) { 834 return BCM_E_PORT; 835 } 836 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &match_addr.modid)); 837 } else { 838 839 #if defined(BCM_HGPROXY_COE_SUPPORT) 840 if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) && 841 BCM_GPORT_IS_SET(port) && 842 _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port)) { 843 BCM_IF_ERROR_RETURN( 844 _bcm_esw_gport_resolve(unit, port, &_modid, &_port, 845 &_trunk, &id)); 846 match_addr.modid = _modid; 847 port = _port; 848 } else 849 #endif 850 #if defined(BCM_KATANA2_SUPPORT) 851 if (_BCM_KT2_GPORT_IS_LINKPHY_OR_SUBTAG_SUBPORT_GPORT(unit, port)) { 852 BCM_IF_ERROR_RETURN( 853 _bcm_esw_gport_resolve(unit, port, &_modid, &_port, 854 &_trunk, &id)); 855 match_addr.modid = _modid; 856 port = _port; 857 } else 858 #endif 859 { 860 match_addr.modid = mod; 861 } 862 } 863 match_addr.port = port; 864 865 BCM_IF_ERROR_RETURN 866 (_bcm_esw_delete_replace_flags_convert(unit, flags, &repl_flags)); 867 repl_flags |= BCM_L2_REPLACE_MATCH_DEST; 868 return _bcm_esw_l2_replace(unit, repl_flags, int_flags, &match_addr, 0, 0, 0, 869 NULL, NULL); 870 } 871 872 /* 873 * Function: 874 * bcm_esw_l2_addr_delete_by_mac 875 * Description: 876 * Delete L2 entries associated with a MAC address. 877 * Parameters: 878 * unit - device unit 879 * mac - MAC address 880 * flags - BCM_L2_DELETE_XXX 881 * Returns: 882 * BCM_E_XXX 883 * Notes: 884 * Static entries are removed only if BCM_L2_DELETE_STATIC flag is used. 885 * L2 aging and learning are disabled during this operation. 886 */ 887 int 888 bcm_esw_l2_addr_delete_by_mac(int unit, bcm_mac_t mac, uint32 flags) 889 { 890 bcm_l2_addr_t match_addr; 891 uint32 repl_flags; 892 893 #if defined(BCM_TOMAHAWK3_SUPPORT) 894 /* Added to handle SDK functions calling esw version, 895 * instead of Tomahawk3's version 896 */ 897 if (SOC_IS_TOMAHAWK3(unit)) { 898 return bcm_tomahawk3_l2_addr_delete_by_mac(unit, mac, flags); 899 } 900 #endif /* BCM_TOMAHAWK3_SUPPORT */ 901 902 L2_INIT(unit); 903 904 #if defined(BCM_TRIUMPH3_SUPPORT) 905 if (soc_feature(unit, soc_feature_ism_memory)) { 906 return bcm_tr3_l2_addr_delete_by_mac(unit, mac, flags); 907 } 908 #endif /* BCM_TRIUMPH3_SUPPORT */ 909 910 sal_memset(&match_addr, 0, sizeof(bcm_l2_addr_t)); 911 sal_memcpy(match_addr.mac, mac, sizeof(bcm_mac_t)); 912 BCM_IF_ERROR_RETURN 913 (_bcm_esw_delete_replace_flags_convert(unit, flags, &repl_flags)); 914 /* Traverse l2 entry contains MAC address field by key type. */ 915 /* Currently, L2 Bridge and VFI are suported. */ 916 repl_flags |= BCM_L2_REPLACE_MATCH_MAC | BCM_L2_REPLACE_VPN_TYPE; 917 BCM_IF_ERROR_RETURN 918 (_bcm_esw_l2_replace(unit, repl_flags, 0, &match_addr, 0, 0, 0, NULL, NULL)); 919 repl_flags &= ~BCM_L2_REPLACE_VPN_TYPE; 920 return _bcm_esw_l2_replace(unit, repl_flags, 0, &match_addr, 0, 0, 0, 921 NULL, NULL); 922 } 923 924 /* 925 * Function: 926 * bcm_esw_l2_addr_delete_by_vlan 927 * Description: 928 * Delete L2 entries associated with a VLAN. 929 * Parameters: 930 * unit - device unit 931 * vid - VLAN id 932 * flags - BCM_L2_DELETE_XXX 933 * Returns: 934 * BCM_E_XXX 935 * Notes: 936 * Static entries are removed only if BCM_L2_DELETE_STATIC flag is used. 937 * L2 aging and learning are disabled during this operation. 938 */ 939 int 940 bcm_esw_l2_addr_delete_by_vlan(int unit, bcm_vlan_t vid, uint32 flags) 941 { 942 bcm_l2_addr_t match_addr; 943 uint32 repl_flags; 944 945 #if defined(BCM_TOMAHAWK3_SUPPORT) 946 /* Added to handle SDK functions calling esw version, 947 * instead of Tomahawk3's version 948 */ 949 if (SOC_IS_TOMAHAWK3(unit)) { 950 return bcm_tomahawk3_l2_addr_delete_by_vlan(unit, vid, flags); 951 } 952 #endif /* BCM_TOMAHAWK3_SUPPORT */ 953 954 L2_INIT(unit); 955 956 #if defined(BCM_TRIUMPH3_SUPPORT) 957 if (soc_feature(unit, soc_feature_ism_memory)) { 958 return bcm_tr3_l2_addr_delete_by_vlan(unit, vid, flags); 959 } 960 #endif /* BCM_TRIUMPH3_SUPPORT */ 961 962 sal_memset(&match_addr, 0, sizeof(bcm_l2_addr_t)); 963 match_addr.vid = vid; 964 BCM_IF_ERROR_RETURN 965 (_bcm_esw_delete_replace_flags_convert(unit, flags, &repl_flags)); 966 repl_flags |= BCM_L2_REPLACE_MATCH_VLAN; 967 return _bcm_esw_l2_replace(unit, repl_flags, 0, &match_addr, 0, 0, 0, 968 NULL, NULL); 969 } 970 971 /* 972 * Function: 973 * bcm_esw_l2_addr_delete_by_trunk 974 * Description: 975 * Delete L2 entries associated with a trunk. 976 * Parameters: 977 * unit - device unit 978 * tid - trunk id 979 * flags - BCM_L2_DELETE_XXX 980 * Returns: 981 * BCM_E_XXX 982 * Notes: 983 * Static entries are removed only if BCM_L2_DELETE_STATIC flag is used. 984 * L2 aging and learning are disabled during this operation. 985 */ 986 int 987 bcm_esw_l2_addr_delete_by_trunk(int unit, bcm_trunk_t tid, uint32 flags) 988 { 989 bcm_l2_addr_t match_addr; 990 uint32 repl_flags; 991 992 #if defined(BCM_TOMAHAWK3_SUPPORT) 993 /* Added to handle SDK functions calling esw version, 994 * instead of Tomahawk3's version 995 */ 996 if (SOC_IS_TOMAHAWK3(unit)) { 997 return bcm_tomahawk3_l2_addr_delete_by_trunk(unit, tid, flags); 998 } 999 #endif /* BCM_TOMAHAWK3_SUPPORT */ 1000 1001 L2_INIT(unit); 1002 1003 #if defined(BCM_TRIUMPH3_SUPPORT) 1004 if (soc_feature(unit, soc_feature_ism_memory)) { 1005 return bcm_tr3_l2_addr_delete_by_trunk(unit, tid, flags); 1006 } 1007 #endif /* BCM_TRIUMPH3_SUPPORT */ 1008 1009 sal_memset(&match_addr, 0, sizeof(bcm_l2_addr_t)); 1010 match_addr.tgid = tid; 1011 match_addr.flags = BCM_L2_TRUNK_MEMBER; 1012 BCM_IF_ERROR_RETURN 1013 (_bcm_esw_delete_replace_flags_convert(unit, flags, &repl_flags)); 1014 repl_flags |= BCM_L2_REPLACE_MATCH_DEST; 1015 return _bcm_esw_l2_replace(unit, repl_flags, 0, &match_addr, 0, 0, 0, 1016 NULL, NULL); 1017 } 1018 1019 /* 1020 * Function: 1021 * bcm_esw_l2_addr_delete_by_mac_port 1022 * Description: 1023 * Delete L2 entries associated with a MAC address and 1024 * a destination module/port 1025 * Parameters: 1026 * unit - device unit 1027 * mac - MAC address 1028 * mod - module id 1029 * port - port 1030 * flags - BCM_L2_DELETE_XXX 1031 * Returns: 1032 * BCM_E_XXX 1033 * Notes: 1034 * Static entries are removed only if BCM_L2_DELETE_STATIC flag is used. 1035 * L2 aging and learning are disabled during this operation. 1036 */ 1037 int 1038 bcm_esw_l2_addr_delete_by_mac_port(int unit, bcm_mac_t mac, 1039 bcm_module_t mod, bcm_port_t port, uint32 flags) 1040 { 1041 bcm_l2_addr_t match_addr; 1042 uint32 repl_flags; 1043 #if (defined(BCM_KATANA2_SUPPORT) || defined(BCM_HGPROXY_COE_SUPPORT)) 1044 int id = -1; 1045 bcm_port_t _port = -1; 1046 bcm_trunk_t _trunk = -1; 1047 bcm_module_t _modid = -1; 1048 #endif 1049 1050 #if defined(BCM_TOMAHAWK3_SUPPORT) 1051 /* Added to handle SDK functions calling esw version, 1052 * instead of Tomahawk3's version 1053 */ 1054 if (SOC_IS_TOMAHAWK3(unit)) { 1055 return bcm_tomahawk3_l2_addr_delete_by_mac_port(unit, mac, mod, port, 1056 flags); 1057 } 1058 #endif /* BCM_TOMAHAWK3_SUPPORT */ 1059 1060 L2_INIT(unit); 1061 1062 #if defined(BCM_TRIUMPH3_SUPPORT) 1063 if (soc_feature(unit, soc_feature_ism_memory)) { 1064 return bcm_tr3_l2_addr_delete_by_mac_port(unit, mac, 1065 mod, port, flags); 1066 } 1067 #endif /* BCM_TRIUMPH3_SUPPORT */ 1068 1069 sal_memset(&match_addr, 0, sizeof(bcm_l2_addr_t)); 1070 sal_memcpy(match_addr.mac, mac, sizeof(bcm_mac_t)); 1071 if (!BCM_GPORT_IS_SET(port) && mod == -1) { 1072 #ifdef BCM_KATANA2_SUPPORT 1073 if ((soc_feature(unit, soc_feature_linkphy_coe) && 1074 BCM_PBMP_MEMBER (SOC_INFO(unit).linkphy_pp_port_pbm, port)) || 1075 (soc_feature(unit, soc_feature_subtag_coe) && 1076 BCM_PBMP_MEMBER (SOC_INFO(unit).subtag_pp_port_pbm, port))) { 1077 return BCM_E_PORT; 1078 } else 1079 #endif 1080 if (!SOC_PORT_VALID(unit, port)) { 1081 return BCM_E_PORT; 1082 } 1083 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &match_addr.modid)); 1084 } else { 1085 1086 #if defined(BCM_HGPROXY_COE_SUPPORT) 1087 if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) && 1088 _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port)) { 1089 BCM_IF_ERROR_RETURN( 1090 _bcm_esw_gport_resolve(unit, port, &_modid, &_port, 1091 &_trunk, &id)); 1092 match_addr.modid = _modid; 1093 port = _port; 1094 } else 1095 #endif 1096 1097 #if defined(BCM_KATANA2_SUPPORT) 1098 if (_BCM_KT2_GPORT_IS_LINKPHY_OR_SUBTAG_SUBPORT_GPORT(unit, port)) { 1099 BCM_IF_ERROR_RETURN( 1100 _bcm_esw_gport_resolve(unit, port, &_modid, &_port, 1101 &_trunk, &id)); 1102 match_addr.modid = _modid; 1103 port = _port; 1104 } else 1105 #endif 1106 { 1107 match_addr.modid = mod; 1108 } 1109 } 1110 match_addr.port = port; 1111 BCM_IF_ERROR_RETURN 1112 (_bcm_esw_delete_replace_flags_convert(unit, flags, &repl_flags)); 1113 repl_flags |= BCM_L2_REPLACE_MATCH_MAC | BCM_L2_REPLACE_MATCH_DEST; 1114 return _bcm_esw_l2_replace(unit, repl_flags, 0, &match_addr, 0, 0, 0, 1115 NULL, NULL); 1116 } 1117 1118 /* 1119 * Function: 1120 * bcm_esw_l2_addr_delete_by_vlan_port 1121 * Description: 1122 * Delete L2 entries associated with a VLAN and 1123 * a destination module/port 1124 * Parameters: 1125 * unit - device unit 1126 * vid - VLAN id 1127 * mod - module id 1128 * port - port 1129 * flags - BCM_L2_DELETE_XXX 1130 * Returns: 1131 * BCM_E_XXX 1132 * Notes: 1133 * Static entries are removed only if BCM_L2_DELETE_STATIC flag is used. 1134 * L2 aging and learning are disabled during this operation. 1135 */ 1136 int 1137 bcm_esw_l2_addr_delete_by_vlan_port(int unit, bcm_vlan_t vid, 1138 bcm_module_t mod, bcm_port_t port, uint32 flags) 1139 { 1140 bcm_l2_addr_t match_addr; 1141 uint32 repl_flags; 1142 #if defined(BCM_KATANA2_SUPPORT) || defined(BCM_HGPROXY_COE_SUPPORT) 1143 int id = -1; 1144 bcm_port_t _port = -1; 1145 bcm_trunk_t _trunk = -1; 1146 bcm_module_t _modid = -1; 1147 #endif 1148 1149 #if defined(BCM_TOMAHAWK3_SUPPORT) 1150 /* Added to handle SDK functions calling esw version, 1151 * instead of Tomahawk3's version 1152 */ 1153 if (SOC_IS_TOMAHAWK3(unit)) { 1154 return bcm_tomahawk3_l2_addr_delete_by_vlan_port(unit, vid, mod, port, 1155 flags); 1156 } 1157 #endif /* BCM_TOMAHAWK3_SUPPORT */ 1158 1159 L2_INIT(unit); 1160 1161 #if defined(BCM_TRIUMPH3_SUPPORT) 1162 if (soc_feature(unit, soc_feature_ism_memory)) { 1163 return bcm_tr3_l2_addr_delete_by_vlan_port(unit, vid, 1164 mod, port, flags); 1165 } 1166 #endif /* BCM_TRIUMPH3_SUPPORT */ 1167 1168 sal_memset(&match_addr, 0, sizeof(bcm_l2_addr_t)); 1169 match_addr.vid = vid; 1170 if (!BCM_GPORT_IS_SET(port) && mod == -1) { 1171 #ifdef BCM_KATANA2_SUPPORT 1172 if ((soc_feature(unit, soc_feature_linkphy_coe) && 1173 BCM_PBMP_MEMBER (SOC_INFO(unit).linkphy_pp_port_pbm, port)) || 1174 (soc_feature(unit, soc_feature_subtag_coe) && 1175 BCM_PBMP_MEMBER (SOC_INFO(unit).subtag_pp_port_pbm, port))) { 1176 return BCM_E_PORT; 1177 } else 1178 #endif 1179 if (!SOC_PORT_VALID(unit, port)) { 1180 return BCM_E_PORT; 1181 } 1182 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &match_addr.modid)); 1183 } else { 1184 1185 #if defined(BCM_HGPROXY_COE_SUPPORT) 1186 if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) && 1187 _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port)) { 1188 BCM_IF_ERROR_RETURN( 1189 _bcm_esw_gport_resolve(unit, port, &_modid, &_port, 1190 &_trunk, &id)); 1191 match_addr.modid = _modid; 1192 port = _port; 1193 } else 1194 #endif 1195 #if defined(BCM_KATANA2_SUPPORT) 1196 if (_BCM_KT2_GPORT_IS_LINKPHY_OR_SUBTAG_SUBPORT_GPORT(unit, port)) { 1197 BCM_IF_ERROR_RETURN( 1198 _bcm_esw_gport_resolve(unit, port, &_modid, &_port, 1199 &_trunk, &id)); 1200 match_addr.modid = _modid; 1201 port = _port; 1202 } else 1203 #endif 1204 { 1205 match_addr.modid = mod; 1206 } 1207 } 1208 match_addr.port = port; 1209 BCM_IF_ERROR_RETURN 1210 (_bcm_esw_delete_replace_flags_convert(unit, flags, &repl_flags)); 1211 repl_flags |= BCM_L2_REPLACE_MATCH_VLAN | BCM_L2_REPLACE_MATCH_DEST; 1212 return _bcm_esw_l2_replace(unit, repl_flags, 0, &match_addr, 0, 0, 0, 1213 NULL, NULL); 1214 } 1215 1216 /* 1217 * Function: 1218 * bcm_esw_l2_addr_delete_by_vlan_trunk 1219 * Description: 1220 * Delete L2 entries associated with a VLAN and a 1221 * destination trunk. 1222 * Parameters: 1223 * unit - device unit 1224 * vid - VLAN id 1225 * tid - trunk group id 1226 * flags - BCM_L2_DELETE_XXX 1227 * Returns: 1228 * BCM_E_XXX 1229 * Notes: 1230 * Static entries are removed only if BCM_L2_DELETE_STATIC flag is used. 1231 * L2 aging and learning are disabled during this operation. 1232 */ 1233 int 1234 bcm_esw_l2_addr_delete_by_vlan_trunk(int unit, bcm_vlan_t vid, 1235 bcm_trunk_t tid, uint32 flags) 1236 { 1237 bcm_l2_addr_t match_addr; 1238 uint32 repl_flags; 1239 1240 #if defined(BCM_TOMAHAWK3_SUPPORT) 1241 /* Added to handle SDK functions calling esw version, 1242 * instead of Tomahawk3's version 1243 */ 1244 if (SOC_IS_TOMAHAWK3(unit)) { 1245 return bcm_tomahawk3_l2_addr_delete_by_vlan_trunk(unit, vid, tid, 1246 flags); 1247 } 1248 #endif /* BCM_TOMAHAWK3_SUPPORT */ 1249 1250 L2_INIT(unit); 1251 1252 #if defined(BCM_TRIUMPH3_SUPPORT) 1253 if (soc_feature(unit, soc_feature_ism_memory)) { 1254 return bcm_tr3_l2_addr_delete_by_vlan_trunk(unit, vid, tid, flags); 1255 } 1256 #endif /* BCM_TRIUMPH3_SUPPORT */ 1257 1258 sal_memset(&match_addr, 0, sizeof(bcm_l2_addr_t)); 1259 match_addr.vid = vid; 1260 match_addr.tgid = tid; 1261 match_addr.flags = BCM_L2_TRUNK_MEMBER; 1262 BCM_IF_ERROR_RETURN 1263 (_bcm_esw_delete_replace_flags_convert(unit, flags, &repl_flags)); 1264 repl_flags |= BCM_L2_REPLACE_MATCH_VLAN | BCM_L2_REPLACE_MATCH_DEST; 1265 return _bcm_esw_l2_replace(unit, repl_flags, 0, &match_addr, 0, 0, 0, 1266 NULL, NULL); 1267 } 1268 1269 /* 1270 * Function: 1271 * bcm_l2_addr_get 1272 * Description: 1273 * Given a MAC address and VLAN ID, check if the entry is present 1274 * in the L2 table, and if so, return all associated information. 1275 * Parameters: 1276 * unit - StrataSwitch PCI device unit number (driver internal). 1277 * mac - input MAC address to search 1278 * vid - input VLAN ID to search 1279 * l2addr - Pointer to bcm_l2_addr_t structure to receive results 1280 * Returns: 1281 * BCM_E_NONE Success (l2addr filled in) 1282 * BCM_E_PARAM Illegal parameter (NULL pointer) 1283 * BCM_E_INTERNAL Chip access failure 1284 * BCM_E_NOT_FOUND Address not found (l2addr not filled in) 1285 */ 1286 1287 int 1288 bcm_esw_l2_addr_get(int unit, sal_mac_addr_t mac, 1289 bcm_vlan_t vid, bcm_l2_addr_t *l2addr) 1290 { 1291 #if defined(BCM_TOMAHAWK3_SUPPORT) 1292 /* Added to handle SDK functions calling esw version, 1293 * instead of Tomahawk3's version 1294 */ 1295 if (SOC_IS_TOMAHAWK3(unit)) { 1296 return bcm_tomahawk3_l2_addr_get(unit, mac, vid, l2addr); 1297 } 1298 #endif /* BCM_TOMAHAWK3_SUPPORT */ 1299 1300 L2_INIT(unit); 1301 1302 #if defined(BCM_TRIUMPH3_SUPPORT) 1303 if (soc_feature(unit, soc_feature_ism_memory)) { 1304 return bcm_tr3_l2_addr_get(unit, mac, vid, l2addr); 1305 } 1306 #endif /* BCM_TRIUMPH3_SUPPORT */ 1307 1308 SOC_IF_ERROR_RETURN( 1309 mbcm_driver[unit]->mbcm_l2_addr_get(unit, mac, vid, l2addr)); 1310 1311 return BCM_E_NONE; 1312 } 1313 1314 /**************************************************************************** 1315 * 1316 * L2X Message Registration 1317 */ 1318 1319 #define L2_CB_MAX 3 1320 1321 typedef struct l2x_cb_entry_s { 1322 bcm_l2_addr_callback_t fn; 1323 void *fn_data; 1324 } l2_cb_entry_t; 1325 1326 #define _BCM_L2X_THREAD_STOP (1 << 0) 1327 typedef struct l2_data_s { 1328 l2_cb_entry_t cb[L2_CB_MAX]; 1329 int cb_count; 1330 int flags; 1331 sal_mutex_t l2_mutex; 1332 } l2_data_t; 1333 1334 static l2_data_t l2_data[SOC_MAX_NUM_DEVICES]; 1335 1336 1337 #define L2_LOCK(unit) \ 1338 sal_mutex_take(l2_data[unit].l2_mutex, sal_mutex_FOREVER) 1339 1340 #define L2_UNLOCK(unit) sal_mutex_give(l2_data[unit].l2_mutex) 1341 1342 #define L2_MUTEX(unit) if (l2_data[unit].l2_mutex == NULL && \ 1343 (l2_data[unit].l2_mutex = sal_mutex_create("bcm_l2_lock")) == NULL) \ 1344 return BCM_E_MEMORY 1345 1346 /* 1347 * Function: 1348 * bcm_esw_l2_port_native 1349 * Purpose: 1350 * Determine if the given port is "native" from the point 1351 * of view of L2. 1352 * Parameters: 1353 * unit - The unit 1354 * modid - Module ID of L2 entry being queried 1355 * port - Module port of L2 entry being queried 1356 * Returns: 1357 * TRUE (> 0) if (modid, port) is front panel/CPU port for unit. 1358 * FALSE (0) otherwise. 1359 * < 0 on error. 1360 * 1361 * Native means front panel, but also includes the CPU port. 1362 * HG ports are always excluded as are ports marked as internal or 1363 * external stacking 1364 */ 1365 1366 int 1367 bcm_esw_l2_port_native(int unit, int modid, int port) 1368 { 1369 int unit_modid; 1370 int unit_port; /* In case unit supports multiple module IDs */ 1371 bcm_trunk_t tgid; 1372 int id, isLocal; 1373 1374 #if defined(BCM_TOMAHAWK3_SUPPORT) 1375 /* Added to handle SDK functions calling esw version, 1376 * instead of Tomahawk3's version 1377 */ 1378 if (SOC_IS_TOMAHAWK3(unit)) { 1379 return bcm_tomahawk3_l2_port_native(unit, modid, port); 1380 } 1381 #endif /* BCM_TOMAHAWK3_SUPPORT */ 1382 1383 L2_INIT(unit); 1384 1385 #if defined(BCM_TRIUMPH3_SUPPORT) 1386 if (soc_feature(unit, soc_feature_ism_memory)) { 1387 return bcm_tr3_l2_port_native(unit, modid, port); 1388 } 1389 #endif /* BCM_TRIUMPH3_SUPPORT */ 1390 1391 if (BCM_GPORT_IS_SET(port)) { 1392 BCM_IF_ERROR_RETURN(_bcm_esw_gport_resolve(unit, port, &modid, 1393 &port, &tgid, &id)); 1394 1395 if (-1 != id || BCM_TRUNK_INVALID != tgid) { 1396 return FALSE; 1397 } 1398 } 1399 1400 BCM_IF_ERROR_RETURN(_bcm_esw_modid_is_local(unit, modid, &isLocal)); 1401 if (isLocal != TRUE) { 1402 return FALSE; 1403 } 1404 1405 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &unit_modid)); 1406 if (unit_modid != modid) { 1407 unit_port = port + 32; 1408 } else { 1409 unit_port = port; 1410 } 1411 1412 if (IS_ST_PORT(unit, unit_port)) { 1413 return FALSE; 1414 } 1415 1416 return TRUE; 1417 } 1418 1419 1420 /**************************************************************************** 1421 * 1422 * L2 Callbacks Registration 1423 */ 1424 static bcm_l2_addr_callback_t _bcm_l2_cbs[SOC_MAX_NUM_DEVICES]; 1425 static void *_bcm_l2_cb_data[SOC_MAX_NUM_DEVICES]; 1426 1427 #if defined(BCM_TSN_SUPPORT) 1428 /* 1429 * Function: 1430 * bcmi_l2_addr_tsn_sr_flowset_ref_update 1431 * Purpose: 1432 * Update reference count for the specified TSN/SR flowset 1433 * associated it to a L2 addition/deletion 1434 * Parameters: 1435 * unit - unit number. 1436 * entry_del - entry deleted from the HW L2_ENTRY memory 1437 * entry_add - entry added into the HW L2_ENTRY memory 1438 * Returns: 1439 * BCM_E_NONE 1440 */ 1441 STATIC int 1442 bcmi_l2_addr_tsn_sr_flowset_ref_update( 1443 int unit, 1444 uint32 *entry_del, 1445 uint32 *entry_add) 1446 { 1447 int rv = BCM_E_NONE; 1448 bcm_l2_addr_t l2addr_del, l2addr_add; 1449 #if defined(BCM_TSN_SR_SUPPORT) 1450 int mp_index = 0; /* TSN SR MAC Proxy profile index */ 1451 bcm_pbmp_t mp_pbmp; 1452 #endif /* BCM_TSN_SR_SUPPORT */ 1453 1454 L2_INIT(unit); 1455 1456 /* Input parameters check */ 1457 if ((entry_del == NULL) && (entry_add == NULL)) { 1458 return BCM_E_NONE; 1459 } 1460 1461 if (entry_del != NULL) { 1462 /* Parse L2X entry into L2_Addr structure */ 1463 (void)_bcm_esw_l2_from_l2x(unit, 0, &l2addr_del, entry_del); 1464 } 1465 if (entry_add != NULL) { 1466 /* Parse L2X entry into L2_Addr structure */ 1467 (void)_bcm_esw_l2_from_l2x(unit, 0, &l2addr_add, entry_add); 1468 } 1469 1470 if (soc_feature(unit, soc_feature_tsn)) { 1471 if ((entry_del != NULL) && (l2addr_del.tsn_flowset != 0)) { 1472 /* decrease TSN flowset ref_cnt */ 1473 rv = bcmi_esw_tsn_flowset_ref_dec(unit, l2addr_del.tsn_flowset); 1474 if (BCM_FAILURE(rv)) { 1475 LOG_WARN(BSL_LS_BCM_ARL, 1476 (BSL_META_U(unit, 1477 "bcmi_l2_addr_tsn_sr_flowset_ref_update:" 1478 " can't decrease TSN flowset ref_cnt!!!" 1479 "\n"))); 1480 return BCM_E_NONE; 1481 } 1482 } 1483 if ((entry_add != NULL) && (l2addr_add.tsn_flowset != 0)) { 1484 /* increase TSN flowset ref_cnt */ 1485 rv = bcmi_esw_tsn_flowset_ref_inc(unit, l2addr_add.tsn_flowset); 1486 if (BCM_FAILURE(rv)) { 1487 LOG_WARN(BSL_LS_BCM_ARL, 1488 (BSL_META_U(unit, 1489 "bcmi_l2_addr_tsn_sr_flowset_ref_update:" 1490 " can't increase TSN flowset ref_cnt!!!" 1491 "\n"))); 1492 return BCM_E_NONE; 1493 } 1494 } 1495 } 1496 1497 #if defined(BCM_TSN_SR_SUPPORT) 1498 if (soc_feature(unit, soc_feature_tsn_sr)) { 1499 if ((entry_del != NULL) && (l2addr_del.sr_flowset != 0)) { 1500 /* decrease TSN SR flowset ref_cnt */ 1501 rv = bcmi_esw_tsn_sr_flowset_ref_dec(unit, l2addr_del.sr_flowset); 1502 if (BCM_FAILURE(rv)) { 1503 LOG_WARN(BSL_LS_BCM_ARL, 1504 (BSL_META_U(unit, 1505 "bcmi_l2_addr_tsn_sr_flowset_ref_update:" 1506 " can't decrease SR flowset ref_cnt!!!" 1507 "\n"))); 1508 return BCM_E_NONE; 1509 } 1510 /* decrease TSN SR MAC Proxy ref_cnt */ 1511 if (!BCM_PBMP_IS_NULL(l2addr_del.sa_source_filter_pbmp)) { 1512 mp_index = soc_L2Xm_field32_get(unit, entry_del, 1513 SR_MAC_PROXY_PROFILE_PTRf); 1514 if (mp_index != 0) { 1515 rv = bcmi_esw_tsn_sr_mac_proxy_delete(unit, mp_index); 1516 if (BCM_FAILURE(rv)) { 1517 LOG_WARN(BSL_LS_BCM_ARL, 1518 (BSL_META_U(unit, 1519 "bcmi_esw_tsn_sr_mac_proxy_delete" 1520 ": can't delete SR MAC Proxy!!!" 1521 "\n"))); 1522 return BCM_E_NONE; 1523 } 1524 } 1525 } 1526 } 1527 if ((entry_add != NULL) && (l2addr_add.sr_flowset != 0)) { 1528 /* increase TSN SR flowset ref_cnt */ 1529 rv = bcmi_esw_tsn_sr_flowset_ref_inc(unit, l2addr_add.sr_flowset); 1530 if (BCM_FAILURE(rv)) { 1531 LOG_WARN(BSL_LS_BCM_ARL, 1532 (BSL_META_U(unit, 1533 "bcmi_l2_addr_tsn_sr_flowset_ref_update:" 1534 " can't increase SR flowset ref_cnt!!!" 1535 "\n"))); 1536 return BCM_E_NONE; 1537 } 1538 /* increase TSN SR MAC Proxy ref_cnt */ 1539 if (!BCM_PBMP_IS_NULL(l2addr_add.sa_source_filter_pbmp)) { 1540 /* The value should be inverted between SW and HW view */ 1541 BCM_PBMP_NEGATE(mp_pbmp, l2addr_add.sa_source_filter_pbmp); 1542 BCM_PBMP_AND(mp_pbmp, PBMP_ALL(unit)); 1543 rv = bcmi_esw_tsn_sr_mac_proxy_insert(unit, mp_pbmp, 1544 &mp_index); 1545 if (BCM_FAILURE(rv)) { 1546 LOG_WARN(BSL_LS_BCM_ARL, 1547 (BSL_META_U(unit, 1548 "bcmi_esw_tsn_sr_mac_proxy_insert" 1549 ": can't insert SR MAC Proxy!!!" 1550 "\n"))); 1551 return BCM_E_NONE; 1552 } 1553 } 1554 } 1555 } 1556 #endif /* BCM_TSN_SR_SUPPORT */ 1557 1558 return rv; 1559 } 1560 #endif /* BCM_TSN_SUPPORT */ 1561 1562 /* 1563 * Function: 1564 * _bcm_l2_register_callback 1565 * Description: 1566 * Call back to handle bcm_l2_addr_register clients. 1567 * Parameters: 1568 * unit - StrataSwitch unit number. 1569 * entry_del - Entry to be deleted or updated, NULL if none. 1570 * entry_add - Entry to be inserted or updated, NULL if none. 1571 * fn_data - unused 1572 * Notes: 1573 * Only one callback per unit to the bcm layer is supported here. 1574 * Multiple bcm client callbacks per unit are supported in the bcm layer. 1575 */ 1576 void 1577 _bcm_l2_register_callback(int unit, 1578 int pflags, 1579 l2x_entry_t *entry_del, 1580 l2x_entry_t *entry_add, 1581 void *fn_data) 1582 { 1583 bcm_l2_addr_t l2addr_del, l2addr_add; 1584 _bcm_l2_match_ctrl_t *match_ctrl; 1585 l2x_entry_t *l2x_entry_buf; 1586 uint32 flags = 0; 1587 int buf_index, entry_index; 1588 int l2_callback_event; 1589 1590 if (_l2_init[unit] == 0) { 1591 return; 1592 } 1593 1594 #if defined(BCM_TSN_SUPPORT) 1595 if (pflags & SOC_L2X_ENTRY_TSN_SR_FLOWSET_REF_CNT) { 1596 if (soc_feature(unit, soc_feature_tsn)) { 1597 (void)bcmi_l2_addr_tsn_sr_flowset_ref_update 1598 (unit, (uint32 *)entry_del, (uint32 *)entry_add); 1599 } 1600 } else 1601 #endif /* BCM_TSN_SUPPORT */ 1602 if (pflags & (SOC_L2X_ENTRY_DUMMY | SOC_L2X_ENTRY_NO_ACTION)) { 1603 /* pass l2addr_add info match */ 1604 match_ctrl = _bcm_l2_match_ctrl[unit]; 1605 buf_index = match_ctrl->entry_wr_idx / _BCM_L2_MATCH_ENTRY_BUF_SIZE; 1606 entry_index = match_ctrl->entry_wr_idx % _BCM_L2_MATCH_ENTRY_BUF_SIZE; 1607 if (entry_index == 0) { 1608 if (buf_index >= _BCM_L2_MATCH_ENTRY_BUF_COUNT) { 1609 return; 1610 } 1611 match_ctrl->l2x_entry_buf[buf_index] = 1612 sal_alloc(sizeof(l2x_entry_t) * _BCM_L2_MATCH_ENTRY_BUF_SIZE, 1613 "l2_matched_traverse"); 1614 if (match_ctrl->l2x_entry_buf[buf_index] == NULL) { 1615 return; 1616 } 1617 } 1618 l2x_entry_buf = match_ctrl->l2x_entry_buf[buf_index]; 1619 1620 if (pflags & SOC_L2X_ENTRY_NO_ACTION) { 1621 l2x_entry_buf[entry_index] = *entry_add; 1622 } else { 1623 sal_memcpy(&l2x_entry_buf[entry_index], 1624 soc_mem_entry_null(unit, L2Xm), sizeof(l2x_entry_t)); 1625 } 1626 match_ctrl->entry_wr_idx++; 1627 sal_sem_give(match_ctrl->sem); 1628 sal_thread_yield(); 1629 } else if (_bcm_l2_cbs[unit] != NULL) { 1630 flags = 0; /* Common flags: Move, From/to native */ 1631 1632 sal_memset(&l2addr_del, 0, sizeof(bcm_l2_addr_t)); 1633 sal_memset(&l2addr_add, 0, sizeof(bcm_l2_addr_t)); 1634 1635 /* First, set up the entries: decode HW entries and set flags */ 1636 if (entry_del != NULL) { 1637 (void)_bcm_esw_l2_from_l2x(unit, 0, &l2addr_del, (uint32 *)entry_del); 1638 } 1639 if (entry_add != NULL) { 1640 (void)_bcm_esw_l2_from_l2x(unit, 0, &l2addr_add, (uint32 *)entry_add); 1641 } 1642 1643 if ((entry_del != NULL) && (entry_add != NULL)) { /* It's a move */ 1644 flags |= BCM_L2_MOVE; 1645 if (SOC_USE_GPORT(unit)) { 1646 if (l2addr_del.port != l2addr_add.port) { 1647 flags |= BCM_L2_MOVE_PORT; 1648 } 1649 } else { 1650 if (l2addr_del.modid != l2addr_add.modid || 1651 l2addr_del.tgid != l2addr_add.tgid || 1652 l2addr_del.port != l2addr_add.port) { 1653 flags |= BCM_L2_MOVE_PORT; 1654 } 1655 } 1656 if (!(l2addr_del.flags & BCM_L2_TRUNK_MEMBER)) { 1657 if (bcm_esw_l2_port_native(unit, l2addr_del.modid, 1658 l2addr_del.port) > 0) { 1659 flags |= BCM_L2_FROM_NATIVE; 1660 l2addr_del.flags |= BCM_L2_NATIVE; 1661 } 1662 } 1663 if (!(l2addr_add.flags & BCM_L2_TRUNK_MEMBER)) { 1664 if (bcm_esw_l2_port_native(unit, l2addr_add.modid, 1665 l2addr_add.port) > 0) { 1666 flags |= BCM_L2_TO_NATIVE; 1667 l2addr_add.flags |= BCM_L2_NATIVE; 1668 } 1669 } 1670 l2addr_del.flags |= flags; 1671 l2addr_add.flags |= flags; 1672 } else if (entry_del != NULL) { /* Age out or simple delete */ 1673 if (!(l2addr_del.flags & BCM_L2_TRUNK_MEMBER)) { 1674 if (bcm_esw_l2_port_native(unit, l2addr_del.modid, 1675 l2addr_del.port) > 0) { 1676 l2addr_del.flags |= BCM_L2_NATIVE; 1677 } 1678 } 1679 } else if (entry_add != NULL) { /* Insert or learn */ 1680 if (!(l2addr_add.flags & BCM_L2_TRUNK_MEMBER)) { 1681 if (bcm_esw_l2_port_native(unit, l2addr_add.modid, 1682 l2addr_add.port) > 0) { 1683 l2addr_add.flags |= BCM_L2_NATIVE; 1684 } 1685 } 1686 } 1687 1688 #ifdef BCM_TRIDENT_SUPPORT 1689 /* Filter out the erroneous station moves. */ 1690 if (SOC_IS_TRIDENT(unit) && 1691 !(sal_memcmp(&l2addr_del, &l2addr_add, sizeof(bcm_l2_addr_t)))) { 1692 return; 1693 } 1694 #endif /* BCM_TRIDENT_SUPPORT */ 1695 1696 1697 /* The entries are now set up. Make the callbacks */ 1698 if (entry_del != NULL) { 1699 if (pflags & SOC_L2X_ENTRY_DELETE) { 1700 l2_callback_event = BCM_L2_CALLBACK_DELETE; 1701 } else if (pflags & SOC_L2X_ENTRY_AGE) { 1702 l2_callback_event = BCM_L2_CALLBACK_AGE_EVENT; 1703 } else { 1704 l2_callback_event = BCM_L2_CALLBACK_DELETE; 1705 } 1706 _bcm_l2_cbs[unit](unit, &l2addr_del, 1707 l2_callback_event, 1708 _bcm_l2_cb_data[unit]); 1709 } 1710 1711 if (pflags & SOC_L2X_ENTRY_OVERFLOW) { 1712 l2addr_add.flags |= BCM_L2_ENTRY_OVERFLOW; 1713 } 1714 1715 if (entry_add != NULL) { 1716 if ((flags & BCM_L2_MOVE) && 1717 ((pflags & (SOC_L2X_ENTRY_INSERT | SOC_L2X_ENTRY_LEARN)))) { 1718 l2_callback_event = BCM_L2_CALLBACK_MOVE_EVENT; 1719 } else if (pflags & SOC_L2X_ENTRY_INSERT) { 1720 l2_callback_event = BCM_L2_CALLBACK_ADD; 1721 } else if (pflags & SOC_L2X_ENTRY_LEARN) { 1722 l2_callback_event = BCM_L2_CALLBACK_LEARN_EVENT; 1723 } else { 1724 l2_callback_event = BCM_L2_CALLBACK_ADD; 1725 } 1726 _bcm_l2_cbs[unit](unit, &l2addr_add, 1727 l2_callback_event, 1728 _bcm_l2_cb_data[unit]); 1729 } 1730 } 1731 } 1732 1733 1734 1735 /* 1736 * Function: 1737 * _bcm_l2_addr_callback 1738 * Description: 1739 * Callback used with chip addr registration functions. 1740 * This callback calls all the top level client callbacks. 1741 * Parameters: 1742 * unit - StrataSwitch PCI device unit number (driver internal). 1743 * l2addr 1744 * insert 1745 * userdata 1746 * Returns: 1747 */ 1748 static void 1749 _bcm_l2_addr_callback(int unit, 1750 bcm_l2_addr_t *l2addr, 1751 int insert, 1752 void *userdata) 1753 { 1754 l2_data_t *ad = &l2_data[unit]; 1755 int i; 1756 1757 if (ad->l2_mutex == NULL) { 1758 return; 1759 } 1760 1761 L2_LOCK(unit); 1762 for(i = 0; i < L2_CB_MAX; i++) { 1763 if(ad->cb[i].fn) { 1764 ad->cb[i].fn(unit, l2addr, insert, ad->cb[i].fn_data); 1765 } 1766 } 1767 L2_UNLOCK(unit); 1768 } 1769 1770 1771 /* 1772 * Function: 1773 * bcm_esw_l2_addr_register 1774 * Description: 1775 * Register a callback routine that will be called whenever 1776 * an entry is inserted into or deleted from the L2 address table. 1777 * Parameters: 1778 * unit - StrataSwitch PCI device unit number (driver internal). 1779 * fn - Callback function of type bcm_l2_addr_callback_t. 1780 * fn_data - Arbitrary value passed to callback along with messages 1781 * Returns: 1782 * BCM_E_NONE Success, handle valid 1783 * BCM_E_MEMORY Out of memory 1784 * BCM_E_INTERNAL Chip access failure 1785 */ 1786 1787 int 1788 bcm_esw_l2_addr_register(int unit, 1789 bcm_l2_addr_callback_t fn, 1790 void *fn_data) 1791 { 1792 l2_data_t *ad = &l2_data[unit]; 1793 int i; 1794 #if defined(BCM_XGS_SWITCH_SUPPORT) 1795 int rv = BCM_E_NONE; 1796 int usec; 1797 #endif /* BCM_XGS_SWITCH_SUPPORT */ 1798 1799 if (!SOC_IS_XGS_SWITCH(unit)) { 1800 return BCM_E_UNAVAIL; 1801 } 1802 1803 #if defined(BCM_TOMAHAWK3_SUPPORT) 1804 /* Added to handle SDK functions calling esw version, 1805 * instead of Tomahawk3's version 1806 */ 1807 if (SOC_IS_TOMAHAWK3(unit)) { 1808 return bcm_tomahawk3_l2_addr_register(unit, fn, fn_data); 1809 } 1810 #endif /* BCM_TOMAHAWK3_SUPPORT */ 1811 1812 L2_INIT(unit); 1813 1814 #if defined(BCM_TRIUMPH3_SUPPORT) 1815 if (soc_feature(unit, soc_feature_ism_memory)) { 1816 return bcm_tr3_l2_addr_register(unit, fn, fn_data); 1817 } 1818 #endif /* BCM_TRIUMPH3_SUPPORT */ 1819 1820 _bcm_l2_cbs[unit] = _bcm_l2_addr_callback; 1821 _bcm_l2_cb_data[unit] = NULL; 1822 1823 L2_MUTEX(unit); 1824 L2_LOCK(unit); 1825 #if defined(BCM_XGS_SWITCH_SUPPORT) 1826 /* Start L2x thread if it isn't running already. */ 1827 if (!soc_l2x_running(unit, NULL, NULL)) { 1828 usec = (SAL_BOOT_BCMSIM && !SOC_IS_TRIDENT3X(unit)) ? \ 1829 BCMSIM_L2XMSG_INTERVAL : 3000000; 1830 usec = soc_property_get(unit, spn_L2XMSG_THREAD_USEC, usec); 1831 rv = soc_l2x_start(unit, 0, usec); 1832 if ((BCM_FAILURE(rv)) && (rv != BCM_E_UNAVAIL)) { 1833 _bcm_l2_cbs[unit] = NULL; 1834 _bcm_l2_cb_data[unit] = NULL; 1835 L2_UNLOCK(unit); 1836 return(rv); 1837 } 1838 ad->flags |= _BCM_L2X_THREAD_STOP; 1839 } 1840 #endif /* BCM_XGS_SWITCH_SUPPORT */ 1841 1842 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_HURRICANE3_SUPPORT) 1843 if (soc_feature(unit, soc_feature_l2_overflow)) { 1844 #if defined(BCM_TRIDENT2_SUPPORT) 1845 if (SOC_IS_TD2_TT2(unit)) { 1846 rv = soc_td2_l2_overflow_start(unit); 1847 } 1848 #endif /* BCM_TRIDENT2_SUPPORT */ 1849 #if defined(BCM_HURRICANE3_SUPPORT) 1850 if (SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) { 1851 rv = soc_hr3_l2_overflow_start(unit); 1852 } 1853 #endif /* BCM_HURRICANE3_SUPPORT */ 1854 if ((BCM_FAILURE(rv)) && (rv != BCM_E_UNAVAIL)) { 1855 _bcm_l2_cbs[unit] = NULL; 1856 _bcm_l2_cb_data[unit] = NULL; 1857 L2_UNLOCK(unit); 1858 return(rv); 1859 } 1860 } 1861 #endif 1862 1863 /* See if the function is already registered (with same data) */ 1864 for (i = 0; i < L2_CB_MAX; i++) { 1865 if (ad->cb[i].fn == fn && ad->cb[i].fn_data == fn_data) { 1866 L2_UNLOCK(unit); 1867 return BCM_E_NONE; 1868 } 1869 } 1870 1871 /* Not found; add to list. */ 1872 for (i = 0; i < L2_CB_MAX; i++) { 1873 if (ad->cb[i].fn == NULL) { 1874 ad->cb[i].fn = fn; 1875 ad->cb[i].fn_data = fn_data; 1876 ad->cb_count++; 1877 break; 1878 } 1879 } 1880 1881 L2_UNLOCK(unit); 1882 return i >= L2_CB_MAX ? BCM_E_RESOURCE : BCM_E_NONE; 1883 } 1884 1885 /* 1886 * Function: 1887 * bcm_esw_l2_addr_unregister 1888 * Description: 1889 * Unregister a previously registered callback routine. 1890 * Parameters: 1891 * unit - StrataSwitch PCI device unit number (driver internal). 1892 * fn - Same callback function used to register callback 1893 * fn_data - Same arbitrary value used to register callback 1894 * Returns: 1895 * BCM_E_NONE Success, handle valid 1896 * BCM_E_MEMORY Out of memory 1897 * BCM_E_INTERNAL Chip access failure 1898 * Notes: 1899 * Both callback and userdata must match from original register call. 1900 */ 1901 1902 int 1903 bcm_esw_l2_addr_unregister(int unit, 1904 bcm_l2_addr_callback_t fn, 1905 void *fn_data) 1906 { 1907 l2_data_t *ad = &l2_data[unit]; 1908 int rv = BCM_E_NOT_FOUND; 1909 int i; 1910 1911 if (!SOC_IS_XGS_SWITCH(unit)) { 1912 return BCM_E_UNAVAIL; 1913 } 1914 1915 #if defined(BCM_TOMAHAWK3_SUPPORT) 1916 /* Added to handle SDK functions calling esw version, 1917 * instead of Tomahawk3's version 1918 */ 1919 if (SOC_IS_TOMAHAWK3(unit)) { 1920 return bcm_tomahawk3_l2_addr_unregister(unit, fn, fn_data); 1921 } 1922 #endif /* BCM_TOMAHAWK3_SUPPORT */ 1923 1924 #if defined(BCM_TRIUMPH3_SUPPORT) 1925 if (soc_feature(unit, soc_feature_ism_memory)) { 1926 return bcm_tr3_l2_addr_unregister(unit, fn, fn_data); 1927 } 1928 #endif /* BCM_TRIUMPH3_SUPPORT */ 1929 1930 L2_INIT(unit); 1931 L2_MUTEX(unit); 1932 L2_LOCK(unit); 1933 1934 for (i = 0; i < L2_CB_MAX; i++) { 1935 if((ad->cb[i].fn == fn) && (ad->cb[i].fn_data == fn_data)) { 1936 rv = BCM_E_NONE; 1937 ad->cb[i].fn = NULL; 1938 ad->cb[i].fn_data = NULL; 1939 ad->cb_count--; 1940 if (ad->cb_count == 0) { 1941 _bcm_l2_cbs[unit] = NULL; 1942 _bcm_l2_cb_data[unit] = NULL; 1943 1944 #if defined(BCM_XGS_SWITCH_SUPPORT) 1945 /* Stop l2x thread if callback registration started it. */ 1946 if (ad->flags & _BCM_L2X_THREAD_STOP) { 1947 rv = soc_l2x_stop(unit); 1948 ad->flags &= ~_BCM_L2X_THREAD_STOP; 1949 } 1950 #endif /* BCM_XGS_SWITCH_SUPPORT */ 1951 } 1952 } 1953 } 1954 1955 L2_UNLOCK(unit); 1956 return (rv); 1957 } 1958 int _bcm_esw_l2_age_timer_set(int unit, int age_seconds, int enabled) 1959 { 1960 int rv; 1961 #ifdef BCM_XGS_SWITCH_SUPPORT 1962 int frozen = 0; 1963 #endif 1964 /* Lock ARLm b/c soc_arl_freeze() does read/modify/write of AGE_TIMER */ 1965 SOC_L2X_MEM_LOCK(unit); 1966 #ifdef BCM_XGS_SWITCH_SUPPORT 1967 rv = soc_l2x_is_frozen(unit, SOC_L2X_FROZEN, &frozen); 1968 1969 if ((!SOC_IS_TRIUMPH3(unit))&& frozen) { 1970 soc_age_timer_cache_set(unit, age_seconds, enabled); 1971 enabled = 0; /* L2x is frozen, so we can't enable aging function */ 1972 } 1973 #endif 1974 1975 rv = SOC_FUNCTIONS(unit)->soc_age_timer_set(unit, age_seconds, enabled); 1976 SOC_L2X_MEM_UNLOCK(unit); 1977 return rv; 1978 } 1979 1980 /* 1981 * Function: 1982 * bcm_esw_l2_age_timer_set 1983 * Description: 1984 * Set the age timer for all blocks. 1985 * Setting the value to 0 disables the age timer. 1986 * Parameters: 1987 * unit - StrataSwitch PCI device unit number (driver internal). 1988 * age_seconds - Age timer value in seconds 1989 * Returns: 1990 * BCM_E_NONE Success 1991 * BCM_E_INTERNAL Chip access failure 1992 */ 1993 1994 int 1995 bcm_esw_l2_age_timer_set(int unit, int age_seconds) 1996 { 1997 int max_value; 1998 int enabled; 1999 int rv; 2000 2001 #if defined(BCM_TOMAHAWK3_SUPPORT) 2002 /* Added to handle SDK functions calling esw version, 2003 * instead of Tomahawk3's version 2004 */ 2005 if (SOC_IS_TOMAHAWK3(unit)) { 2006 return bcm_tomahawk3_l2_age_timer_set(unit, age_seconds); 2007 } 2008 #endif /* BCM_TOMAHAWK3_SUPPORT */ 2009 2010 L2_INIT(unit); 2011 2012 #if defined(BCM_TRIUMPH3_SUPPORT) 2013 if (soc_feature(unit, soc_feature_ism_memory)) { 2014 return bcm_tr3_l2_age_timer_set(unit, age_seconds); 2015 } 2016 #endif /* BCM_TRIUMPH3_SUPPORT */ 2017 2018 BCM_IF_ERROR_RETURN 2019 (SOC_FUNCTIONS(unit)->soc_age_timer_max_get(unit, &max_value)); 2020 2021 if (age_seconds < 0 || age_seconds > max_value) { 2022 return BCM_E_PARAM; 2023 } 2024 2025 enabled = age_seconds ? 1 : 0; 2026 2027 rv = _bcm_esw_l2_age_timer_set(unit, age_seconds, enabled); 2028 2029 return rv; 2030 } 2031 2032 /* 2033 * Function: * bcm_esw_l2_age_timer_get 2034 * Description: 2035 * Returns the current age timer value. 2036 * The value is 0 if aging is not enabled. 2037 * Parameters: 2038 * unit - StrataSwitch PCI device unit number (driver internal). 2039 * age_seconds - Place to store returned age timer value in seconds 2040 * Returns: 2041 * BCM_E_NONE Success 2042 * BCM_E_INTERNAL Chip access failure 2043 */ 2044 2045 int 2046 bcm_esw_l2_age_timer_get(int unit, int *age_seconds) 2047 { 2048 int seconds, enabled; 2049 int rv; 2050 2051 #if defined(BCM_TOMAHAWK3_SUPPORT) 2052 /* Added to handle SDK functions calling esw version, 2053 * instead of Tomahawk3's version 2054 */ 2055 if (SOC_IS_TOMAHAWK3(unit)) { 2056 return bcm_tomahawk3_l2_age_timer_get(unit, age_seconds); 2057 } 2058 #endif /* BCM_TOMAHAWK3_SUPPORT */ 2059 2060 L2_INIT(unit); 2061 2062 if (age_seconds == NULL) { 2063 return BCM_E_PARAM; 2064 } 2065 2066 #if defined(BCM_TRIUMPH3_SUPPORT) 2067 if (soc_feature(unit, soc_feature_ism_memory)) { 2068 return bcm_tr3_l2_age_timer_get(unit, age_seconds); 2069 } 2070 #endif /* BCM_TRIUMPH3_SUPPORT */ 2071 2072 /* 2073 * Lock ARLm because soc_arl_freeze() does read/modify/write of 2074 * AGE_TIMER 2075 */ 2076 2077 SOC_L2X_MEM_LOCK(unit); 2078 rv = SOC_FUNCTIONS(unit)->soc_age_timer_get(unit, &seconds, &enabled); 2079 SOC_L2X_MEM_UNLOCK(unit); 2080 2081 BCM_IF_ERROR_RETURN(rv); 2082 2083 if (enabled) { 2084 *age_seconds = seconds; 2085 } else { 2086 *age_seconds = 0; 2087 } 2088 2089 return BCM_E_NONE; 2090 } 2091 2092 /*internal function*/ 2093 int 2094 _bcm_esw_l2_age_timer_get(int unit, int *age_seconds) 2095 { 2096 int rv = BCM_E_NONE; 2097 #ifdef BCM_XGS_SWITCH_SUPPORT 2098 int frozen = 0; 2099 #endif 2100 int enabled; 2101 /* Lock ARLm b/c soc_arl_freeze() does read/modify/write of AGE_TIMER */ 2102 SOC_L2X_MEM_LOCK(unit); 2103 2104 #ifdef BCM_XGS_SWITCH_SUPPORT 2105 rv = soc_l2x_is_frozen(unit, SOC_L2X_FROZEN, &frozen); 2106 2107 if (BCM_FAILURE(rv)) { 2108 frozen = 0; 2109 } 2110 if ((!SOC_IS_TRIUMPH3(unit)) && frozen) { 2111 soc_age_timer_cache_get(unit, age_seconds, &enabled); 2112 2113 SOC_L2X_MEM_UNLOCK(unit); 2114 return rv; 2115 } 2116 #endif 2117 rv = SOC_FUNCTIONS(unit)->soc_age_timer_get(unit, age_seconds, &enabled); 2118 2119 SOC_L2X_MEM_UNLOCK(unit); 2120 return rv; 2121 } 2122 2123 2124 /* 2125 * Function: 2126 * bcm_esw_l2_addr_freeze 2127 * Description: 2128 * Temporarily quiesce ARL from all activity (learning, aging, inserting) 2129 * include SW operations 2130 * Parameters: 2131 * unit - StrataSwitch PCI device unit number (driver internal). 2132 * Returns: 2133 * BCM_E_NONE Success 2134 * BCM_E_INTERNAL Chip access failure 2135 */ 2136 2137 int 2138 bcm_esw_l2_addr_freeze(int unit) 2139 { 2140 #if defined(BCM_TOMAHAWK3_SUPPORT) 2141 /* Added to handle SDK functions calling esw version, 2142 * instead of Tomahawk3's version 2143 */ 2144 if (SOC_IS_TOMAHAWK3(unit)) { 2145 return bcm_tomahawk3_l2_addr_freeze(unit); 2146 } 2147 #endif /* BCM_TOMAHAWK3_SUPPORT */ 2148 2149 L2_INIT(unit); 2150 2151 #ifdef BCM_XGS_SWITCH_SUPPORT 2152 if (soc_feature(unit, soc_feature_arl_hashed)) { 2153 return soc_l2x_freeze(unit); 2154 } 2155 #endif 2156 2157 return BCM_E_UNAVAIL; 2158 } 2159 2160 /* 2161 * Function: 2162 * bcm_esw_l2_addr_thaw 2163 * Description: 2164 * Restore normal ARL activity including S/W and H/W activity. 2165 * Parameters: 2166 * unit - StrataSwitch PCI device unit number (driver internal). 2167 * Returns: 2168 * BCM_E_NONE Success 2169 * BCM_E_INTERNAL Chip access failure 2170 */ 2171 2172 int 2173 bcm_esw_l2_addr_thaw(int unit) 2174 { 2175 #if defined(BCM_TOMAHAWK3_SUPPORT) 2176 /* Added to handle SDK functions calling esw version, 2177 * instead of Tomahawk3's version 2178 */ 2179 if (SOC_IS_TOMAHAWK3(unit)) { 2180 return bcm_tomahawk3_l2_addr_thaw(unit); 2181 } 2182 #endif /* BCM_TOMAHAWK3_SUPPORT */ 2183 2184 L2_INIT(unit); 2185 2186 #if defined(BCM_TRIUMPH3_SUPPORT) 2187 if (soc_feature(unit, soc_feature_ism_memory)) { 2188 return soc_tr3_l2_thaw(unit); 2189 } 2190 #endif /* BCM_TRIUMPH3_SUPPORT */ 2191 2192 #ifdef BCM_XGS_SWITCH_SUPPORT 2193 if (soc_feature(unit, soc_feature_arl_hashed)) { 2194 return soc_l2x_thaw(unit); 2195 } 2196 #endif 2197 2198 return BCM_E_UNAVAIL; 2199 } 2200 2201 2202 /* 2203 * Function: 2204 * _bcm_l2_bpdu_init 2205 * Description: 2206 * Initialize all BPDU addresses to recognize the 802.1D 2207 * Spanning Tree address on all chips. 2208 * Parameters: 2209 * unit - StrataSwitch PCI device unit number (driver internal). 2210 * Returns: 2211 * BCM_E_XXX 2212 * Notes: 2213 */ 2214 2215 static int 2216 _bcm_l2_bpdu_init(int unit) 2217 { 2218 int i, nbpdu; 2219 sal_mac_addr_t mac; 2220 2221 BCM_IF_ERROR_RETURN(bcm_esw_l2_cache_size_get(unit, &nbpdu)); 2222 2223 /* Spanning Tree addr (01:80:c2:00:00:00) used as default entries */ 2224 mac[0] = 0x01; 2225 mac[1] = 0x80; 2226 mac[2] = 0xc2; 2227 mac[3] = mac[4] = mac[5] = 0x00; 2228 2229 for (i = 0; i < nbpdu; i++) { 2230 BCM_IF_ERROR_RETURN(soc_bpdu_addr_set(unit, i, mac)); 2231 } 2232 return BCM_E_NONE; 2233 } 2234 2235 /* 2236 * Function: 2237 * bcm_esw_l2_key_dump 2238 * Purpose: 2239 * Dump the key (VLAN+MAC) portion of a hardware-independent 2240 * L2 address for debugging 2241 * Parameters: 2242 * unit - Unit number 2243 * pfx - String to print before output 2244 * entry - Hardware-independent L2 entry to dump 2245 * sfx - String to print after output 2246 */ 2247 2248 int 2249 bcm_esw_l2_key_dump(int unit, char *pfx, bcm_l2_addr_t *entry, char *sfx) 2250 { 2251 #if defined(BCM_TOMAHAWK3_SUPPORT) 2252 /* Added to handle SDK functions calling esw version, 2253 * instead of Tomahawk3's version 2254 */ 2255 if (SOC_IS_TOMAHAWK3(unit)) { 2256 return bcm_tomahawk3_l2_key_dump(unit, pfx, entry, sfx); 2257 } 2258 #endif /* BCM_TOMAHAWK3_SUPPORT */ 2259 2260 LOG_CLI((BSL_META_U(unit, 2261 "l2: %sVLAN=0x%03x MAC=0x%02x%02x%02x" 2262 "%02x%02x%02x%s"), pfx, entry->vid, 2263 entry->mac[0], entry->mac[1], entry->mac[2], 2264 entry->mac[3], entry->mac[4], entry->mac[5], sfx)); 2265 2266 return BCM_E_NONE; 2267 } 2268 2269 /* 2270 * Function: 2271 * bcm_esw_l2_conflict_get 2272 * Purpose: 2273 * Given an L2 address, return existing addresses which could conflict. 2274 * Parameters: 2275 * unit - switch device 2276 * addr - l2 address to search for conflicts 2277 * cf_array - (OUT) list of l2 addresses conflicting with addr 2278 * cf_max - number of entries allocated to cf_array 2279 * cf_count - (OUT) actual number of cf_array entries filled 2280 * Returns: 2281 * BCM_E_XXX 2282 * Notes: 2283 * Given an L2 or L2 multicast address, return any existing L2 or 2284 * L2 multicast addresses which might prevent it from being 2285 * inserted because a chip resource (like a hash bucket) is full. 2286 * This routine could be used if bcm_l2_addr_add or bcm_l2_mcast_add 2287 * returns BCM_E_FULL. 2288 */ 2289 2290 int 2291 bcm_esw_l2_conflict_get(int unit, bcm_l2_addr_t *addr, 2292 bcm_l2_addr_t *cf_array, int cf_max, 2293 int *cf_count) 2294 { 2295 #if defined(BCM_TOMAHAWK3_SUPPORT) 2296 /* Added to handle SDK functions calling esw version, 2297 * instead of Tomahawk3's version 2298 */ 2299 if (SOC_IS_TOMAHAWK3(unit)) { 2300 return bcm_tomahawk3_l2_conflict_get(unit, addr, cf_array, cf_max, 2301 cf_count); 2302 } 2303 #endif /* BCM_TOMAHAWK3_SUPPORT */ 2304 2305 L2_INIT(unit); 2306 /* 2307 * Call chip-dependent handler. 2308 */ 2309 SOC_IF_ERROR_RETURN 2310 (mbcm_driver[unit]->mbcm_l2_conflict_get(unit, addr, 2311 cf_array, cf_max, cf_count)); 2312 2313 return BCM_E_NONE; 2314 } 2315 2316 /* 2317 * Function: 2318 * bcm_esw_l2_tunnel_add 2319 * Purpose: 2320 * Add a (MAC, VLAN) for tunnel/MPLS processing, frames 2321 * destined to (MAC, VLAN) is subjected to TUNNEL/MPLS processing. 2322 * Parameters: 2323 * unit - StrataXGS unit number 2324 * mac - MAC address 2325 * vlan - VLAN ID 2326 */ 2327 2328 int 2329 bcm_esw_l2_tunnel_add(int unit, bcm_mac_t mac, bcm_vlan_t vlan) 2330 { 2331 #if defined(BCM_TOMAHAWK3_SUPPORT) 2332 /* Added to handle SDK functions calling esw version, 2333 * instead of Tomahawk3's version 2334 */ 2335 if (SOC_IS_TOMAHAWK3(unit)) { 2336 return bcm_tomahawk3_l2_tunnel_add(unit, mac, vlan); 2337 } 2338 #endif /* BCM_TOMAHAWK3_SUPPORT */ 2339 2340 L2_INIT(unit); 2341 2342 if (SOC_IS_HURRICANEX(unit) || SOC_IS_GREYHOUND(unit) || 2343 SOC_IS_GREYHOUND2(unit)) { 2344 return BCM_E_UNAVAIL; 2345 } 2346 #if defined(BCM_TRIUMPH3_SUPPORT) 2347 if (soc_feature(unit, soc_feature_ism_memory)) { 2348 VLAN_CHK_ID(unit, vlan); 2349 return bcm_tr3_l2_tunnel_add(unit, mac, vlan); 2350 } 2351 #endif /* BCM_TRIUMPH3_SUPPORT */ 2352 2353 #if defined (BCM_TRIDENT_SUPPORT) && defined(BCM_MPLS_SUPPORT) && \ 2354 defined(INCLUDE_L3) 2355 if (SOC_IS_TD_TT(unit) || SOC_IS_KATANAX(unit)) { 2356 VLAN_CHK_ID(unit, vlan); 2357 #if defined(BCM_TOMAHAWK_SUPPORT) 2358 if (SOC_MEM_IS_VALID(unit, MY_STATION_TCAMm)) { 2359 return bcm_td_metro_myStation_add(unit, mac, vlan, -1, 1); 2360 } 2361 else { 2362 return BCM_E_UNAVAIL; 2363 } 2364 #else 2365 return bcm_td_metro_myStation_add(unit, mac, vlan, -1, 1); 2366 #endif 2367 } 2368 #endif /* BCM_TRIDENT_SUPPORT */ 2369 2370 #if defined(BCM_TRIUMPH_SUPPORT) && defined(BCM_MPLS_SUPPORT) && \ 2371 defined(INCLUDE_L3) 2372 if (SOC_IS_TR_VL(unit)) { 2373 VLAN_CHK_ID(unit, vlan); 2374 return bcm_trx_metro_l2_tunnel_add(unit, mac, vlan); 2375 } 2376 #endif 2377 2378 return BCM_E_UNAVAIL; 2379 } 2380 2381 /* 2382 * Function: 2383 * bcm_esw_l2_tunnel_delete 2384 * Purpose: 2385 * Remove a tunnel processing indicator for an L2 address 2386 * Parameters: 2387 * unit - StrataXGS unit number 2388 * mac - MAC address 2389 vlan - VLAN ID 2390 */ 2391 2392 int 2393 bcm_esw_l2_tunnel_delete(int unit, bcm_mac_t mac, bcm_vlan_t vlan) 2394 { 2395 #if defined(BCM_TOMAHAWK3_SUPPORT) 2396 /* Added to handle SDK functions calling esw version, 2397 * instead of Tomahawk3's version 2398 */ 2399 if (SOC_IS_TOMAHAWK3(unit)) { 2400 return bcm_tomahawk3_l2_tunnel_delete(unit, mac, vlan); 2401 } 2402 #endif /* BCM_TOMAHAWK3_SUPPORT */ 2403 2404 L2_INIT(unit); 2405 2406 if (SOC_IS_HURRICANEX(unit) || SOC_IS_GREYHOUND(unit) || 2407 SOC_IS_GREYHOUND2(unit)) { 2408 return BCM_E_UNAVAIL; 2409 } 2410 2411 #if defined(BCM_TRIUMPH3_SUPPORT) 2412 if (soc_feature(unit, soc_feature_ism_memory)) { 2413 VLAN_CHK_ID(unit, vlan); 2414 return bcm_tr3_l2_tunnel_delete(unit, mac, vlan); 2415 } 2416 #endif /* BCM_TRIUMPH3_SUPPORT */ 2417 2418 #if defined(BCM_TRIDENT_SUPPORT) && defined(BCM_MPLS_SUPPORT) && \ 2419 defined(INCLUDE_L3) 2420 if (SOC_IS_TD_TT(unit) || SOC_IS_KATANAX(unit)) { 2421 VLAN_CHK_ID(unit, vlan); 2422 return bcm_td_metro_myStation_delete(unit, mac, vlan, -1, 1); 2423 } 2424 #endif /* BCM_TRIDENT_SUPPORT */ 2425 2426 #if defined(BCM_TRIUMPH_SUPPORT) && defined(BCM_MPLS_SUPPORT) && \ 2427 defined(INCLUDE_L3) 2428 if (SOC_IS_TR_VL(unit)) { 2429 VLAN_CHK_ID(unit, vlan); 2430 return bcm_trx_metro_l2_tunnel_delete(unit, mac, vlan); 2431 } 2432 #endif 2433 return BCM_E_UNAVAIL; 2434 2435 } 2436 2437 /* 2438 * Function: 2439 * bcm_l2_tunnel_delete_all 2440 * Purpose: 2441 * Remove all tunnel processing indicating L2 addresses 2442 * Parameters: 2443 * unit - StrataXGS unit number 2444 */ 2445 2446 int 2447 bcm_esw_l2_tunnel_delete_all(int unit) 2448 { 2449 #if defined(BCM_TOMAHAWK3_SUPPORT) 2450 /* Added to handle SDK functions calling esw version, 2451 * instead of Tomahawk3's version 2452 */ 2453 if (SOC_IS_TOMAHAWK3(unit)) { 2454 return bcm_tomahawk3_l2_tunnel_delete_all(unit); 2455 } 2456 #endif /* BCM_TOMAHAWK3_SUPPORT */ 2457 2458 L2_INIT(unit); 2459 2460 if (SOC_IS_HURRICANEX(unit) || SOC_IS_GREYHOUND(unit) || 2461 SOC_IS_GREYHOUND2(unit)) { 2462 return BCM_E_UNAVAIL; 2463 } 2464 2465 #if defined(BCM_TRIUMPH3_SUPPORT) 2466 if (soc_feature(unit, soc_feature_ism_memory)) { 2467 return bcm_tr3_l2_tunnel_delete_all(unit); 2468 } 2469 #endif /* BCM_TRIUMPH3_SUPPORT */ 2470 2471 #if defined(BCM_TRIDENT_SUPPORT) && defined(BCM_MPLS_SUPPORT) && \ 2472 defined(INCLUDE_L3) 2473 if (SOC_IS_TD_TT(unit)||SOC_IS_KATANAX(unit)) { 2474 return bcm_td_metro_myStation_delete_all(unit); 2475 } 2476 #endif /* BCM_TRIDENT_SUPPORT */ 2477 2478 #if defined(BCM_TRIUMPH_SUPPORT) && defined(BCM_MPLS_SUPPORT) && \ 2479 defined(INCLUDE_L3) 2480 if (SOC_IS_TR_VL(unit)) { 2481 return bcm_trx_metro_l2_tunnel_delete_all(unit); 2482 } 2483 #endif 2484 2485 return BCM_E_UNAVAIL; 2486 } 2487 2488 /* 2489 * Function: 2490 * bcm_esw_l2_clear 2491 * Purpose: 2492 * Clear the L2 layer 2493 * Parameters: 2494 * unit - BCM unit number 2495 * Returns: 2496 * BCM_E_XXX 2497 */ 2498 2499 int 2500 bcm_esw_l2_clear(int unit) 2501 { 2502 #if defined(BCM_TOMAHAWK3_SUPPORT) 2503 /* Added to handle SDK functions calling esw version, 2504 * instead of Tomahawk3's version 2505 */ 2506 if (SOC_IS_TOMAHAWK3(unit)) { 2507 return bcm_tomahawk3_l2_clear(unit); 2508 } 2509 #endif /* BCM_TOMAHAWK3_SUPPORT */ 2510 2511 L2_INIT(unit); 2512 2513 #if defined(BCM_TRIUMPH3_SUPPORT) 2514 if (soc_feature(unit, soc_feature_ism_memory)) { 2515 return bcm_tr3_l2_clear(unit); 2516 } 2517 #endif /* BCM_TRIUMPH3_SUPPORT */ 2518 2519 if (_bcm_l2_match_ctrl[unit]) { 2520 _bcm_l2_match_ctrl[unit]->preserved = 1; 2521 } 2522 2523 bcm_esw_l2_detach(unit); 2524 2525 if (_bcm_l2_match_ctrl[unit]) { 2526 _bcm_l2_match_ctrl[unit]->preserved = 0; 2527 } 2528 2529 /* 2530 * Call chip-dependent initialization 2531 */ 2532 BCM_IF_ERROR_RETURN(mbcm_driver[unit]->mbcm_l2_init(unit)); 2533 2534 #if defined(BCM_XGS_SWITCH_SUPPORT) 2535 /* Stop l2x thread if callback registration started it. */ 2536 if (l2_data[unit].flags & _BCM_L2X_THREAD_STOP) { 2537 BCM_IF_ERROR_RETURN(soc_l2x_stop(unit)); 2538 } 2539 #endif /* BCM_XGS_SWITCH_SUPPORT */ 2540 2541 /* Clear l2_data structure */ 2542 l2_data[unit].cb_count = 0; 2543 l2_data[unit].flags = 0; 2544 sal_memset(&l2_data[unit].cb, 0, sizeof(l2_data[unit].cb)); 2545 2546 _l2_init[unit] = 1; /* some positive value */ 2547 2548 return BCM_E_NONE; 2549 } 2550 2551 /* 2552 * MAC learn limit 2553 */ 2554 #ifdef BCM_TRIUMPH_SUPPORT 2555 /* 2556 * Function: 2557 * _bcm_tr_l2_learn_limit_system_set 2558 * Purpose: 2559 * Set MAC learn limit for a system 2560 * Parameters: 2561 * unit - BCM unit number 2562 * flags - Action bitmask 2563 * limit - System limit of MAC addresses to learn 2564 * Negative limit disables the check 2565 * Returns: 2566 * BCM_E_XXX 2567 */ 2568 STATIC int 2569 _bcm_tr_l2_learn_limit_system_set(int unit, uint32 flags, int limit) 2570 { 2571 uint32 rval, orval; 2572 int tocpu, drop, enable; 2573 2574 if (limit < 0) { 2575 tocpu = 0; 2576 drop = 0; 2577 limit = soc_mem_index_max(unit, L2Xm); 2578 enable = 0; 2579 } else { 2580 tocpu = flags & BCM_L2_LEARN_LIMIT_ACTION_CPU ? 1 : 0; 2581 drop = flags & BCM_L2_LEARN_LIMIT_ACTION_DROP ? 1 : 0; 2582 enable = 1; 2583 } 2584 2585 /* Starting from Triumph this flag is not supported */ 2586 if (flags & BCM_L2_LEARN_LIMIT_ACTION_PREFER) { 2587 return BCM_E_PARAM; 2588 } 2589 2590 BCM_IF_ERROR_RETURN(READ_SYS_MAC_LIMIT_CONTROLr(unit, &rval)); 2591 orval = rval; 2592 soc_reg_field_set(unit, SYS_MAC_LIMIT_CONTROLr, &rval, 2593 SYS_OVER_LIMIT_TOCPUf, tocpu); 2594 soc_reg_field_set(unit, SYS_MAC_LIMIT_CONTROLr, &rval, 2595 SYS_OVER_LIMIT_DROPf, drop); 2596 soc_reg_field_set(unit, SYS_MAC_LIMIT_CONTROLr, &rval, SYS_LIMITf, limit); 2597 soc_reg_field_set(unit, SYS_MAC_LIMIT_CONTROLr, &rval, ENABLEf, enable); 2598 if (rval != orval) { 2599 BCM_IF_ERROR_RETURN(WRITE_SYS_MAC_LIMIT_CONTROLr(unit, rval)); 2600 } 2601 2602 return BCM_E_NONE; 2603 } 2604 2605 /* 2606 * Function: 2607 * _bcm_tr_l2_learn_limit_system_get 2608 * Purpose: 2609 * Get MAC learn limit for a system 2610 * Parameters: 2611 * unit - BCM unit number 2612 * flags - Action bitmask 2613 * limit - System limit of MAC addresses to learn 2614 * Negative if limit disabled 2615 * Returns: 2616 * BCM_E_XXX 2617 */ 2618 STATIC int 2619 _bcm_tr_l2_learn_limit_system_get(int unit, uint32 *flags, int *limit) 2620 { 2621 uint32 rval; 2622 2623 BCM_IF_ERROR_RETURN(READ_SYS_MAC_LIMIT_CONTROLr(unit, &rval)); 2624 *flags &= ~(BCM_L2_LEARN_LIMIT_ACTION_DROP | 2625 BCM_L2_LEARN_LIMIT_ACTION_CPU); 2626 if (soc_reg_field_get(unit, SYS_MAC_LIMIT_CONTROLr, rval, 2627 SYS_OVER_LIMIT_TOCPUf)) { 2628 *flags |= BCM_L2_LEARN_LIMIT_ACTION_CPU; 2629 } 2630 if (soc_reg_field_get(unit, SYS_MAC_LIMIT_CONTROLr, rval, 2631 SYS_OVER_LIMIT_DROPf)) { 2632 *flags |= BCM_L2_LEARN_LIMIT_ACTION_DROP; 2633 } 2634 if (soc_reg_field_get(unit, SYS_MAC_LIMIT_CONTROLr, rval, ENABLEf)) { 2635 *limit = soc_reg_field_get(unit, SYS_MAC_LIMIT_CONTROLr, rval, 2636 SYS_LIMITf); 2637 } else { 2638 *limit = -1; 2639 } 2640 2641 return BCM_E_NONE; 2642 } 2643 2644 /* 2645 * Function: 2646 * _bcm_tr_l2_learn_limit_set 2647 * Purpose: 2648 * Set MAC learn limit for a port/trunk/vlan 2649 * Parameters: 2650 * unit - BCM unit number 2651 * mem - PORT_OR_TRUNK_MAC_LIMITm or VLAN_OR_VFI_MAC_LIMITm 2652 * index - for PORT_OR_TRUNK_MAC_LIMITm 2653 * 0 - 127: trunk identifier 2654 * 128 - 181: port identifier + 128 2655 * for VLAN_OR_VFI_MAC_LIMITm 2656 * 0 - 4095: VLAN identifier 2657 * 4096 - 5119: virtual forwarding instance + 4096 2658 * flags - Action bitmask 2659 * limit - Max number of MAC addresses can be learned for the specified 2660 * identifier 2661 * Negative if limit disabled (i.e. unlimit) 2662 * Returns: 2663 * BCM_E_XXX 2664 */ 2665 STATIC int 2666 _bcm_tr_l2_learn_limit_set(int unit, soc_mem_t mem, int index, uint32 flags, 2667 int limit) 2668 { 2669 uint32 entry[SOC_MAX_MEM_WORDS], rval; 2670 int rv; 2671 #if defined(BCM_ENDURO_SUPPORT) || defined(BCM_HURRICANE_SUPPORT) 2672 port_or_trunk_mac_limit_entry_t init_entry; 2673 uint32 max_limit = BCM_MAC_LIMIT_MAX; 2674 #endif /* BCM_ENDURO_SUPPORT || BCM_HURRICANE_SUPPORT */ 2675 2676 if (limit < 0) { 2677 soc_mem_lock(unit, mem); 2678 rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, index, 2679 soc_mem_entry_null(unit, mem)); 2680 #if defined(BCM_ENDURO_SUPPORT) || defined(BCM_HURRICANE_SUPPORT) 2681 if (SOC_IS_ENDURO(unit) || SOC_IS_HURRICANEX(unit) || 2682 SOC_IS_GREYHOUND(unit) || SOC_IS_GREYHOUND2(unit)) { 2683 /* Reset Limit value is different than soc_mem_entry_null for different SKUs */ 2684 soc_mem_field32_set(unit, mem, &init_entry, LIMITf, max_limit); 2685 rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, index, &init_entry); 2686 } 2687 #endif /* BCM_ENDURO_SUPPORT || BCM_HURRICANE_SUPPORT */ 2688 soc_mem_unlock(unit, mem); 2689 return rv; 2690 } 2691 2692 soc_mem_lock(unit, mem); 2693 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, index, &entry); 2694 if (BCM_SUCCESS(rv)) { 2695 soc_mem_field32_set(unit, mem, &entry, OVER_LIMIT_TOCPUf, 2696 flags & BCM_L2_LEARN_LIMIT_ACTION_CPU ? 1 : 0); 2697 soc_mem_field32_set(unit, mem, &entry, OVER_LIMIT_DROPf, 2698 flags & BCM_L2_LEARN_LIMIT_ACTION_DROP ? 1 : 0); 2699 soc_mem_field32_set(unit, mem, &entry, LIMITf, limit); 2700 rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, index, &entry); 2701 } 2702 soc_mem_unlock(unit, mem); 2703 2704 if (BCM_FAILURE(rv)) { 2705 return rv; 2706 } 2707 2708 BCM_IF_ERROR_RETURN(READ_SYS_MAC_LIMIT_CONTROLr(unit, &rval)); 2709 soc_reg_field_set(unit, SYS_MAC_LIMIT_CONTROLr, &rval, ENABLEf, 1); 2710 return (WRITE_SYS_MAC_LIMIT_CONTROLr(unit, rval)); 2711 } 2712 2713 /* 2714 * Function: 2715 * _bcm_tr_l2_learn_limit_get 2716 * Purpose: 2717 * Get MAC learn limit for a port/trunk/vlan 2718 * Parameters: 2719 * unit - BCM unit number 2720 * mem - PORT_OR_TRUNK_MAC_LIMITm or VLAN_OR_VFI_MAC_LIMITm 2721 * index - for PORT_OR_TRUNK_MAC_LIMITm 2722 * 0 - 127: trunk identifier 2723 * 128 - 181: port identifier + 128 2724 * for VLAN_OR_VFI_MAC_LIMITm 2725 * 0 - 4095: VLAN identifier 2726 * 4096 - 5119: virtual forwarding instance + 4096 2727 * flags - Action bitmask 2728 * limit - Max number of MAC addresses can be learned for the specified 2729 * identifier 2730 * Negative if limit disabled (i.e. unlimit) 2731 * Returns: 2732 * BCM_E_XXX 2733 */ 2734 STATIC int 2735 _bcm_tr_l2_learn_limit_get(int unit, soc_mem_t mem, int index, uint32* flags, 2736 int* limit) 2737 { 2738 uint32 entry[SOC_MAX_MEM_WORDS]; 2739 2740 SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ANY, index, &entry)); 2741 *flags &= ~(BCM_L2_LEARN_LIMIT_ACTION_DROP | 2742 BCM_L2_LEARN_LIMIT_ACTION_CPU); 2743 if (soc_mem_field32_get(unit, mem, &entry, OVER_LIMIT_DROPf)) { 2744 *flags |= BCM_L2_LEARN_LIMIT_ACTION_DROP; 2745 } 2746 if (soc_mem_field32_get(unit, mem, &entry, OVER_LIMIT_TOCPUf)) { 2747 *flags |= BCM_L2_LEARN_LIMIT_ACTION_CPU; 2748 } 2749 *limit = soc_mem_field32_get(unit, mem, &entry, LIMITf); 2750 2751 return BCM_E_NONE; 2752 } 2753 #endif 2754 2755 #if defined(BCM_ENDURO_SUPPORT) || defined(BCM_HURRICANE_SUPPORT) 2756 /* 2757 * Function: 2758 * _bcm_enduro_l2_learn_limit_init 2759 * Purpose: 2760 * Init the system to support MAC learn limit 2761 * Parameters: 2762 * unit - BCM unit number 2763 * Returns: 2764 * BCM_E_XXX 2765 */ 2766 STATIC int 2767 _bcm_enduro_l2_learn_limit_init(int unit) 2768 { 2769 uint32 maxInitVal; 2770 int rv, idx, idx_min, idx_max; 2771 uint8 *port_or_trunk_mac_limit_buf = NULL; 2772 uint8 *vlan_or_vfi_mac_limit_buf = NULL; 2773 vlan_or_vfi_mac_limit_entry_t *vlan_or_vfi_mac_limit_entry = NULL; 2774 port_or_trunk_mac_limit_entry_t *port_or_trunk_mac_limit_entry = NULL; 2775 maxInitVal = BCM_MAC_LIMIT_MAX; 2776 2777 BCM_IF_ERROR_RETURN(_bcm_tr_l2_learn_limit_system_set(unit, 0, -1)); 2778 BCM_IF_ERROR_RETURN 2779 (soc_mem_clear(unit, PORT_OR_TRUNK_MAC_LIMITm, COPYNO_ALL, FALSE)); 2780 BCM_IF_ERROR_RETURN 2781 (soc_mem_clear(unit, VLAN_OR_VFI_MAC_LIMITm, COPYNO_ALL, FALSE)); 2782 2783 /* PORT_OR_TRUNK_MAC_LIMIT table*/ 2784 port_or_trunk_mac_limit_buf = soc_cm_salloc(unit, 2785 SOC_MEM_TABLE_BYTES(unit,PORT_OR_TRUNK_MAC_LIMITm), 2786 "port_or_trunk"); 2787 if (port_or_trunk_mac_limit_buf == NULL) { 2788 return BCM_E_MEMORY; 2789 } 2790 2791 idx_min = soc_mem_index_min(unit, PORT_OR_TRUNK_MAC_LIMITm); 2792 idx_max = soc_mem_index_max(unit, PORT_OR_TRUNK_MAC_LIMITm); 2793 rv = soc_mem_read_range(unit, PORT_OR_TRUNK_MAC_LIMITm, 2794 MEM_BLOCK_ANY, idx_min, idx_max, 2795 port_or_trunk_mac_limit_buf); 2796 2797 if (BCM_FAILURE(rv)) { 2798 goto cleanup; 2799 } 2800 2801 for(idx = idx_min; idx<= idx_max; idx++) { 2802 port_or_trunk_mac_limit_entry = 2803 soc_mem_table_idx_to_pointer(unit, PORT_OR_TRUNK_MAC_LIMITm, 2804 port_or_trunk_mac_limit_entry_t *, 2805 port_or_trunk_mac_limit_buf, 2806 idx); 2807 soc_PORT_OR_TRUNK_MAC_LIMITm_field32_set(unit, 2808 port_or_trunk_mac_limit_entry, 2809 LIMITf, maxInitVal); 2810 } 2811 rv = soc_mem_write_range(unit, PORT_OR_TRUNK_MAC_LIMITm, MEM_BLOCK_ALL, 2812 idx_min, idx_max, port_or_trunk_mac_limit_buf); 2813 if (BCM_FAILURE(rv)) { 2814 goto cleanup; 2815 } 2816 2817 /* VLAN_OR_VFI_MAC_LIMIT table*/ 2818 vlan_or_vfi_mac_limit_buf = soc_cm_salloc(unit, 2819 SOC_MEM_TABLE_BYTES(unit, VLAN_OR_VFI_MAC_LIMITm), 2820 "vlan_or_vfi"); 2821 if (vlan_or_vfi_mac_limit_buf == NULL) { 2822 rv = BCM_E_MEMORY; 2823 goto cleanup; 2824 } 2825 2826 idx_min = soc_mem_index_min(unit, VLAN_OR_VFI_MAC_LIMITm); 2827 idx_max = soc_mem_index_max(unit, VLAN_OR_VFI_MAC_LIMITm); 2828 rv = soc_mem_read_range(unit, VLAN_OR_VFI_MAC_LIMITm, 2829 MEM_BLOCK_ANY, idx_min, idx_max, 2830 vlan_or_vfi_mac_limit_buf); 2831 2832 if (BCM_FAILURE(rv)) { 2833 goto cleanup; 2834 } 2835 2836 for(idx = idx_min; idx<= idx_max; idx++) { 2837 vlan_or_vfi_mac_limit_entry = 2838 soc_mem_table_idx_to_pointer(unit, VLAN_OR_VFI_MAC_LIMITm, 2839 vlan_or_vfi_mac_limit_entry_t *, 2840 vlan_or_vfi_mac_limit_buf, 2841 idx); 2842 soc_PORT_OR_TRUNK_MAC_LIMITm_field32_set(unit, 2843 vlan_or_vfi_mac_limit_entry, 2844 LIMITf, maxInitVal); 2845 } 2846 rv = soc_mem_write_range(unit, VLAN_OR_VFI_MAC_LIMITm, MEM_BLOCK_ALL, 2847 idx_min, idx_max, vlan_or_vfi_mac_limit_buf); 2848 if (BCM_FAILURE(rv)) { 2849 goto cleanup; 2850 } 2851 2852 2853 cleanup: 2854 2855 if (port_or_trunk_mac_limit_buf) { 2856 soc_cm_sfree(unit, port_or_trunk_mac_limit_buf); 2857 } 2858 2859 if (vlan_or_vfi_mac_limit_buf) { 2860 soc_cm_sfree(unit, vlan_or_vfi_mac_limit_buf); 2861 } 2862 2863 return rv; 2864 } 2865 #endif /* BCM_ENDURO_SUPPORT || BCM_HURRICANE_SUPPORT */ 2866 2867 #define PORT_COUNT(unit) (SOC_INFO(unit).port_num) 2868 2869 #if defined(BCM_TRIUMPH_SUPPORT) || defined(BCM_RAPTOR_SUPPORT) 2870 /* 2871 * Function: 2872 * _bcm_l2_learn_limit_porttrunk_set 2873 * Purpose: 2874 * helper function to configure registers 2875 * Parameters: 2876 * unit - BCM unit number 2877 * port_tgid - Port or Trunk number 2878 * flags - Action bitmask 2879 * limit - Per port limit of MAC addresses to learn 2880 * Negative if limit disabled 2881 * Returns: 2882 * BCM_E_XXX 2883 */ 2884 2885 STATIC int 2886 _bcm_l2_learn_limit_porttrunk_set(int unit, int port_tgid, uint32 flags, 2887 int limit) 2888 { 2889 int rv = BCM_E_NONE; 2890 port_or_trunk_mac_limit_entry_t lim_entry; 2891 port_or_trunk_mac_action_entry_t act_entry; 2892 2893 2894 if (limit > BCM_MAC_LIMIT_MAX){ 2895 return BCM_E_PARAM; 2896 } 2897 /* Negative limit disables the check */ 2898 if (limit < 0) { 2899 soc_mem_lock(unit, PORT_OR_TRUNK_MAC_LIMITm); 2900 2901 rv = READ_PORT_OR_TRUNK_MAC_LIMITm(unit, MEM_BLOCK_ANY, port_tgid, &lim_entry); 2902 if ( BCM_E_NONE == rv) { 2903 soc_PORT_OR_TRUNK_MAC_LIMITm_field32_set(unit, &lim_entry, 2904 PORT_TRUNK_MAC_LIMITf, 2905 BCM_MAC_LIMIT_MAX); 2906 rv = WRITE_PORT_OR_TRUNK_MAC_LIMITm(unit, MEM_BLOCK_ALL, 2907 port_tgid, &lim_entry); 2908 } 2909 soc_mem_unlock(unit, PORT_OR_TRUNK_MAC_LIMITm); 2910 2911 return rv; 2912 } 2913 2914 2915 /* If everything is OK - configure the registers */ 2916 soc_mem_lock(unit, PORT_OR_TRUNK_MAC_LIMITm); 2917 2918 rv = READ_PORT_OR_TRUNK_MAC_LIMITm(unit, MEM_BLOCK_ANY, port_tgid, &lim_entry); 2919 if (BCM_E_NONE == rv) { 2920 soc_PORT_OR_TRUNK_MAC_LIMITm_field32_set(unit, &lim_entry, 2921 PORT_TRUNK_MAC_LIMITf, 2922 limit); 2923 rv = WRITE_PORT_OR_TRUNK_MAC_LIMITm(unit, MEM_BLOCK_ALL, 2924 port_tgid, &lim_entry); 2925 } 2926 soc_mem_unlock(unit, PORT_OR_TRUNK_MAC_LIMITm); 2927 2928 BCM_IF_ERROR_RETURN(rv); 2929 2930 soc_mem_lock(unit, PORT_OR_TRUNK_MAC_ACTIONm); 2931 2932 rv = READ_PORT_OR_TRUNK_MAC_ACTIONm(unit, MEM_BLOCK_ANY, port_tgid, &act_entry); 2933 if (BCM_E_NONE == rv) { 2934 soc_mem_field32_set(unit, PORT_OR_TRUNK_MAC_ACTIONm, &act_entry, 2935 OVER_LIMIT_DROPf, 2936 flags & BCM_L2_LEARN_LIMIT_ACTION_DROP ? 1 : 0); 2937 soc_mem_field32_set(unit, PORT_OR_TRUNK_MAC_ACTIONm, &act_entry, 2938 OVER_LIMIT_TOCPUf, 2939 flags & BCM_L2_LEARN_LIMIT_ACTION_CPU ? 1 : 0); 2940 rv = WRITE_PORT_OR_TRUNK_MAC_ACTIONm(unit, MEM_BLOCK_ALL, port_tgid, &act_entry); 2941 } 2942 soc_mem_unlock(unit, PORT_OR_TRUNK_MAC_ACTIONm); 2943 2944 return rv; 2945 } 2946 2947 /* 2948 * Function: 2949 * _bcm_l2_learn_limit_porttrunk_get 2950 * Purpose: 2951 * helper function to configure registers 2952 * Parameters: 2953 * unit - BCM unit number 2954 * port_tgid - Port or trunk number 2955 * flags - Action bitmask 2956 * limit - Per port limit of MAC addresses to learn 2957 * Negative limit disables the check 2958 * Returns: 2959 * BCM_E_XXX 2960 */ 2961 2962 STATIC int 2963 _bcm_l2_learn_limit_porttrunk_get(int unit, int port_tgid, uint32 *flags, 2964 int *limit) 2965 { 2966 int org_action; 2967 port_or_trunk_mac_limit_entry_t lim_entry; 2968 port_or_trunk_mac_action_entry_t act_entry; 2969 2970 if (!soc_feature(unit, soc_feature_mac_learn_limit)) { 2971 return BCM_E_UNAVAIL; 2972 } 2973 2974 *flags = 0; 2975 2976 BCM_IF_ERROR_RETURN 2977 (READ_PORT_OR_TRUNK_MAC_LIMITm(unit, 2978 MEM_BLOCK_ANY, 2979 port_tgid, 2980 &lim_entry)); 2981 *limit = soc_PORT_OR_TRUNK_MAC_LIMITm_field32_get(unit, &lim_entry, 2982 PORT_TRUNK_MAC_LIMITf); 2983 BCM_IF_ERROR_RETURN 2984 (READ_PORT_OR_TRUNK_MAC_ACTIONm(unit, 2985 MEM_BLOCK_ANY, 2986 port_tgid, 2987 &act_entry)); 2988 org_action = soc_PORT_OR_TRUNK_MAC_ACTIONm_field32_get(unit, &act_entry, 2989 OVER_LIMIT_DROPf); 2990 if (org_action) { 2991 *flags |= BCM_L2_LEARN_LIMIT_ACTION_DROP; 2992 } 2993 org_action = soc_PORT_OR_TRUNK_MAC_ACTIONm_field32_get(unit, &act_entry, 2994 OVER_LIMIT_TOCPUf); 2995 if (org_action) { 2996 *flags |= BCM_L2_LEARN_LIMIT_ACTION_CPU; 2997 } 2998 2999 return BCM_E_NONE; 3000 } 3001 3002 /* 3003 * Function: 3004 * _bcm_l2_learn_limit_init 3005 * Purpose: 3006 * Init the system to support MAC learn limit 3007 * Parameters: 3008 * unit - BCM unit number 3009 * Returns: 3010 * BCM_E_XXX 3011 */ 3012 STATIC int 3013 _bcm_l2_learn_limit_init(int unit) 3014 { 3015 3016 bcm_port_t port; 3017 bcm_trunk_t trunk; 3018 bcm_trunk_t trunk_index; 3019 mac_limit_port_map_table_entry_t entry; 3020 int rv = BCM_E_NONE; 3021 uint32 maxInitVal, zeroInitVal; 3022 3023 if (soc_feature(unit, soc_feature_mac_learn_limit)) { 3024 #if defined(BCM_ENDURO_SUPPORT) || defined(BCM_HURRICANE_SUPPORT) 3025 if (SOC_IS_ENDURO(unit) || SOC_IS_HURRICANEX(unit) || 3026 SOC_IS_GREYHOUND(unit) || SOC_IS_GREYHOUND2(unit)) { 3027 /* Reset Limit value is different than soc_mem_entry_null for different SKUs */ 3028 return _bcm_enduro_l2_learn_limit_init(unit); 3029 } 3030 #endif /* BCM_ENDURO_SUPPORT || BCM_HURRICANE_SUPPORT */ 3031 #ifdef BCM_TRIUMPH_SUPPORT 3032 if (SOC_IS_TR_VL(unit)) { 3033 _bcm_tr_l2_learn_limit_system_set(unit, 0, -1); 3034 BCM_IF_ERROR_RETURN 3035 (soc_mem_clear(unit, PORT_OR_TRUNK_MAC_LIMITm, COPYNO_ALL, FALSE)); 3036 BCM_IF_ERROR_RETURN 3037 (soc_mem_clear(unit, VLAN_OR_VFI_MAC_LIMITm, COPYNO_ALL, FALSE)); 3038 return BCM_E_NONE; 3039 } 3040 #endif 3041 maxInitVal = BCM_MAC_LIMIT_MAX; 3042 zeroInitVal = 0; 3043 3044 /* Initialize all learning limits to max and disable feature */ 3045 BCM_IF_ERROR_RETURN(WRITE_MAC_LIMIT_ENABLEr(unit, zeroInitVal)); 3046 BCM_IF_ERROR_RETURN(WRITE_SYS_MAC_LIMITr(unit, maxInitVal)); 3047 /* Map initial port/trunk to counters */ 3048 soc_mem_lock(unit, MAC_LIMIT_PORT_MAP_TABLEm); 3049 soc_mem_lock(unit, MAC_LIMIT_TRUNK_MAP_TABLEm); 3050 soc_mem_lock(unit, PORT_OR_TRUNK_MAC_LIMITm); 3051 soc_mem_lock(unit, PORT_OR_TRUNK_MAC_ACTIONm); 3052 PBMP_ALL_ITER(unit, port) { 3053 /* Initialize the HW tables for port map table*/ 3054 rv = WRITE_PORT_OR_TRUNK_MAC_LIMITm(unit, MEM_BLOCK_ALL, 3055 port, &maxInitVal); 3056 if (BCM_FAILURE(rv)) { 3057 goto done; 3058 } 3059 3060 rv = WRITE_PORT_OR_TRUNK_MAC_ACTIONm(unit, MEM_BLOCK_ALL, 3061 port, &zeroInitVal ); 3062 if (BCM_FAILURE(rv)) { 3063 goto done; 3064 } 3065 3066 rv = READ_MAC_LIMIT_PORT_MAP_TABLEm(unit, MEM_BLOCK_ANY, 3067 port, &entry); 3068 if (BCM_SUCCESS(rv)) { 3069 soc_MAC_LIMIT_PORT_MAP_TABLEm_field32_set(unit, &entry, 3070 INDEXf, port); 3071 rv = WRITE_MAC_LIMIT_PORT_MAP_TABLEm(unit, MEM_BLOCK_ALL, 3072 port, &entry); 3073 } 3074 if (BCM_FAILURE(rv)) { 3075 goto done; 3076 } 3077 } 3078 /* Initialize the HW tables for trunk map table */ 3079 for (trunk = 0; 3080 trunk < soc_mem_index_count(unit, MAC_LIMIT_TRUNK_MAP_TABLEm); 3081 trunk ++ ) { 3082 trunk_index = trunk + PORT_COUNT(unit); 3083 rv = WRITE_PORT_OR_TRUNK_MAC_LIMITm(unit, MEM_BLOCK_ALL, 3084 trunk_index, &maxInitVal); 3085 if (BCM_FAILURE(rv)) { 3086 goto done; 3087 } 3088 rv = READ_MAC_LIMIT_TRUNK_MAP_TABLEm(unit, MEM_BLOCK_ALL, 3089 trunk, &entry); 3090 if (BCM_SUCCESS(rv)) { 3091 soc_MAC_LIMIT_TRUNK_MAP_TABLEm_field32_set(unit, &entry, 3092 INDEXf, trunk); 3093 rv = WRITE_MAC_LIMIT_TRUNK_MAP_TABLEm(unit, MEM_BLOCK_ALL, 3094 trunk, &entry); 3095 } 3096 if (BCM_FAILURE(rv)) { 3097 goto done; 3098 } 3099 } 3100 done: 3101 soc_mem_unlock(unit, MAC_LIMIT_PORT_MAP_TABLEm); 3102 soc_mem_unlock(unit, MAC_LIMIT_TRUNK_MAP_TABLEm); 3103 soc_mem_unlock(unit, PORT_OR_TRUNK_MAC_LIMITm); 3104 soc_mem_unlock(unit, PORT_OR_TRUNK_MAC_ACTIONm); 3105 3106 return rv; 3107 } 3108 3109 return BCM_E_UNAVAIL; 3110 } 3111 3112 3113 /* 3114 * Function: 3115 * _bcm_l2_learn_limit_system_set 3116 * Purpose: 3117 * Set MAC learn limit for a system 3118 * Parameters: 3119 * unit - BCM unit number 3120 * flags - Action bitmask 3121 * limit - System limit of MAC addresses to learn 3122 * Negative limit disables the check 3123 * Returns: 3124 * BCM_E_XXX 3125 */ 3126 STATIC int 3127 _bcm_l2_learn_limit_system_set(int unit, uint32 flags, int limit) 3128 { 3129 uint32 limit_enable, limit_action; 3130 int org_limit = 0; 3131 3132 if (!soc_feature(unit, soc_feature_mac_learn_limit)) { 3133 return BCM_E_UNAVAIL; 3134 } 3135 3136 if (limit > BCM_MAC_LIMIT_MAX){ 3137 return BCM_E_PARAM; 3138 } 3139 3140 /* Negative limit disables the check */ 3141 if (limit < 0) { 3142 BCM_IF_ERROR_RETURN(READ_SYS_MAC_LIMITr(unit, &limit_enable)); 3143 soc_reg_field_set(unit, SYS_MAC_LIMITr, &limit_enable, 3144 SYS_MAC_LIMITf, BCM_MAC_LIMIT_MAX); 3145 BCM_IF_ERROR_RETURN(WRITE_SYS_MAC_LIMITr(unit, limit_enable)); 3146 3147 return BCM_E_NONE; 3148 } 3149 3150 /* If everything is OK - configure the registers */ 3151 /* First configure the Limit and then enable */ 3152 3153 3154 BCM_IF_ERROR_RETURN(READ_SYS_MAC_LIMITr(unit, &limit_enable)); 3155 org_limit = soc_reg_field_get(unit, SYS_MAC_LIMITr, limit_enable, 3156 SYS_MAC_LIMITf); 3157 if (org_limit != limit) { 3158 soc_reg_field_set(unit, SYS_MAC_LIMITr, &limit_enable, 3159 SYS_MAC_LIMITf, limit); 3160 BCM_IF_ERROR_RETURN(WRITE_SYS_MAC_LIMITr(unit, limit_enable)); 3161 } 3162 3163 BCM_IF_ERROR_RETURN(READ_SYS_MAC_ACTIONr(unit, &limit_action)); 3164 /* 3165 * Need to reset the action bit if the flasg is not set. 3166 */ 3167 soc_reg_field_set(unit, 3168 SYS_MAC_ACTIONr, 3169 &limit_action, 3170 OVER_LIMIT_DROPf, 3171 (flags & BCM_L2_LEARN_LIMIT_ACTION_DROP) ? 1 : 0); 3172 soc_reg_field_set(unit, 3173 SYS_MAC_ACTIONr, 3174 &limit_action, 3175 OVER_LIMIT_TOCPUf, 3176 (flags & BCM_L2_LEARN_LIMIT_ACTION_CPU) ? 1 : 0); 3177 soc_reg_field_set(unit, 3178 SYS_MAC_ACTIONr, 3179 &limit_action, 3180 MAC_LIMIT_USE_SYS_ACTIONf, 3181 (flags & BCM_L2_LEARN_LIMIT_ACTION_PREFER) ? 1 : 0); 3182 3183 BCM_IF_ERROR_RETURN(WRITE_SYS_MAC_ACTIONr(unit, limit_action)); 3184 3185 3186 return BCM_E_NONE; 3187 } 3188 3189 /* 3190 * Function: 3191 * _bcm_l2_learn_limit_system_get 3192 * Purpose: 3193 * Get MAC learn limit for a system 3194 * Parameters: 3195 * unit - BCM unit number 3196 * flags - Action bitmask 3197 * limit - System limit of MAC addresses to learn 3198 * Negative if limit disabled 3199 * Returns: 3200 * BCM_E_XXX 3201 */ 3202 STATIC int 3203 _bcm_l2_learn_limit_system_get(int unit, uint32 *flags, int *limit) 3204 { 3205 uint32 limit_enable, limit_action; 3206 int org_limit, org_action; 3207 3208 if (!soc_feature(unit, soc_feature_mac_learn_limit)) { 3209 return BCM_E_UNAVAIL; 3210 } 3211 3212 BCM_IF_ERROR_RETURN(READ_MAC_LIMIT_ENABLEr(unit, &limit_enable)); 3213 org_limit = soc_reg_field_get(unit, MAC_LIMIT_ENABLEr, limit_enable, 3214 ENABLEf); 3215 3216 *flags = 0; 3217 if (!org_limit) { 3218 *limit = -1; 3219 return BCM_E_NONE; 3220 } 3221 3222 BCM_IF_ERROR_RETURN(READ_SYS_MAC_LIMITr(unit, &limit_enable)); 3223 *limit = soc_reg_field_get(unit, SYS_MAC_LIMITr, limit_enable, 3224 SYS_MAC_LIMITf); 3225 3226 /* 3227 * In case of MAC learn limit was disabled but somehow 3228 * enable bit was set 3229 */ 3230 if (*limit > BCM_MAC_LIMIT_MAX) { 3231 *limit = -1 ; 3232 return BCM_E_NONE; 3233 } 3234 3235 BCM_IF_ERROR_RETURN(READ_SYS_MAC_ACTIONr(unit, &limit_action)); 3236 org_action = soc_reg_field_get(unit, SYS_MAC_ACTIONr, limit_action, 3237 OVER_LIMIT_DROPf); 3238 if (org_action) { 3239 *flags |= BCM_L2_LEARN_LIMIT_ACTION_DROP; 3240 } 3241 org_action = soc_reg_field_get(unit, SYS_MAC_ACTIONr, limit_action, 3242 OVER_LIMIT_TOCPUf); 3243 if (org_action) { 3244 *flags |= BCM_L2_LEARN_LIMIT_ACTION_CPU; 3245 } 3246 org_action = soc_reg_field_get(unit, SYS_MAC_ACTIONr, limit_action, 3247 MAC_LIMIT_USE_SYS_ACTIONf); 3248 if (org_action) { 3249 *flags |= BCM_L2_LEARN_LIMIT_ACTION_PREFER; 3250 } 3251 3252 return BCM_E_NONE; 3253 } 3254 /* 3255 * Function: 3256 * _bcm_l2_learn_limit_port_set 3257 * Purpose: 3258 * Set MAC learn limit for a specific port 3259 * Parameters: 3260 * unit - BCM unit number 3261 * port - Port number 3262 * flags - Action bitmask 3263 * limit - Per port limit of MAC addresses to learn 3264 * Negative if limit disabled 3265 * Returns: 3266 * BCM_E_XXX 3267 */ 3268 STATIC int 3269 _bcm_l2_learn_limit_port_set(int unit, bcm_port_t port, uint32 flags, 3270 int limit) 3271 { 3272 int rv = BCM_E_NONE; 3273 mac_limit_port_map_table_entry_t entry; 3274 source_trunk_map_table_entry_t trunk_entry; 3275 bcm_module_t my_modid; 3276 int index; 3277 3278 if (!SOC_UNIT_VALID(unit)) { 3279 return BCM_E_UNIT; 3280 } 3281 if (!SOC_PORT_VALID(unit, port)) { 3282 return BCM_E_PORT; 3283 } 3284 3285 if (0 == soc_feature(unit, soc_feature_mac_learn_limit)) { 3286 return (BCM_E_UNAVAIL); 3287 } 3288 3289 /* Get local module id. */ 3290 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_modid)); 3291 3292 /* Calculate table index. */ 3293 BCM_IF_ERROR_RETURN(_bcm_esw_src_mod_port_table_index_get(unit, 3294 my_modid, port, &index)); 3295 3296 SOC_IF_ERROR_RETURN(READ_SOURCE_TRUNK_MAP_TABLEm(unit, MEM_BLOCK_ANY, 3297 index, &trunk_entry)); 3298 /* Normal port will be encoded as 0 */ 3299 if (soc_SOURCE_TRUNK_MAP_TABLEm_field32_get(unit, &trunk_entry, 3300 PORT_TYPEf)) { 3301 return BCM_E_CONFIG; 3302 } 3303 rv = _bcm_l2_learn_limit_porttrunk_set(unit, port, flags, limit); 3304 if (rv != BCM_E_NONE) { 3305 return rv; 3306 } 3307 soc_mem_lock(unit, MAC_LIMIT_PORT_MAP_TABLEm); 3308 /* Map port to it's counter */ 3309 rv = READ_MAC_LIMIT_PORT_MAP_TABLEm(unit, MEM_BLOCK_ANY, 3310 port, &entry); 3311 if (BCM_E_NONE == rv) { 3312 soc_MAC_LIMIT_PORT_MAP_TABLEm_field32_set(unit, &entry, 3313 INDEXf, port); 3314 rv = WRITE_MAC_LIMIT_PORT_MAP_TABLEm(unit, MEM_BLOCK_ALL, 3315 port, &entry); 3316 } 3317 soc_mem_unlock(unit, MAC_LIMIT_PORT_MAP_TABLEm); 3318 3319 return rv; 3320 } 3321 3322 /* 3323 * Function: 3324 * _bcm_l2_learn_limit_port_get 3325 * Purpose: 3326 * Get MAC learn limit for a specific port 3327 * Parameters: 3328 * unit - BCM unit number 3329 * port - Port number 3330 * flags - Action bitmask 3331 * limit - Per port limit of MAC addresses to learn 3332 * Negative limit disables the check 3333 * Returns: 3334 * BCM_E_XXX 3335 */ 3336 STATIC int 3337 _bcm_l2_learn_limit_port_get(int unit, bcm_port_t port, uint32 *flags, 3338 int *limit) 3339 { 3340 int rv = BCM_E_NONE; 3341 int hw_index; 3342 source_trunk_map_table_entry_t trunk_entry; 3343 bcm_module_t my_modid; 3344 int index; 3345 3346 if (!SOC_UNIT_VALID(unit)) { 3347 return BCM_E_UNIT; 3348 } 3349 if (!SOC_PORT_VALID(unit, port)) { 3350 return BCM_E_PORT; 3351 } 3352 if (0 == soc_feature(unit, soc_feature_mac_learn_limit)) { 3353 return (BCM_E_UNAVAIL); 3354 } 3355 3356 /* Get local module id. */ 3357 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_modid)); 3358 3359 /* Calculate table index. */ 3360 BCM_IF_ERROR_RETURN(_bcm_esw_src_mod_port_table_index_get(unit, 3361 my_modid, port, &index)); 3362 3363 /* If port is part of a trunk - Error */ 3364 SOC_IF_ERROR_RETURN(READ_SOURCE_TRUNK_MAP_TABLEm(unit, MEM_BLOCK_ANY, 3365 index, &trunk_entry)); 3366 /* Normal port will be encoded as 0 */ 3367 if (soc_SOURCE_TRUNK_MAP_TABLEm_field32_get(unit, &trunk_entry, 3368 PORT_TYPEf)) { 3369 return BCM_E_CONFIG; 3370 } 3371 hw_index = port; 3372 rv = _bcm_l2_learn_limit_porttrunk_get(unit, hw_index, flags, limit); 3373 return rv; 3374 } 3375 3376 /* 3377 * Function: 3378 * _bcm_l2_learn_limit_trunk_set 3379 * Purpose: 3380 * Set MAC learn limit for a specific port 3381 * Parameters: 3382 * unit - BCM unit number 3383 * trunk - Trunk identifier 3384 * flags - Action bitmask 3385 * limit - Per port limit of MAC addresses to learn 3386 * Negative limit disables the check 3387 * Returns: 3388 * BCM_E_XXX 3389 */ 3390 STATIC int 3391 _bcm_l2_learn_limit_trunk_set(int unit, bcm_trunk_t trunk, uint32 flags, 3392 int limit) 3393 { 3394 int rv = BCM_E_NONE; 3395 int hw_index = -1; 3396 mac_limit_trunk_map_table_entry_t entry; 3397 soc_mem_t trunk_mem = TRUNK_GROUPm; 3398 3399 if (soc_feature(unit, soc_feature_fastlag)) { 3400 trunk_mem = FAST_TRUNK_GROUPm; 3401 } 3402 3403 if (!SOC_UNIT_VALID(unit)) { 3404 return BCM_E_UNIT; 3405 } 3406 3407 if (trunk >= soc_mem_index_count(unit, trunk_mem) || trunk < 0) { 3408 return BCM_E_PARAM; 3409 } 3410 3411 if (0 == soc_feature(unit, soc_feature_mac_learn_limit)) { 3412 return (BCM_E_UNAVAIL); 3413 } 3414 hw_index = trunk + PORT_COUNT(unit); 3415 rv = _bcm_l2_learn_limit_porttrunk_set(unit, hw_index, flags, limit); 3416 soc_mem_lock(unit, MAC_LIMIT_TRUNK_MAP_TABLEm); 3417 /* Map port to it's counter */ 3418 rv = READ_MAC_LIMIT_TRUNK_MAP_TABLEm(unit, MEM_BLOCK_ANY, 3419 trunk, &entry); 3420 if (BCM_E_NONE == rv) { 3421 soc_MAC_LIMIT_TRUNK_MAP_TABLEm_field32_set(unit, &entry, 3422 INDEXf, hw_index); 3423 rv = WRITE_MAC_LIMIT_TRUNK_MAP_TABLEm(unit, MEM_BLOCK_ALL, 3424 trunk, &entry); 3425 } 3426 soc_mem_unlock(unit, MAC_LIMIT_TRUNK_MAP_TABLEm); 3427 return rv; 3428 } 3429 3430 /* 3431 * Function: 3432 * _bcm_l2_learn_limit_trunk_get 3433 * Purpose: 3434 * Get MAC learn limit for a specific port 3435 * Parameters: 3436 * unit - BCM unit number 3437 * trunk - Trunk identifier 3438 * flags - Action bitmask 3439 * limit - Per port limit of MAC addresses to learn 3440 * Negative if limit disabled 3441 * Returns: 3442 * BCM_E_XXX 3443 */ 3444 STATIC int 3445 _bcm_l2_learn_limit_trunk_get(int unit, bcm_trunk_t tid, uint32 *flags, 3446 int *limit) 3447 { 3448 int rv = BCM_E_NONE; 3449 int hw_index = -1; 3450 soc_mem_t trunk_mem = TRUNK_GROUPm; 3451 3452 if (soc_feature(unit, soc_feature_fastlag)) { 3453 trunk_mem = FAST_TRUNK_GROUPm; 3454 } 3455 3456 if (!SOC_UNIT_VALID(unit)) { 3457 return BCM_E_UNIT; 3458 } 3459 3460 if (tid >= soc_mem_index_count(unit, trunk_mem) || tid < 0) { 3461 return BCM_E_PARAM; 3462 } 3463 3464 if (soc_feature(unit, soc_feature_mac_learn_limit)) { 3465 hw_index = tid + PORT_COUNT(unit); 3466 rv = _bcm_l2_learn_limit_porttrunk_get(unit, hw_index, flags, limit); 3467 return rv; 3468 } 3469 3470 return BCM_E_UNAVAIL; 3471 } 3472 #endif /* BCM_RAPTOR_SUPPORT || BCM_TRIUMPH_SUPPORT */ 3473 /* 3474 * Function: 3475 * bcm_esw_l2_learn_limit_set 3476 * Description: 3477 * Set the L2 MAC learning limit 3478 * Parameters: 3479 * unit device number 3480 * limit learn limit control info 3481 * limit->flags - qualifiers bits and action bits 3482 * limit->vlan - vlan identifier 3483 * limit->port - port number 3484 * limit->trunk - trunk identifier 3485 * limit->limit - max number of learned entry, -1 for unlimit 3486 * Return: 3487 * BCM_E_XXX 3488 */ 3489 int 3490 bcm_esw_l2_learn_limit_set(int unit, bcm_l2_learn_limit_t *limit) 3491 { 3492 #if defined(BCM_TRIUMPH_SUPPORT) || defined(BCM_RAPTOR_SUPPORT) 3493 uint32 type, action, limit_enable, org_limit=0; 3494 #if defined(BCM_KATANA2_SUPPORT) 3495 int id = -1; 3496 bcm_port_t _port = -1; 3497 bcm_trunk_t _trunk = -1; 3498 bcm_module_t _modid = -1; 3499 #endif 3500 3501 #ifdef BCM_TRIUMPH_SUPPORT 3502 soc_mem_t trunk_mem = TRUNK_GROUPm; 3503 3504 if (soc_feature(unit, soc_feature_fastlag)) { 3505 trunk_mem = FAST_TRUNK_GROUPm; 3506 } 3507 #endif 3508 3509 #if defined(BCM_TOMAHAWK3_SUPPORT) 3510 /* Added to handle SDK functions calling esw version, 3511 * instead of Tomahawk3's version 3512 */ 3513 if (SOC_IS_TOMAHAWK3(unit)) { 3514 return bcm_tomahawk3_l2_learn_limit_set(unit, limit); 3515 } 3516 #endif /* BCM_TOMAHAWK3_SUPPORT */ 3517 3518 L2_INIT(unit); 3519 3520 #if defined(BCM_TRIUMPH3_SUPPORT) 3521 if (soc_feature(unit, soc_feature_ism_memory)) { 3522 return bcm_tr3_l2_learn_limit_set(unit, limit); 3523 } 3524 #endif /* BCM_TRIUMPH3_SUPPORT */ 3525 3526 if ((!soc_feature(unit, soc_feature_mac_learn_limit))) { 3527 return BCM_E_UNAVAIL; 3528 } 3529 3530 if (!limit) { 3531 return BCM_E_PARAM; 3532 } 3533 3534 if (limit->limit > BCM_MAC_LIMIT_MAX){ 3535 return BCM_E_PARAM; 3536 } 3537 3538 type = limit->flags & 3539 (BCM_L2_LEARN_LIMIT_SYSTEM | BCM_L2_LEARN_LIMIT_VLAN | 3540 BCM_L2_LEARN_LIMIT_PORT | BCM_L2_LEARN_LIMIT_TRUNK); 3541 3542 action = limit->flags & 3543 (BCM_L2_LEARN_LIMIT_ACTION_DROP | BCM_L2_LEARN_LIMIT_ACTION_CPU | 3544 BCM_L2_LEARN_LIMIT_ACTION_PREFER); 3545 3546 if (!type) { 3547 return BCM_E_PARAM; 3548 } 3549 3550 if (type != BCM_L2_LEARN_LIMIT_SYSTEM && 3551 (action & BCM_L2_LEARN_LIMIT_ACTION_PREFER)) { 3552 return BCM_E_PARAM; 3553 } 3554 3555 3556 if (type & BCM_L2_LEARN_LIMIT_SYSTEM) { 3557 #ifdef BCM_TRIUMPH_SUPPORT 3558 if (SOC_IS_TR_VL(unit)) { 3559 BCM_IF_ERROR_RETURN 3560 (_bcm_tr_l2_learn_limit_system_set(unit, action, 3561 limit->limit)); 3562 } else 3563 #endif 3564 if (soc_feature(unit, soc_feature_system_mac_learn_limit)) { 3565 BCM_IF_ERROR_RETURN 3566 (_bcm_l2_learn_limit_system_set(unit, action, limit->limit)); 3567 } else { 3568 return BCM_E_UNAVAIL; 3569 } 3570 } 3571 3572 if (type & BCM_L2_LEARN_LIMIT_PORT) { 3573 if (BCM_GPORT_IS_SET(limit->port)) { 3574 3575 #if defined(BCM_KATANA2_SUPPORT) 3576 if (_BCM_KT2_GPORT_IS_LINKPHY_OR_SUBTAG_SUBPORT_GPORT(unit, 3577 limit->port)) { 3578 BCM_IF_ERROR_RETURN( 3579 _bcm_esw_gport_resolve(unit, limit->port, &_modid, &_port, 3580 &_trunk, &id)); 3581 BCM_IF_ERROR_RETURN(_bcm_kt2_modport_to_pp_port_get( 3582 unit, _modid, _port, &(limit->port))); 3583 } else 3584 #endif 3585 { 3586 BCM_IF_ERROR_RETURN( 3587 bcm_esw_port_local_get(unit, limit->port, &(limit->port))); 3588 } 3589 } 3590 3591 if (!SOC_PORT_VALID(unit, limit->port)) { 3592 return BCM_E_PORT; 3593 } 3594 3595 /* BCM_L2_LEARN_LIMIT_ACTION_PREFER should be used only in system limit 3596 and only for Raptor/Raven devices */ 3597 if (limit->flags & BCM_L2_LEARN_LIMIT_ACTION_PREFER) { 3598 return BCM_E_PARAM; 3599 } 3600 3601 #ifdef BCM_TRIUMPH_SUPPORT 3602 if (SOC_IS_TR_VL(unit)) { 3603 int index; 3604 3605 index = limit->port + soc_mem_index_count(unit, trunk_mem); 3606 BCM_IF_ERROR_RETURN 3607 (_bcm_tr_l2_learn_limit_set(unit, PORT_OR_TRUNK_MAC_LIMITm, 3608 index, action, limit->limit)); 3609 } else 3610 #endif 3611 { 3612 BCM_IF_ERROR_RETURN 3613 (_bcm_l2_learn_limit_port_set(unit, limit->port, action, 3614 limit->limit)); 3615 } 3616 } 3617 3618 if (type & BCM_L2_LEARN_LIMIT_TRUNK) { 3619 /* BCM_L2_LEARN_LIMIT_ACTION_PREFER should be used only in system limit 3620 and only for Raptor/Raven devices */ 3621 if (limit->flags & BCM_L2_LEARN_LIMIT_ACTION_PREFER) { 3622 return BCM_E_PARAM; 3623 } 3624 3625 #ifdef BCM_TRIUMPH_SUPPORT 3626 if (SOC_IS_TR_VL(unit)) { 3627 int index; 3628 3629 if (limit->trunk < 0 || 3630 limit->trunk >= soc_mem_index_count(unit, trunk_mem)) { 3631 return BCM_E_PARAM; 3632 } 3633 index = limit->trunk; 3634 BCM_IF_ERROR_RETURN 3635 (_bcm_tr_l2_learn_limit_set(unit, PORT_OR_TRUNK_MAC_LIMITm, 3636 index, action, limit->limit)); 3637 } else 3638 #endif 3639 { 3640 BCM_IF_ERROR_RETURN 3641 (_bcm_l2_learn_limit_trunk_set(unit, limit->trunk, action, 3642 limit->limit)); 3643 } 3644 } 3645 3646 #ifdef BCM_TRIUMPH_SUPPORT 3647 if (type & BCM_L2_LEARN_LIMIT_VLAN) { 3648 /* BCM_L2_LEARN_LIMIT_ACTION_PREFER should be used only in system limit 3649 and only for Raptor/Raven devices */ 3650 if (limit->flags & BCM_L2_LEARN_LIMIT_ACTION_PREFER) { 3651 return BCM_E_PARAM; 3652 } 3653 3654 if (SOC_IS_TR_VL(unit)) { 3655 int index, vfi; 3656 3657 if (_BCM_VPN_VFI_IS_SET(limit->vlan)) { 3658 _BCM_VPN_GET(vfi, _BCM_VPN_TYPE_VFI, limit->vlan); 3659 if (vfi >= soc_mem_index_count(unit, VFIm)) { 3660 return BCM_E_PARAM; 3661 } 3662 index = vfi + soc_mem_index_count(unit, VLAN_TABm); 3663 } else { 3664 if (limit->vlan >= soc_mem_index_count(unit, VLAN_TABm)) { 3665 return BCM_E_PARAM; 3666 } 3667 index = limit->vlan; 3668 } 3669 BCM_IF_ERROR_RETURN 3670 (_bcm_tr_l2_learn_limit_set(unit, VLAN_OR_VFI_MAC_LIMITm, 3671 index, action, limit->limit)); 3672 } 3673 } 3674 3675 if (SOC_IS_TR_VL(unit)) { 3676 return BCM_E_NONE; 3677 } 3678 #endif 3679 3680 /* Enable the MAC learn limit feature after configuring the indexes */ 3681 /* Negative limit disables the check */ 3682 if (limit->limit < 0) { 3683 BCM_IF_ERROR_RETURN(READ_MAC_LIMIT_ENABLEr(unit, &limit_enable)); 3684 soc_reg_field_set(unit, MAC_LIMIT_ENABLEr, &limit_enable, 3685 ENABLEf, 0); 3686 BCM_IF_ERROR_RETURN(WRITE_MAC_LIMIT_ENABLEr(unit, limit_enable)); 3687 } else { 3688 BCM_IF_ERROR_RETURN(READ_MAC_LIMIT_ENABLEr(unit, &limit_enable)); 3689 org_limit = soc_reg_field_get(unit, MAC_LIMIT_ENABLEr, limit_enable, 3690 ENABLEf); 3691 if (!org_limit) { 3692 soc_reg_field_set(unit, MAC_LIMIT_ENABLEr, &limit_enable, 3693 ENABLEf, 1); 3694 BCM_IF_ERROR_RETURN(WRITE_MAC_LIMIT_ENABLEr(unit, limit_enable)); 3695 } 3696 } 3697 return BCM_E_NONE; 3698 #else /* BCM_TRIUMPH_SUPPORT || BCM_RAPTOR_SUPPORT */ 3699 return (BCM_E_UNAVAIL); 3700 #endif /* BCM_TRIUMPH_SUPPORT || BCM_RAPTOR_SUPPORT */ 3701 } 3702 3703 /* 3704 * Function: 3705 * bcm_esw_l2_learn_limit_get 3706 * Description: 3707 * Get the L2 MAC learning limit 3708 * Parameters: 3709 * unit device number 3710 * limit learn limit control info 3711 * limit->flags - qualifiers bits and action bits 3712 * limit->vlan - vlan identifier 3713 * limit->port - port number 3714 * limit->trunk - trunk identifier 3715 * limit->limit - max number of learned entry, -1 for unlimit 3716 * Return: 3717 * BCM_E_XXX 3718 */ 3719 int 3720 bcm_esw_l2_learn_limit_get(int unit, bcm_l2_learn_limit_t *limit) 3721 { 3722 #if defined(BCM_TRIUMPH_SUPPORT) || defined(BCM_RAPTOR_SUPPORT) 3723 int rv; 3724 uint32 type, action; 3725 int max; 3726 #if defined(BCM_KATANA2_SUPPORT) || defined(BCM_HGPROXY_COE_SUPPORT) 3727 int id = -1; 3728 bcm_port_t _port = -1; 3729 bcm_trunk_t _trunk = -1; 3730 bcm_module_t _modid = -1; 3731 #endif 3732 3733 #ifdef BCM_TRIUMPH_SUPPORT 3734 soc_mem_t trunk_mem = TRUNK_GROUPm; 3735 3736 if (soc_feature(unit, soc_feature_fastlag)) { 3737 trunk_mem = FAST_TRUNK_GROUPm; 3738 } 3739 #endif 3740 3741 #if defined(BCM_TOMAHAWK3_SUPPORT) 3742 /* Added to handle SDK functions calling esw version, 3743 * instead of Tomahawk3's version 3744 */ 3745 if (SOC_IS_TOMAHAWK3(unit)) { 3746 return bcm_tomahawk3_l2_learn_limit_get(unit, limit); 3747 } 3748 #endif /* BCM_TOMAHAWK3_SUPPORT */ 3749 3750 L2_INIT(unit); 3751 3752 #if defined(BCM_TRIUMPH3_SUPPORT) 3753 if (soc_feature(unit, soc_feature_ism_memory)) { 3754 return bcm_tr3_l2_learn_limit_get(unit, limit); 3755 } 3756 #endif /* BCM_TRIUMPH3_SUPPORT */ 3757 3758 if (!soc_feature(unit, soc_feature_mac_learn_limit)) { 3759 return BCM_E_UNAVAIL; 3760 } 3761 3762 if (!limit) { 3763 return BCM_E_PARAM; 3764 } 3765 3766 type = limit->flags & 3767 (BCM_L2_LEARN_LIMIT_SYSTEM | BCM_L2_LEARN_LIMIT_VLAN | 3768 BCM_L2_LEARN_LIMIT_PORT | BCM_L2_LEARN_LIMIT_TRUNK); 3769 action = 0; 3770 max = 0; 3771 3772 rv = BCM_E_UNAVAIL; 3773 switch (type) { 3774 case BCM_L2_LEARN_LIMIT_SYSTEM: 3775 #ifdef BCM_TRIUMPH_SUPPORT 3776 if (SOC_IS_TR_VL(unit)) { 3777 return _bcm_tr_l2_learn_limit_system_get(unit, &limit->flags, 3778 &limit->limit); 3779 } 3780 #endif 3781 if (soc_feature(unit, soc_feature_system_mac_learn_limit)) { 3782 rv = _bcm_l2_learn_limit_system_get(unit, &action, &max); 3783 } 3784 break; 3785 3786 case BCM_L2_LEARN_LIMIT_PORT: 3787 if (BCM_GPORT_IS_SET(limit->port)) { 3788 3789 #if defined(BCM_HGPROXY_COE_SUPPORT) 3790 if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) && 3791 _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, limit->port)) { 3792 3793 BCM_IF_ERROR_RETURN( 3794 _bcm_esw_gport_resolve(unit, limit->port, &_modid, &_port, 3795 &_trunk, &id)); 3796 3797 BCM_IF_ERROR_RETURN(_bcmi_coe_subport_physical_port_get(unit, 3798 limit->port, &(limit->port))); 3799 } else 3800 #endif 3801 #if defined(BCM_KATANA2_SUPPORT) 3802 if (_BCM_KT2_GPORT_IS_LINKPHY_OR_SUBTAG_SUBPORT_GPORT(unit, 3803 limit->port)) { 3804 BCM_IF_ERROR_RETURN( 3805 _bcm_esw_gport_resolve(unit, limit->port, &_modid, &_port, 3806 &_trunk, &id)); 3807 BCM_IF_ERROR_RETURN(_bcm_kt2_modport_to_pp_port_get( 3808 unit, _modid, _port, &(limit->port))); 3809 } else 3810 #endif 3811 { 3812 BCM_IF_ERROR_RETURN( 3813 bcm_esw_port_local_get(unit, limit->port, &(limit->port))); 3814 } 3815 } 3816 3817 if (!SOC_PORT_VALID(unit, limit->port)) { 3818 return BCM_E_PORT; 3819 } 3820 #ifdef BCM_TRIUMPH_SUPPORT 3821 if (SOC_IS_TR_VL(unit)) { 3822 int index; 3823 index = limit->port + soc_mem_index_count(unit, trunk_mem); 3824 return _bcm_tr_l2_learn_limit_get(unit, PORT_OR_TRUNK_MAC_LIMITm, 3825 index, &limit->flags, 3826 &limit->limit); 3827 } 3828 #endif 3829 rv = _bcm_l2_learn_limit_port_get(unit, limit->port, &action, &max); 3830 break; 3831 3832 case BCM_L2_LEARN_LIMIT_TRUNK: 3833 #ifdef BCM_TRIUMPH_SUPPORT 3834 if (SOC_IS_TR_VL(unit)) { 3835 int index; 3836 3837 if (limit->trunk < 0 || 3838 limit->trunk >= soc_mem_index_count(unit, trunk_mem)) { 3839 return BCM_E_PARAM; 3840 } 3841 index = limit->trunk; 3842 return _bcm_tr_l2_learn_limit_get(unit, PORT_OR_TRUNK_MAC_LIMITm, 3843 index, &limit->flags, 3844 &limit->limit); 3845 } 3846 #endif 3847 rv = _bcm_l2_learn_limit_trunk_get(unit, limit->trunk, &action, &max); 3848 break; 3849 3850 case BCM_L2_LEARN_LIMIT_VLAN: 3851 #ifdef BCM_TRIUMPH_SUPPORT 3852 if (SOC_IS_TR_VL(unit)) { 3853 int index, vfi; 3854 3855 if (_BCM_VPN_VFI_IS_SET(limit->vlan)) { 3856 _BCM_VPN_GET(vfi, _BCM_VPN_TYPE_VFI, limit->vlan); 3857 if (vfi >= soc_mem_index_count(unit, VFIm)) { 3858 return BCM_E_PARAM; 3859 } 3860 index = vfi + soc_mem_index_count(unit, VLAN_TABm); 3861 } else { 3862 if (limit->vlan >= soc_mem_index_count(unit, VLAN_TABm)) { 3863 return BCM_E_PARAM; 3864 } 3865 index = limit->vlan; 3866 } 3867 return _bcm_tr_l2_learn_limit_get(unit, VLAN_OR_VFI_MAC_LIMITm, 3868 index, &limit->flags, 3869 &limit->limit); 3870 } 3871 #endif 3872 break; 3873 3874 default: 3875 return BCM_E_PARAM; 3876 } 3877 3878 if (rv == BCM_E_NONE) { 3879 limit->flags |= action; 3880 limit->limit = max; 3881 } 3882 return rv; 3883 #else /* BCM_TRIUMPH_SUPPORT || BCM_RAPTOR_SUPPORT */ 3884 return (BCM_E_UNAVAIL); 3885 #endif /* BCM_TRIUMPH_SUPPORT || BCM_RAPTOR_SUPPORT */ 3886 } 3887 3888 /* 3889 * Function: 3890 * bcm_esw_l2_learn_class_set 3891 * Description: 3892 * To set the attributes of L2 learning class 3893 * Parameters: 3894 * unit device number 3895 * lclass learning class id (0 - 3) 3896 * lclass_prio learning class priority (0 - 3, 3 is the highest) 3897 * flags flags (BCM_L2_LEARN_CLASS_*) 3898 * Return: 3899 * BCM_E_XXX 3900 * Note: 3901 * This feature is disabled by default (see bcmPortControlLearnClassEnable). 3902 * By default, each learning class is assigned priority 0 (lowest) 3903 * and the attribute, BCM_L2_LEARN_CLASS_MOVE, is not set. By default, 3904 * each port is assigned to learning class 0. 3905 */ 3906 int 3907 bcm_esw_l2_learn_class_set(int unit, int lclass, int lclass_prio, uint32 flags) 3908 { 3909 #if defined(BCM_TRX_SUPPORT) 3910 uint32 data; 3911 3912 #if defined(BCM_TOMAHAWK3_SUPPORT) 3913 /* Added to handle SDK functions calling esw version, 3914 * instead of Tomahawk3's version 3915 */ 3916 if (SOC_IS_TOMAHAWK3(unit)) { 3917 return bcm_tomahawk3_l2_learn_class_set(unit, lclass, lclass_prio, 3918 flags); 3919 } 3920 #endif /* BCM_TOMAHAWK3_SUPPORT */ 3921 3922 L2_INIT(unit); 3923 3924 #if defined(BCM_TRIUMPH3_SUPPORT) 3925 if (soc_feature(unit, soc_feature_ism_memory)) { 3926 return bcm_tr3_l2_learn_class_set(unit, lclass, lclass_prio, flags); 3927 } 3928 #endif /* BCM_TRIUMPH3_SUPPORT */ 3929 3930 if (!soc_feature(unit, soc_feature_class_based_learning)) { 3931 return (BCM_E_UNAVAIL); 3932 } 3933 3934 if (lclass < 0 || lclass >= SOC_REG_NUMELS(unit, CBL_ATTRIBUTEr) || 3935 lclass_prio < 0 || 3936 lclass_prio >= (1 << soc_reg_field_length(unit, CBL_ATTRIBUTEr, 3937 PORT_LEARNING_PRIORITYf))) { 3938 return (BCM_E_PARAM); 3939 } 3940 3941 BCM_IF_ERROR_RETURN(READ_CBL_ATTRIBUTEr(unit, lclass, &data)); 3942 soc_reg_field_set(unit, CBL_ATTRIBUTEr, &data, PORT_LEARNING_PRIORITYf, 3943 lclass_prio); 3944 soc_reg_field_set(unit, CBL_ATTRIBUTEr, &data, ALLOW_MOVE_IN_CLASSf, 3945 flags & BCM_L2_LEARN_CLASS_MOVE ? 1 : 0); 3946 BCM_IF_ERROR_RETURN(WRITE_CBL_ATTRIBUTEr(unit, lclass, data)); 3947 3948 return SOC_E_NONE; 3949 #else /* BCM_TRIUMPH_SUPPORT */ 3950 return (BCM_E_UNAVAIL); 3951 #endif /* BCM_TRIUMPH_SUPPORT */ 3952 } 3953 /* 3954 * Function: 3955 * bcm_esw_l2_learn_class_get 3956 * Description: 3957 * To get the attributes of L2 learning class 3958 * Parameters: 3959 * unit device number 3960 * lclass learning class id (0 - 3) 3961 * lclass_prio learning class priority (0 - 3, 3 is the highest) 3962 * flags flags (BCM_L2_LEARN_CLASS_*) 3963 * Return: 3964 * BCM_E_XXX 3965 */ 3966 int 3967 bcm_esw_l2_learn_class_get(int unit, int lclass, int *lclass_prio, uint32 *flags) 3968 { 3969 #if defined(BCM_TRX_SUPPORT) 3970 uint32 data; 3971 3972 #if defined(BCM_TOMAHAWK3_SUPPORT) 3973 /* Added to handle SDK functions calling esw version, 3974 * instead of Tomahawk3's version 3975 */ 3976 if (SOC_IS_TOMAHAWK3(unit)) { 3977 return bcm_tomahawk3_l2_learn_class_get(unit, lclass, lclass_prio, 3978 flags); 3979 } 3980 #endif /* BCM_TOMAHAWK3_SUPPORT */ 3981 3982 L2_INIT(unit); 3983 3984 #if defined(BCM_TRIUMPH3_SUPPORT) 3985 if (soc_feature(unit, soc_feature_ism_memory)) { 3986 return bcm_tr3_l2_learn_class_get(unit, lclass, lclass_prio, flags); 3987 } 3988 #endif /* BCM_TRIUMPH3_SUPPORT */ 3989 3990 if (!soc_feature(unit, soc_feature_class_based_learning)) { 3991 return (BCM_E_UNAVAIL); 3992 } 3993 3994 if (lclass < 0 || lclass >= SOC_REG_NUMELS(unit, CBL_ATTRIBUTEr) || 3995 lclass_prio == NULL || flags == NULL) { 3996 return (BCM_E_PARAM); 3997 } 3998 3999 BCM_IF_ERROR_RETURN(READ_CBL_ATTRIBUTEr(unit, lclass, &data)); 4000 *lclass_prio = soc_reg_field_get(unit, CBL_ATTRIBUTEr, data, 4001 PORT_LEARNING_PRIORITYf); 4002 *flags = 0; 4003 if (soc_reg_field_get(unit, CBL_ATTRIBUTEr, data, ALLOW_MOVE_IN_CLASSf)) { 4004 *flags |= BCM_L2_LEARN_CLASS_MOVE; 4005 } 4006 4007 return (BCM_E_NONE); 4008 #else /* BCM_TRX_SUPPORT */ 4009 return (BCM_E_UNAVAIL); 4010 #endif /* BCM_TRX_SUPPORT */ 4011 } 4012 4013 /* 4014 * Function: 4015 * bcm_esw_l2_learn_port_class_set 4016 * Description: 4017 * To set the L2 learning class of a port 4018 * Parameters: 4019 * unit device number 4020 * port Ingress generic port 4021 * lclass learning class id (0 - 3) 4022 * Return: 4023 * BCM_E_XXX 4024 * Note: 4025 * This feature is disabled by default (see bcmPortControlLearnClassEnable). 4026 * By default, each port is assigned to learning class 0. 4027 */ 4028 int 4029 bcm_esw_l2_learn_port_class_set(int unit, bcm_gport_t port, int lclass) 4030 { 4031 #if defined(BCM_TRX_SUPPORT) 4032 bcm_module_t module; 4033 bcm_port_t local_port; 4034 bcm_trunk_t trunk; 4035 int id; 4036 4037 #if defined(BCM_TOMAHAWK3_SUPPORT) 4038 /* Added to handle SDK functions calling this function directly. 4039 * Class based learning is not supported on TH3 4040 */ 4041 if (SOC_IS_TOMAHAWK3(unit)) { 4042 return BCM_E_UNAVAIL; 4043 } 4044 #endif /* BCM_TOMAHAWK3_SUPPORT */ 4045 4046 L2_INIT(unit); 4047 4048 #if defined(BCM_TRIUMPH3_SUPPORT) 4049 if (soc_feature(unit, soc_feature_ism_memory)) { 4050 return bcm_tr3_l2_learn_port_class_set(unit, port, lclass); 4051 } 4052 #endif /* BCM_TRIUMPH3_SUPPORT */ 4053 4054 if (!soc_feature(unit, soc_feature_class_based_learning)) { 4055 return BCM_E_UNAVAIL; 4056 } 4057 4058 BCM_L2_LEARN_CLASSID_VALID(lclass); 4059 4060 BCM_IF_ERROR_RETURN(_bcm_esw_gport_resolve(unit, port, &module, 4061 &local_port, &trunk, &id)); 4062 4063 if (soc_feature(unit, soc_feature_linkphy_coe) || 4064 soc_feature(unit, soc_feature_subtag_coe) || 4065 soc_feature(unit, soc_feature_hgproxy_subtag_coe)) { 4066 4067 #if defined(BCM_HGPROXY_COE_SUPPORT) 4068 if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) && 4069 _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port)) { 4070 id = -1; 4071 } 4072 #endif 4073 #if defined(BCM_KATANA2_SUPPORT) 4074 if (_BCM_KT2_GPORT_IS_LINKPHY_OR_SUBTAG_SUBPORT_GPORT(unit, port)) { 4075 id = -1; 4076 } 4077 #endif 4078 } 4079 if (id != -1) { 4080 if (!BCM_GPORT_IS_MPLS_PORT(port) && 4081 !BCM_GPORT_IS_SUBPORT_GROUP(port) && 4082 !BCM_GPORT_IS_SUBPORT_PORT(port) && 4083 !BCM_GPORT_IS_MIM_PORT(port) && 4084 !BCM_GPORT_IS_VLAN_PORT(port) && 4085 !BCM_GPORT_IS_WLAN_PORT(port) && 4086 !BCM_GPORT_IS_TRILL_PORT(port) && 4087 !BCM_GPORT_IS_NIV_PORT(port) && 4088 !BCM_GPORT_IS_L2GRE_PORT(port) && 4089 !BCM_GPORT_IS_VXLAN_PORT(port) && 4090 !BCM_GPORT_IS_EXTENDER_PORT(port)) { 4091 return BCM_E_PARAM; 4092 } 4093 return soc_mem_field32_modify(unit, PORT_CBL_TABLEm, id, 4094 VIRTUAL_PORT_LEARNING_CLASSf, lclass); 4095 } else if (trunk != -1) { 4096 return soc_mem_field32_modify(unit, TRUNK_CBL_TABLEm, trunk, 4097 PORT_LEARNING_CLASSf, lclass); 4098 } else if (!soc_mem_is_valid(unit, PORT_CBL_TABLE_MODBASEm)) { 4099 return soc_mem_field32_modify(unit, PORT_CBL_TABLEm, 4100 module * (SOC_PORT_ADDR_MAX(unit) + 1) + 4101 local_port, 4102 PORT_LEARNING_CLASSf, lclass); 4103 } 4104 #ifdef BCM_TRIDENT_SUPPORT 4105 else { 4106 soc_profile_mem_t *profile; 4107 port_cbl_table_modbase_entry_t base_entry; 4108 port_cbl_table_entry_t cbl_entries[256]; 4109 void *entries[1]; 4110 uint32 old_index, index; 4111 int rv; 4112 4113 profile = _bcm_l2_port_cbl_profile[unit]; 4114 entries[0] = &cbl_entries; 4115 4116 soc_mem_lock(unit, PORT_CBL_TABLE_MODBASEm); 4117 4118 rv = soc_mem_read(unit, PORT_CBL_TABLE_MODBASEm, MEM_BLOCK_ALL, module, 4119 &base_entry); 4120 if (SOC_FAILURE(rv)) { 4121 soc_mem_unlock(unit, PORT_CBL_TABLE_MODBASEm); 4122 return rv; 4123 } 4124 old_index = soc_mem_field32_get(unit, PORT_CBL_TABLE_MODBASEm, 4125 &base_entry, BASEf); 4126 rv = soc_profile_mem_get(unit, profile, old_index, 4127 SOC_PORT_ADDR_MAX(unit) + 1, entries); 4128 if (BCM_FAILURE(rv)) { 4129 soc_mem_unlock(unit, PORT_CBL_TABLE_MODBASEm); 4130 return rv; 4131 } 4132 soc_mem_field32_set(unit, PORT_CBL_TABLEm, &cbl_entries[local_port], 4133 PORT_LEARNING_CLASSf, lclass); 4134 rv = soc_profile_mem_add(unit, profile, entries, 4135 SOC_PORT_ADDR_MAX(unit) + 1, &index); 4136 if (BCM_FAILURE(rv)) { 4137 soc_mem_unlock(unit, PORT_CBL_TABLE_MODBASEm); 4138 return rv; 4139 } 4140 rv = soc_mem_field32_modify(unit, PORT_CBL_TABLE_MODBASEm, module, 4141 BASEf, index); 4142 if (BCM_FAILURE(rv)) { 4143 soc_mem_unlock(unit, PORT_CBL_TABLE_MODBASEm); 4144 return rv; 4145 } 4146 rv = soc_profile_mem_delete(unit, profile, old_index); 4147 4148 soc_mem_unlock(unit, PORT_CBL_TABLE_MODBASEm); 4149 4150 return rv; 4151 } 4152 #endif /* BCM_TRIDENT_SUPPORT */ 4153 return BCM_E_NONE; 4154 #else /* BCM_TRX_SUPPORT */ 4155 return (BCM_E_UNAVAIL); 4156 #endif /* BCM_TRX_SUPPORT */ 4157 } 4158 4159 /* 4160 * Function: 4161 * bcm_esw_l2_learn_port_class_get 4162 * Description: 4163 * To get the L2 learning class of a port 4164 * Parameters: 4165 * unit device number 4166 * port Ingress generic port 4167 * lclass learning class id (0 - 3) 4168 * Return: 4169 * BCM_E_XXX 4170 */ 4171 int 4172 bcm_esw_l2_learn_port_class_get(int unit, bcm_gport_t port, int *lclass) 4173 { 4174 #if defined(BCM_TRX_SUPPORT) 4175 bcm_module_t module; 4176 bcm_port_t local_port; 4177 bcm_trunk_t trunk; 4178 int id; 4179 port_cbl_table_entry_t port_entry; 4180 trunk_cbl_table_entry_t trunk_entry; 4181 4182 #if defined(BCM_TOMAHAWK3_SUPPORT) 4183 /* Added to handle SDK functions calling this function directly. Class based 4184 * learning is not supported on TH3 4185 */ 4186 if (SOC_IS_TOMAHAWK3(unit)) { 4187 return BCM_E_UNAVAIL; 4188 } 4189 #endif /* BCM_TOMAHAWK3_SUPPORT */ 4190 4191 L2_INIT(unit); 4192 4193 #if defined(BCM_TRIUMPH3_SUPPORT) 4194 if (soc_feature(unit, soc_feature_ism_memory)) { 4195 return bcm_tr3_l2_learn_port_class_get(unit, port, lclass); 4196 } 4197 #endif /* BCM_TRIUMPH3_SUPPORT */ 4198 4199 if (!soc_feature(unit, soc_feature_class_based_learning)) { 4200 return BCM_E_UNAVAIL; 4201 } 4202 4203 if (lclass == NULL) { 4204 return BCM_E_PARAM; 4205 } 4206 BCM_IF_ERROR_RETURN(_bcm_esw_gport_resolve(unit, port, &module, 4207 &local_port, &trunk, &id)); 4208 4209 if (soc_feature(unit, soc_feature_linkphy_coe) || 4210 soc_feature(unit, soc_feature_subtag_coe) || 4211 soc_feature(unit, soc_feature_hgproxy_subtag_coe)) { 4212 4213 #if defined(BCM_HGPROXY_COE_SUPPORT) 4214 if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) && 4215 _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port)) { 4216 id = -1; 4217 } 4218 #endif 4219 #if defined(BCM_KATANA2_SUPPORT) 4220 if (_BCM_KT2_GPORT_IS_LINKPHY_OR_SUBTAG_SUBPORT_GPORT(unit, port)) { 4221 id = -1; 4222 } 4223 #endif 4224 } 4225 if (id != -1) { 4226 if (!BCM_GPORT_IS_MPLS_PORT(port) && 4227 !BCM_GPORT_IS_SUBPORT_GROUP(port) && 4228 !BCM_GPORT_IS_SUBPORT_PORT(port) && 4229 !BCM_GPORT_IS_MIM_PORT(port) && 4230 !BCM_GPORT_IS_VLAN_PORT(port) && 4231 !BCM_GPORT_IS_WLAN_PORT(port) && 4232 !BCM_GPORT_IS_TRILL_PORT(port) && 4233 !BCM_GPORT_IS_NIV_PORT(port) && 4234 !BCM_GPORT_IS_L2GRE_PORT(port) && 4235 !BCM_GPORT_IS_VXLAN_PORT(port) && 4236 !BCM_GPORT_IS_EXTENDER_PORT(port)) { 4237 return BCM_E_PARAM; 4238 } 4239 BCM_IF_ERROR_RETURN 4240 (READ_PORT_CBL_TABLEm(unit, MEM_BLOCK_ALL, id, &port_entry)); 4241 *lclass = soc_mem_field32_get(unit, PORT_CBL_TABLEm, &port_entry, 4242 VIRTUAL_PORT_LEARNING_CLASSf); 4243 } else if (trunk != -1) { 4244 BCM_IF_ERROR_RETURN 4245 (READ_TRUNK_CBL_TABLEm(unit, MEM_BLOCK_ALL, trunk, &trunk_entry)); 4246 *lclass = soc_mem_field32_get(unit, TRUNK_CBL_TABLEm, &trunk_entry, 4247 PORT_LEARNING_CLASSf); 4248 } else if (!soc_mem_is_valid(unit, PORT_CBL_TABLE_MODBASEm)) { 4249 BCM_IF_ERROR_RETURN 4250 (READ_PORT_CBL_TABLEm(unit, MEM_BLOCK_ALL, 4251 module * (SOC_PORT_ADDR_MAX(unit) + 1) + 4252 local_port, &port_entry)); 4253 *lclass = soc_mem_field32_get(unit, PORT_CBL_TABLEm, &port_entry, 4254 PORT_LEARNING_CLASSf); 4255 } 4256 #ifdef BCM_TRIDENT_SUPPORT 4257 else { 4258 soc_profile_mem_t *profile; 4259 port_cbl_table_modbase_entry_t base_entry; 4260 port_cbl_table_entry_t cbl_entries[256]; 4261 void *entries[1]; 4262 uint32 index; 4263 4264 profile = _bcm_l2_port_cbl_profile[unit]; 4265 entries[0] = &cbl_entries; 4266 4267 BCM_IF_ERROR_RETURN 4268 (soc_mem_read(unit, PORT_CBL_TABLE_MODBASEm, MEM_BLOCK_ALL, module, 4269 &base_entry)); 4270 index = soc_mem_field32_get(unit, PORT_CBL_TABLE_MODBASEm, &base_entry, 4271 BASEf); 4272 4273 BCM_IF_ERROR_RETURN 4274 (soc_profile_mem_get(unit, profile, index, 4275 SOC_PORT_ADDR_MAX(unit) + 1, entries)); 4276 *lclass = soc_mem_field32_get(unit, PORT_CBL_TABLEm, 4277 &cbl_entries[local_port], 4278 PORT_LEARNING_CLASSf); 4279 } 4280 #endif /* BCM_TRIDENT_SUPPORT */ 4281 4282 return BCM_E_NONE; 4283 #else /* BCM_TRX_SUPPORT */ 4284 return (BCM_E_UNAVAIL); 4285 #endif /* BCM_TRX_SUPPORT */ 4286 } 4287 4288 #ifdef BCM_HURRICANE3_SUPPORT 4289 /* 4290 * Function: 4291 * _bcm_esw_l2_learn_stat_set 4292 * Description: 4293 * To set or clear the specified L2 hash counter to the indicated value. 4294 * Parameters: 4295 * unit - (IN) Unit number. 4296 * learn_stat - (IN) Pointer to the L2 learned statistic structure. 4297 * Return: 4298 * BCM_E_XXX 4299 */ 4300 STATIC int 4301 _bcm_esw_l2_learn_stat_set(int unit, bcm_l2_learn_stat_t *learn_stat) 4302 { 4303 uint32 val=0; 4304 soc_field_t learn_field; 4305 soc_reg_t learn_reg; 4306 4307 if (learn_stat == NULL) { 4308 return (BCM_E_PARAM); 4309 } 4310 4311 switch(learn_stat->type) { 4312 case bcmL2LearnStatL2TableLearned: 4313 if (SOC_REG_IS_VALID(unit, L2_ENTRY_LEARNED_CNTr)) { 4314 learn_reg = L2_ENTRY_LEARNED_CNTr; 4315 learn_field = COUNTERf; 4316 } else { 4317 return (BCM_E_UNAVAIL); 4318 } 4319 break; 4320 case bcmL2LearnStatOverflowPoolLearned: 4321 if (SOC_REG_IS_VALID(unit, L2_128_OVF_LEARNED_CNTr)) { 4322 learn_reg = L2_128_OVF_LEARNED_CNTr; 4323 learn_field = COUNTERf; 4324 } else { 4325 return (BCM_E_UNAVAIL); 4326 } 4327 break; 4328 case bcmL2LearnStatHashCollisions: 4329 if (SOC_REG_IS_VALID(unit, L2_ENTRY_COLLISION_CNTr)) { 4330 learn_reg = L2_ENTRY_COLLISION_CNTr; 4331 learn_field = COUNTERf; 4332 } else { 4333 return (BCM_E_UNAVAIL); 4334 } 4335 break; 4336 default: 4337 return (BCM_E_PARAM); 4338 } 4339 4340 BCM_IF_ERROR_RETURN(soc_reg32_get 4341 (unit, learn_reg, REG_PORT_ANY, 0, &val)); 4342 soc_reg_field_set(unit, learn_reg, &val, learn_field, learn_stat->value); 4343 BCM_IF_ERROR_RETURN(soc_reg32_set 4344 (unit, learn_reg, REG_PORT_ANY, 0, val)); 4345 4346 return (BCM_E_NONE); 4347 } 4348 4349 /* 4350 * Function: 4351 * _bcm_esw_l2_learn_stat_get 4352 * Description: 4353 * To get the statistic of the specified L2 hash counter from chip. 4354 * Parameters: 4355 * unit - (IN) Unit number. 4356 * learn_stat - (INOUT) Pointer to the L2 learned statistic structure. 4357 * Return: 4358 * BCM_E_XXX 4359 */ 4360 STATIC int 4361 _bcm_esw_l2_learn_stat_get(int unit, bcm_l2_learn_stat_t *learn_stat) 4362 { 4363 uint32 val=0; 4364 soc_field_t learn_field; 4365 soc_reg_t learn_reg; 4366 4367 if (learn_stat == NULL) { 4368 return (BCM_E_PARAM); 4369 } 4370 4371 switch(learn_stat->type) { 4372 case bcmL2LearnStatL2TableLearned: 4373 if (SOC_REG_IS_VALID(unit, L2_ENTRY_LEARNED_CNTr)) { 4374 learn_reg = L2_ENTRY_LEARNED_CNTr; 4375 learn_field = COUNTERf; 4376 } else { 4377 return (BCM_E_UNAVAIL); 4378 } 4379 break; 4380 case bcmL2LearnStatOverflowPoolLearned: 4381 if (SOC_REG_IS_VALID(unit, L2_128_OVF_LEARNED_CNTr)) { 4382 learn_reg = L2_128_OVF_LEARNED_CNTr; 4383 learn_field = COUNTERf; 4384 } else { 4385 return (BCM_E_UNAVAIL); 4386 } 4387 break; 4388 case bcmL2LearnStatHashCollisions: 4389 if (SOC_REG_IS_VALID(unit, L2_ENTRY_COLLISION_CNTr)) { 4390 learn_reg = L2_ENTRY_COLLISION_CNTr; 4391 learn_field = COUNTERf; 4392 } else { 4393 return (BCM_E_UNAVAIL); 4394 } 4395 break; 4396 default: 4397 return (BCM_E_PARAM); 4398 } 4399 4400 BCM_IF_ERROR_RETURN(soc_reg32_get 4401 (unit, learn_reg, REG_PORT_ANY, 0, &val)); 4402 learn_stat->value = soc_reg_field_get(unit, learn_reg, val, learn_field); 4403 4404 return (BCM_E_NONE); 4405 } 4406 #endif /* BCM_HURRICANE3_SUPPORT */ 4407 4408 /* 4409 * Function: 4410 * bcm_esw_l2_learn_stat_set 4411 * Description: 4412 * To set or clear the specified L2 hash counter to the indicated value. 4413 * Parameters: 4414 * unit - (IN) Unit number. 4415 * learn_stat - (IN) Pointer to the L2 learned statistic structure. 4416 * Return: 4417 * BCM_E_XXX 4418 * Note: 4419 * The purposes of these counters are used to monitor the L2 hash condition. 4420 * When the counter counts to 32'hffff_ffff (maximum value), it will keep this value till 4421 * software clear it. Currently these L2 hash counters are system-wise. 4422 */ 4423 int 4424 bcm_esw_l2_learn_stat_set(int unit, bcm_l2_learn_stat_t *learn_stat) 4425 { 4426 #ifdef BCM_HURRICANE3_SUPPORT 4427 if (soc_feature(unit, soc_feature_l2_learn_stats)) { 4428 return _bcm_esw_l2_learn_stat_set(unit, learn_stat); 4429 } 4430 #endif /* BCM_HURRICANE3_SUPPORT */ 4431 4432 return (BCM_E_UNAVAIL); 4433 } 4434 4435 /* 4436 * Function: 4437 * bcm_esw_l2_learn_stat_get 4438 * Description: 4439 * To get the statistic of the specified L2 hash counter from chip. 4440 * Parameters: 4441 * unit - (IN) Unit number. 4442 * learn_stat - (INOUT) Pointer to the L2 learned statistic structure. 4443 * Return: 4444 * BCM_E_XXX 4445 * Note: 4446 * The purposes of these counters are used to monitor the L2 hash condition. 4447 * When the counter counts to 32'hffff_ffff (maximum value), it will keep this value till 4448 * software clear it. Currently these L2 hash counters are system-wise. 4449 */ 4450 int 4451 bcm_esw_l2_learn_stat_get(int unit, bcm_l2_learn_stat_t *learn_stat) 4452 { 4453 #ifdef BCM_HURRICANE3_SUPPORT 4454 if (soc_feature(unit, soc_feature_l2_learn_stats)) { 4455 return _bcm_esw_l2_learn_stat_get(unit, learn_stat); 4456 } 4457 #endif /* BCM_HURRICANE3_SUPPORT */ 4458 4459 return (BCM_E_UNAVAIL); 4460 } 4461 4462 /* 4463 * Function: 4464 * _bcm_esw_l2_entry_valid 4465 * Description: 4466 * Check if given L2 entry is Valid 4467 * Parameters: 4468 * unit device number 4469 * mem L2 memory to operate on 4470 * l2_entry L2X entry read from HW 4471 * Return: 4472 * BCM_E_NONE 4473 * BCM_E_NOT_FOUND 4474 */ 4475 STATIC int 4476 _bcm_esw_l2_entry_valid(int unit, soc_memacc_t *l2x_memacc, uint32 *l2_entry) 4477 { 4478 #if defined(BCM_FIREBOLT_SUPPORT) 4479 if (SOC_IS_FBX(unit)){ 4480 int valid; 4481 if (soc_feature(unit, soc_feature_base_valid)) { 4482 valid = soc_mem_field32_get(unit, L2Xm, l2_entry, BASE_VALIDf); 4483 } else { 4484 valid = soc_memacc_field32_get(&l2x_memacc[_BCM_L2_MEMACC_VALID], 4485 l2_entry); 4486 } 4487 if (!valid) { 4488 return BCM_E_NOT_FOUND; 4489 } 4490 } 4491 #endif 4492 #if defined(BCM_TRIUMPH_SUPPORT) 4493 if (SOC_IS_TR_VL(unit)) { 4494 int key_type; 4495 key_type = soc_memacc_field32_get(&l2x_memacc[_BCM_L2_MEMACC_KEY_TYPE], 4496 l2_entry); 4497 #if defined(BCM_TRIDENT2_SUPPORT) 4498 if (SOC_IS_TD2_TT2(unit)) { 4499 if (key_type != TD2_L2_HASH_KEY_TYPE_BRIDGE && 4500 key_type != TD2_L2_HASH_KEY_TYPE_VFI) { 4501 return BCM_E_NOT_FOUND; 4502 } 4503 } else 4504 #endif 4505 #if defined(BCM_GREYHOUND2_SUPPORT) 4506 if (soc_feature(unit, soc_feature_vxlan_lite_riot)) { 4507 if ((key_type != GH2_L2_HASH_KEY_TYPE_BRIDGE) && 4508 (key_type != GH2_L2_HASH_KEY_TYPE_VFI) && 4509 (key_type != GH2_L2_HASH_KEY_TYPE_VFI_MULTICAST)) { 4510 return BCM_E_NOT_FOUND; 4511 } 4512 } else 4513 #endif /* BCM_GREYHOUND2_SUPPORT */ 4514 4515 /* Suppress coverity warning, because enum values used here 4516 * for key_type are defined differently based on device type 4517 */ 4518 4519 /* coverity[mixed_enums] */ 4520 if (key_type != TR_L2_HASH_KEY_TYPE_BRIDGE && 4521 key_type != TR_L2_HASH_KEY_TYPE_VFI) { 4522 return BCM_E_NOT_FOUND; 4523 } 4524 } 4525 #endif 4526 4527 return BCM_E_NONE; 4528 } 4529 4530 /* 4531 * Function: 4532 * _bcm_esw_l2_from_l2x 4533 * Description: 4534 * Parser function to parse L2X entry into L2_Addr structure 4535 * will call per chip parser 4536 * Parameters: 4537 * unit device number 4538 * mem L2 memory to operate on 4539 * l2addr L2 address structure to fill 4540 * l2_entry L2X entry read from HW 4541 * Return: 4542 * BCM_E_XXX 4543 */ 4544 int 4545 _bcm_esw_l2_from_l2x(int unit, soc_mem_t mem, bcm_l2_addr_t *l2addr, uint32 *l2_entry) 4546 { 4547 #if defined(BCM_TRX_SUPPORT) 4548 if (SOC_IS_TRX(unit)) { 4549 if (EXT_L2_ENTRYm == mem) { 4550 return _bcm_tr_l2_from_ext_l2(unit, l2addr, 4551 (ext_l2_entry_entry_t *)l2_entry); 4552 } else { 4553 return _bcm_tr_l2_from_l2x(unit, l2addr, 4554 (l2x_entry_t *)l2_entry); 4555 } 4556 } else 4557 #endif 4558 #if defined(BCM_FIREBOLT_SUPPORT) || defined(BCM_BRADLEY_SUPPORT) 4559 if (SOC_IS_FBX(unit)) { 4560 return _bcm_fb_l2_from_l2x(unit, l2addr, 4561 (l2x_entry_t *)l2_entry); 4562 } else 4563 #endif 4564 4565 return BCM_E_UNAVAIL; 4566 } 4567 4568 /* 4569 * Function: 4570 * _bcm_esw_l2_traverse_mem 4571 * Description: 4572 * Helper function to _bcm_esw_l2_traverse to itterate over given memory 4573 * and actually read the table and parse entries. 4574 * Parameters: 4575 * unit device number 4576 * mem L2 memory to read 4577 * trav_st Traverse structure with all the data. 4578 * Return: 4579 * BCM_E_XXX 4580 */ 4581 int 4582 _bcm_esw_l2_traverse_mem(int unit, soc_mem_t mem, _bcm_l2_traverse_t *trav_st) 4583 { 4584 /* Indexes to iterate over memories, chunks and entries */ 4585 int chnk_idx, ent_idx, chnk_idx_max, mem_idx_max; 4586 int buf_size, chunksize, chnk_end; 4587 /* Buffer to store chunk of L2 table we currently work on */ 4588 uint32 *l2_tbl_chnk; 4589 uint32 *l2_entry; 4590 int rv = BCM_E_NONE; 4591 int i; 4592 soc_memacc_t l2x_memacc_list[_BCM_L2_MEMACC_NUM]; 4593 soc_field_t l2x_fields[_BCM_L2_MEMACC_NUM] = { 4594 VALIDf, 4595 KEY_TYPEf 4596 }; 4597 _bcm_l2_replace_t *rep_st; 4598 4599 if (!soc_mem_index_count(unit, mem)) { 4600 return BCM_E_NONE; 4601 } 4602 4603 for (i = 0; i < _BCM_L2_MEMACC_NUM; i++) { 4604 rv = soc_memacc_init(unit, mem, l2x_fields[i], &l2x_memacc_list[i]); 4605 if (BCM_FAILURE(rv)) { 4606 SOC_MEMACC_INVALID_SET(&l2x_memacc_list[i]); 4607 } 4608 } 4609 4610 chunksize = soc_property_get(unit, spn_L2DELETE_CHUNKS, 4611 L2_MEM_CHUNKS_DEFAULT); 4612 4613 buf_size = 4 * SOC_MAX_MEM_FIELD_WORDS * chunksize; 4614 l2_tbl_chnk = soc_cm_salloc(unit, buf_size, "l2 traverse"); 4615 if (NULL == l2_tbl_chnk) { 4616 return BCM_E_MEMORY; 4617 } 4618 4619 mem_idx_max = soc_mem_index_max(unit, mem); 4620 for (chnk_idx = soc_mem_index_min(unit, mem); 4621 chnk_idx <= mem_idx_max; 4622 chnk_idx += chunksize) { 4623 sal_memset((void *)l2_tbl_chnk, 0, buf_size); 4624 4625 chnk_idx_max = 4626 ((chnk_idx + chunksize) < mem_idx_max) ? 4627 (chnk_idx + chunksize - 1) : mem_idx_max; 4628 4629 rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY, 4630 chnk_idx, chnk_idx_max, l2_tbl_chnk); 4631 if (SOC_FAILURE(rv)) { 4632 break; 4633 } 4634 #if defined(BCM_TRIDENT2_SUPPORT) 4635 if (SOC_IS_TRIDENT2(unit) || SOC_IS_TITAN2(unit) 4636 || SOC_IS_TD2P_TT2P(unit)) { 4637 rv = _bcm_td2_l2_hit_range_retrieve(unit, mem, chnk_idx, 4638 chnk_idx_max, l2_tbl_chnk); 4639 if (SOC_FAILURE(rv)) { 4640 break; 4641 } 4642 } 4643 #endif /* BCM_TRIDENT2_SUPPORT */ 4644 chnk_end = (chnk_idx_max - chnk_idx); 4645 for (ent_idx = 0 ; ent_idx <= chnk_end; ent_idx ++) { 4646 l2_entry = 4647 soc_mem_table_idx_to_pointer(unit, mem, uint32 *, 4648 l2_tbl_chnk, ent_idx); 4649 if (BCM_FAILURE(_bcm_esw_l2_entry_valid(unit, l2x_memacc_list, 4650 l2_entry))) { 4651 continue; 4652 } 4653 trav_st->data = l2_entry; 4654 trav_st->mem = mem; 4655 trav_st->mem_idx = chnk_idx + ent_idx; 4656 rv = trav_st->int_cb(unit, (void *)trav_st); 4657 if (BCM_FAILURE(rv)) { 4658 break; 4659 } 4660 } 4661 if (BCM_FAILURE(rv)) { 4662 break; 4663 } 4664 4665 if (!trav_st->user_cb) { 4666 /* Enhancement: use memory write range (per chunk) for replacing l2 entry data */ 4667 rep_st = ((_bcm_l2_traverse_t *)trav_st)->user_data; 4668 if (mem == L2Xm && !(rep_st->flags & BCM_L2_REPLACE_DELETE)) { 4669 rv = soc_mem_write_range(unit, mem, MEM_BLOCK_ANY, 4670 chnk_idx, chnk_idx_max, l2_tbl_chnk); 4671 if (SOC_FAILURE(rv)) { 4672 break; 4673 } 4674 } 4675 } 4676 } 4677 soc_cm_sfree(unit, l2_tbl_chnk); 4678 return rv; 4679 } 4680 4681 /* 4682 * Function: 4683 * _bcm_esw_l2_traverse 4684 * Description: 4685 * Helper function to bcm_esw_l2_traverse to itterate over table 4686 * and actually read the momery 4687 * Parameters: 4688 * unit device number 4689 * trav_st Traverse structure with all the data. 4690 * Return: 4691 * BCM_E_XXX 4692 */ 4693 int 4694 _bcm_esw_l2_traverse(int unit, _bcm_l2_traverse_t *trav_st) 4695 { 4696 int rv = BCM_E_UNAVAIL; 4697 4698 #if defined(BCM_FIREBOLT_SUPPORT) || defined(BCM_BRADLEY_SUPPORT) 4699 if (SOC_IS_FBX(unit)) { 4700 rv = _bcm_esw_l2_traverse_mem(unit, L2Xm, trav_st); 4701 #if defined(BCM_TRIUMPH_SUPPORT) 4702 if (soc_feature(unit, soc_feature_esm_support) && BCM_SUCCESS(rv)) { 4703 rv = _bcm_tr_l2_traverse_mem(unit, EXT_L2_ENTRYm, trav_st); 4704 } 4705 #endif /* BCM_TRIUMPH_SUPPORT */ 4706 #if defined(BCM_HURRICANE3_SUPPORT) 4707 if (soc_feature(unit, soc_feature_l2_overflow_bucket) && BCM_SUCCESS(rv)) { 4708 rv = _bcm_esw_l2_traverse_mem(unit, L2_ENTRY_OVERFLOWm, trav_st); 4709 } 4710 #endif /* BCM_HURRICANE3_SUPPORT */ 4711 4712 } 4713 #endif /* BCM_FBX_SUPPORT */ 4714 return rv; 4715 } 4716 4717 /* 4718 * Function: 4719 * _bcm_esw_l2_traverse_int_cb 4720 * Description: 4721 * Simple internal callback function for bcm_l2_traverse API just to call 4722 * a user provided callback on a given entry. 4723 * Parameters: 4724 * unit device number 4725 * trav_st traverse structure 4726 * Return: 4727 * BCM_E_XXX 4728 */ 4729 int 4730 _bcm_esw_l2_traverse_int_cb(int unit, void *trav_st) 4731 { 4732 _bcm_l2_traverse_t *trv; 4733 bcm_l2_addr_t l2_addr; 4734 4735 trv = (_bcm_l2_traverse_t *)trav_st; 4736 4737 BCM_IF_ERROR_RETURN( 4738 _bcm_esw_l2_from_l2x(unit, trv->mem, &l2_addr, trv->data)); 4739 4740 return trv->user_cb(unit, &l2_addr, trv->user_data); 4741 } 4742 4743 /* 4744 * Function: 4745 * bcm_esw_l2_traverse 4746 * Description: 4747 * To traverse the L2 table and call provided callback function with matched entry 4748 * Parameters: 4749 * unit device number 4750 * trav_fn User specified callback function 4751 * user_data User specified cookie 4752 * Return: 4753 * BCM_E_XXX 4754 */ 4755 int 4756 bcm_esw_l2_traverse(int unit, bcm_l2_traverse_cb trav_fn, void *user_data) 4757 { 4758 _bcm_l2_traverse_t trav_st; 4759 4760 #if defined(BCM_TOMAHAWK3_SUPPORT) 4761 /* Added to handle SDK functions calling esw version, 4762 * instead of Tomahawk3's version 4763 */ 4764 if (SOC_IS_TOMAHAWK3(unit)) { 4765 return bcm_tomahawk3_l2_traverse(unit, trav_fn, user_data); 4766 } 4767 #endif /* BCM_TOMAHAWK3_SUPPORT */ 4768 4769 L2_INIT(unit); 4770 4771 if (!trav_fn) { 4772 return (BCM_E_PARAM); 4773 } 4774 4775 sal_memset(&trav_st, 0, sizeof(_bcm_l2_traverse_t)); 4776 4777 trav_st.user_cb = trav_fn; 4778 trav_st.user_data = user_data; 4779 trav_st.int_cb = _bcm_esw_l2_traverse_int_cb; 4780 4781 #if defined(BCM_TRIUMPH3_SUPPORT) 4782 if (soc_feature(unit, soc_feature_ism_memory)) { 4783 return bcm_tr3_l2_traverse(unit, &trav_st); 4784 } 4785 #endif /* BCM_TRIUMPH3_SUPPORT */ 4786 4787 return (_bcm_esw_l2_traverse(unit, &trav_st)); 4788 } 4789 4790 int 4791 _bcm_esw_l2_match_sw(int unit, bcm_l2_addr_t *info, void *user_data) 4792 { 4793 int flag_match, vid_match, mac_match, dest_match; 4794 _bcm_l2_match_t *l2match = user_data; 4795 4796 flag_match = ((info->flags & l2match->addr_mask->flags) == 4797 (l2match->match_addr->flags & l2match->addr_mask->flags)); 4798 4799 vid_match = ((info->vid & l2match->addr_mask->vid) == 4800 (l2match->match_addr->vid & l2match->addr_mask->vid)); 4801 4802 { 4803 uint8 *s = l2match->match_addr->mac, *d = info->mac; 4804 uint8 *m = l2match->addr_mask->mac; 4805 4806 mac_match = (((( s[0] & m[0] ) ^ (d[0] & m[0])) | 4807 (( s[1] & m[1] ) ^ (d[1] & m[1])) | 4808 (( s[2] & m[2] ) ^ (d[2] & m[2])) | 4809 (( s[3] & m[3] ) ^ (d[3] & m[3])) | 4810 (( s[4] & m[4] ) ^ (d[4] & m[4])) | 4811 (( s[5] & m[5] ) ^ (d[5] & m[5]))) == 0); 4812 } 4813 4814 { 4815 if (BCM_MAC_IS_MCAST(info->mac)) { 4816 dest_match = ((info->l2mc_group & l2match->addr_mask->l2mc_group) == 4817 (l2match->match_addr->l2mc_group & l2match->addr_mask->l2mc_group)); 4818 } else if (info->flags & BCM_L2_TRUNK_MEMBER) { 4819 dest_match = ((info->tgid & l2match->addr_mask->tgid) == 4820 (l2match->match_addr->tgid & l2match->addr_mask->tgid)); 4821 } else if (BCM_GPORT_IS_SET(info->port)) { 4822 dest_match = ((info->port & l2match->addr_mask->port) == 4823 (l2match->match_addr->port & l2match->addr_mask->port)); 4824 } else { 4825 dest_match = ((info->port & l2match->addr_mask->port) == 4826 (l2match->match_addr->port & l2match->addr_mask->port)); 4827 dest_match &= ((info->modid & l2match->addr_mask->modid) == 4828 (l2match->match_addr->modid & l2match->addr_mask->modid)); 4829 } 4830 } 4831 4832 if (flag_match && vid_match && mac_match && dest_match) { 4833 l2match->trav_fn(unit, info, l2match->user_data); 4834 } 4835 4836 return 0; 4837 } 4838 4839 int 4840 _bcm_esw_l2_matched_traverse(int unit, uint32 flags, bcm_l2_addr_t *match_addr, 4841 bcm_l2_traverse_cb trav_fn, void *user_data) 4842 { 4843 bcm_l2_addr_t addr_mask; 4844 bcm_mac_t mac_mask = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; 4845 _bcm_l2_match_t l2match; 4846 4847 if (!trav_fn) { 4848 return (BCM_E_PARAM); 4849 } 4850 4851 if (!match_addr) { 4852 return (BCM_E_PARAM); 4853 } 4854 4855 bcm_l2_addr_t_init(&addr_mask, mac_mask, 0xFFF); 4856 4857 if (flags & BCM_L2_TRAVERSE_MATCH_STATIC) { 4858 addr_mask.flags |= BCM_L2_STATIC; 4859 } else { 4860 addr_mask.flags &= ~BCM_L2_STATIC; 4861 } 4862 4863 if (flags & BCM_L2_TRAVERSE_MATCH_MAC) { 4864 sal_memset(addr_mask.mac, 0xFF, sizeof(addr_mask.mac)); 4865 } else { 4866 sal_memset(addr_mask.mac, 0x0, sizeof(addr_mask.mac)); 4867 } 4868 4869 if (flags & BCM_L2_TRAVERSE_MATCH_VLAN) { 4870 addr_mask.vid = ~0; 4871 } else { 4872 addr_mask.vid = 0; 4873 } 4874 4875 if (flags & BCM_L2_TRAVERSE_MATCH_DEST) { 4876 addr_mask.port = ~0; 4877 addr_mask.modid = ~0; 4878 addr_mask.l2mc_group = ~0; 4879 addr_mask.tgid = ~0; 4880 } else { 4881 addr_mask.port = 0x0; 4882 addr_mask.modid = 0x0; 4883 addr_mask.l2mc_group = 0x0; 4884 addr_mask.tgid = 0x0; 4885 } 4886 4887 if (flags & BCM_L2_TRAVERSE_IGNORE_DISCARD_SRC) { 4888 addr_mask.flags &= ~BCM_L2_DISCARD_SRC; 4889 } else { 4890 addr_mask.flags |= BCM_L2_DISCARD_SRC; 4891 } 4892 4893 if (flags & BCM_L2_TRAVERSE_IGNORE_DES_HIT) { 4894 addr_mask.flags &= ~BCM_L2_DES_HIT; 4895 } else { 4896 addr_mask.flags |= BCM_L2_DES_HIT; 4897 } 4898 4899 l2match.match_addr = match_addr; 4900 l2match.addr_mask = &addr_mask; 4901 l2match.trav_fn =trav_fn; 4902 l2match.user_data = user_data; 4903 4904 return bcm_esw_l2_traverse(unit, _bcm_esw_l2_match_sw, &l2match); 4905 } 4906 4907 #ifdef BCM_XGS_SWITCH_SUPPORT 4908 /* 4909 * Function: 4910 * _bcm_get_op_from_flags 4911 * Description: 4912 * Helper function to _bcm_fb_age_reg_config to 4913 * decide on a PPA command according to flags 4914 * Parameters: 4915 * flags flags BCM_L2_REPLACE_* 4916 * op PPA command to be programmed 4917 * sync_op Search Key for _soc_l2x_sync_delete_by 4918 * Return: 4919 * BCM_E_NONE - Success 4920 * BCM_E_PARAM - Failure 4921 */ 4922 int 4923 _bcm_get_op_from_flags(uint32 flags, uint32 *op, uint32 *sync_op) 4924 { 4925 uint32 cmp_flags = 0, int_op = 0, int_sync_op = 0; 4926 int rv = BCM_E_NONE; 4927 4928 if (NULL == op) { 4929 return BCM_E_PARAM; 4930 } 4931 cmp_flags = flags & (BCM_L2_REPLACE_MATCH_VLAN | 4932 BCM_L2_REPLACE_MATCH_DEST); 4933 switch (cmp_flags) { 4934 case BCM_L2_REPLACE_MATCH_VLAN: 4935 { 4936 int_op = (flags & BCM_L2_REPLACE_DELETE ? XGS_PPAMODE_VLAN : 4937 XGS_PPAMODE_VLAN_REPLACE); 4938 int_sync_op = (flags & BCM_L2_REPLACE_DELETE ? SOC_L2X_VLAN_DEL : 4939 SOC_L2X_NO_DEL); 4940 break; 4941 } 4942 case BCM_L2_REPLACE_MATCH_DEST : 4943 { 4944 int_op = (flags & BCM_L2_REPLACE_DELETE ? XGS_PPAMODE_PORTMOD : 4945 XGS_PPAMODE_PORTMOD_REPLACE); 4946 int_sync_op = (flags & BCM_L2_REPLACE_DELETE ? SOC_L2X_PORTMOD_DEL : 4947 SOC_L2X_NO_DEL); 4948 break; 4949 } 4950 case BCM_L2_REPLACE_MATCH_VLAN | BCM_L2_REPLACE_MATCH_DEST: 4951 { 4952 int_op = (flags & BCM_L2_REPLACE_DELETE ? XGS_PPAMODE_PORTMOD_VLAN : 4953 XGS_PPAMODE_PORTMOD_VLAN_REPLACE); 4954 int_sync_op = (flags & BCM_L2_REPLACE_DELETE ? SOC_L2X_PORTMOD_VLAN_DEL : 4955 SOC_L2X_NO_DEL); 4956 4957 break; 4958 } 4959 default: 4960 rv = BCM_E_PARAM; 4961 break; 4962 } 4963 4964 *op = int_op; 4965 *sync_op = int_sync_op; 4966 return rv; 4967 } 4968 4969 #endif /* BCM_XGS_SWITCH_SUPPORT */ 4970 4971 4972 /* 4973 * Function: 4974 * _bcm_l2_replace_limit_count_update 4975 * Description: 4976 * Helper function to bcm_l2_replace API to update mac learn limit counters 4977 * Parameters: 4978 * unit device number 4979 * mem memory for wich to update counters 4980 * rep_st structure with information of replaced and new params 4981 * entry The entry that is being updated. 4982 * Return: 4983 * BCM_E_NONE - OK 4984 * BCM_E_XXX - Error 4985 */ 4986 STATIC int 4987 _bcm_l2_replace_limit_count_update(int unit, soc_mem_t mem, 4988 _bcm_l2_replace_t *rep_st, 4989 uint32 *entry) 4990 { 4991 int index; 4992 uint32 rval, cnt_val, port_val, mac_cnt_entry; 4993 soc_mem_t trunk_mem = TRUNK_GROUPm; 4994 4995 if (soc_feature(unit, soc_feature_fastlag)) { 4996 trunk_mem = FAST_TRUNK_GROUPm; 4997 } 4998 4999 /* If MAC learn limit not supported do nothing */ 5000 if ((!soc_feature(unit, soc_feature_mac_learn_limit))) { 5001 return BCM_E_NONE; 5002 } 5003 5004 /* If MAC learn limit not enabled do nothing */ 5005 if (SOC_REG_IS_VALID(unit, MAC_LIMIT_ENABLEr)) { 5006 BCM_IF_ERROR_RETURN(READ_MAC_LIMIT_ENABLEr(unit, &rval)); 5007 if (!soc_reg_field_get(unit, MAC_LIMIT_ENABLEr, rval, ENABLEf)) { 5008 return BCM_E_NONE; 5009 } 5010 } else if (SOC_REG_IS_VALID(unit, SYS_MAC_LIMIT_CONTROLr)) { 5011 BCM_IF_ERROR_RETURN(READ_SYS_MAC_LIMIT_CONTROLr(unit, &rval)); 5012 if (!soc_reg_field_get(unit, SYS_MAC_LIMIT_CONTROLr, rval, ENABLEf)) { 5013 return BCM_E_NONE; 5014 } 5015 } 5016 5017 /* If entry marked as EXEMPT do nothing */ 5018 if (soc_mem_field_valid(unit, mem, LIMIT_COUNTEDf)) { 5019 if (!soc_mem_field32_get(unit,mem, entry, LIMIT_COUNTEDf)) { 5020 return BCM_E_NONE; 5021 } 5022 } 5023 5024 if (soc_mem_field_valid(unit, mem, TGID_PORTf)) { /* Draco Style */ 5025 port_val = soc_mem_field32_get(unit, mem, entry, TGID_PORTf); 5026 } else { /* Triumph style */ 5027 port_val = soc_mem_field32_get(unit, mem, entry, PORT_NUMf); 5028 } 5029 if (soc_feature(unit, soc_feature_trunk_group_overlay)) { 5030 if (soc_mem_field32_get(unit, mem, entry, Tf)) { 5031 /* If trunk member - do nothing */ 5032 index = port_val; 5033 } else { 5034 index = port_val + soc_mem_index_count(unit, trunk_mem); 5035 } 5036 } else { 5037 if (port_val & BCM_TGID_TRUNK_INDICATOR(unit)) { 5038 /* If trunk member - do nothing */ 5039 index = port_val; 5040 } else { 5041 index = port_val + soc_mem_index_count(unit, trunk_mem); 5042 } 5043 } 5044 5045 /* If match_dest contains trunk info it is there where we should do the decrement */ 5046 if ((rep_st->flags & BCM_L2_REPLACE_MATCH_DEST)) { 5047 if (rep_st->match_dest.trunk != -1) { 5048 index = rep_st->match_dest.trunk; 5049 } else { 5050 index = rep_st->match_dest.port + 5051 soc_mem_index_count(unit, trunk_mem); 5052 } 5053 } 5054 5055 BCM_IF_ERROR_RETURN( 5056 READ_PORT_OR_TRUNK_MAC_COUNTm(unit, MEM_BLOCK_ANY, index, 5057 &mac_cnt_entry)); 5058 cnt_val = soc_mem_field32_get(unit, PORT_OR_TRUNK_MAC_COUNTm, 5059 &mac_cnt_entry, COUNTf); 5060 if ( 0 != cnt_val) { 5061 cnt_val--; 5062 } 5063 soc_mem_field32_set(unit, PORT_OR_TRUNK_MAC_COUNTm, &mac_cnt_entry, 5064 COUNTf, cnt_val); 5065 BCM_IF_ERROR_RETURN( 5066 WRITE_PORT_OR_TRUNK_MAC_COUNTm(unit, MEM_BLOCK_ALL, index, 5067 &mac_cnt_entry)); 5068 5069 /* For replace cases a new index should be incremented. */ 5070 if (!(rep_st->flags & BCM_L2_REPLACE_DELETE)) { 5071 if (rep_st->new_dest.trunk != -1) { 5072 index = rep_st->new_dest.trunk; 5073 } else { 5074 index = rep_st->new_dest.port + 5075 soc_mem_index_count(unit, trunk_mem); 5076 } 5077 BCM_IF_ERROR_RETURN( 5078 READ_PORT_OR_TRUNK_MAC_COUNTm(unit, MEM_BLOCK_ANY, index, 5079 &mac_cnt_entry)); 5080 cnt_val = soc_mem_field32_get(unit, PORT_OR_TRUNK_MAC_COUNTm, 5081 &mac_cnt_entry, COUNTf); 5082 if ((++cnt_val) > 0x3FFF) { 5083 cnt_val = 0x3FFF; 5084 } 5085 soc_mem_field32_set(unit, PORT_OR_TRUNK_MAC_COUNTm, &mac_cnt_entry, 5086 COUNTf, cnt_val); 5087 BCM_IF_ERROR_RETURN( 5088 WRITE_PORT_OR_TRUNK_MAC_COUNTm(unit, MEM_BLOCK_ALL, index, 5089 &mac_cnt_entry)); 5090 } 5091 5092 return BCM_E_NONE; 5093 } 5094 5095 5096 /* 5097 * Function: 5098 * _bcm_l2_entry_replace 5099 * Description: 5100 * Helper function to bcm_l2_replace API to be used as a call back for 5101 * bcm_l2_traverse API and replace given entry if MAC matches 5102 * Parameters: 5103 * unit device number 5104 * trav_st structure with information from traverse function 5105 * Return: 5106 * BCM_E_XXX 5107 */ 5108 STATIC int 5109 _bcm_l2_entry_replace(int unit, void *trav_st) 5110 { 5111 _bcm_l2_replace_t *rep_st; 5112 soc_mem_t mem; 5113 uint32 *entry; 5114 uint32 *match_data, *match_mask, *new_data, *new_mask; 5115 int entry_words, i, idx, rv; 5116 bcm_mac_t l2mac; 5117 int mod_val, port_val, trunk_val, vp_val; 5118 soc_control_t *soc = SOC_CONTROL(unit); 5119 int fifo_modified; 5120 bcm_l2_addr_t l2_addr; 5121 5122 if (trav_st == NULL) { 5123 return BCM_E_PARAM; 5124 } 5125 5126 mem = ((_bcm_l2_traverse_t *)trav_st)->mem; 5127 entry = ((_bcm_l2_traverse_t *)trav_st)->data; 5128 idx = ((_bcm_l2_traverse_t *)trav_st)->mem_idx; 5129 rep_st = ((_bcm_l2_traverse_t *)trav_st)->user_data; 5130 5131 if (rep_st == NULL || entry == NULL || mem == INVALIDm) { 5132 return BCM_E_PARAM; 5133 } 5134 5135 if (mem == L2Xm) { 5136 match_data = (uint32 *)&rep_st->match_data; 5137 match_mask = (uint32 *)&rep_st->match_mask; 5138 new_data = (uint32 *)&rep_st->new_data; 5139 new_mask = (uint32 *)&rep_st->new_mask; 5140 entry_words = soc_mem_entry_words(unit, mem); 5141 #if defined(BCM_TRIDENT2_SUPPORT) 5142 /* Retrieve the hit bit for TD2/TT2 */ 5143 if (rep_st->int_flags & _BCM_L2_REPLACE_INT_NO_ACTION) { 5144 if (!SOC_IS_TOMAHAWKX(unit) && !SOC_IS_APACHE(unit) && 5145 !SOC_IS_TRIDENT3X(unit) && 5146 SOC_IS_TD2_TT2(unit)) { 5147 BCM_IF_ERROR_RETURN( 5148 _bcm_td2_l2_hit_retrieve(unit, (l2x_entry_t *)entry, idx)); 5149 } 5150 } 5151 #endif /* BCM_TRIDENT2_SUPPORT */ 5152 for (i = 0; i < entry_words; i++) { 5153 if ((entry[i] ^ match_data[i]) & match_mask[i]) { 5154 return BCM_E_NONE; 5155 } 5156 } 5157 if (rep_st->int_flags & _BCM_L2_REPLACE_INT_NO_ACTION) { 5158 BCM_IF_ERROR_RETURN 5159 (_bcm_esw_l2_from_l2x(unit, mem, &l2_addr, entry)); 5160 return rep_st->trav_fn(unit, &l2_addr, rep_st->user_data); 5161 } 5162 if (rep_st->flags & BCM_L2_REPLACE_DELETE) { 5163 if (SOC_CONTROL(unit)->l2x_mode == L2MODE_FIFO) { 5164 fifo_modified = FALSE; 5165 if ((rep_st->flags & BCM_L2_REPLACE_NO_CALLBACKS) && 5166 soc_reg_field_valid(unit, AUX_ARB_CONTROLr, 5167 L2_MOD_FIFO_ENABLE_L2_DELETEf) && 5168 soc_l2mod_running(unit, NULL, NULL)) { 5169 BCM_IF_ERROR_RETURN 5170 (soc_reg_field32_modify(unit, AUX_ARB_CONTROLr, 5171 REG_PORT_ANY, 5172 L2_MOD_FIFO_ENABLE_L2_DELETEf, 5173 0)); 5174 fifo_modified = TRUE; 5175 } 5176 rv = soc_mem_delete(unit, mem, MEM_BLOCK_ALL, entry); 5177 if (fifo_modified) { 5178 BCM_IF_ERROR_RETURN 5179 (soc_reg_field32_modify(unit, AUX_ARB_CONTROLr, 5180 REG_PORT_ANY, 5181 L2_MOD_FIFO_ENABLE_L2_DELETEf, 5182 1)); 5183 } 5184 } else { 5185 MEM_LOCK(unit, mem); 5186 if (SOC_L2_DEL_SYNC_LOCK(soc) < 0) { 5187 MEM_UNLOCK(unit, mem); 5188 return BCM_E_RESOURCE; 5189 } 5190 rv = soc_mem_delete(unit, mem, MEM_BLOCK_ALL, entry); 5191 #ifdef BCM_XGS_SWITCH_SUPPORT 5192 if (BCM_SUCCESS(rv)) { 5193 rv = soc_l2x_sync_delete 5194 (unit, entry, idx, 5195 rep_st->flags & BCM_L2_REPLACE_NO_CALLBACKS ? 5196 SOC_L2X_NO_CALLBACKS : 0); 5197 } 5198 #endif /* BCM_XGS_SWITCH_SUPPORT */ 5199 SOC_L2_DEL_SYNC_UNLOCK(soc); 5200 MEM_UNLOCK(unit, mem); 5201 } 5202 return rv; 5203 } else { 5204 for (i = 0; i < entry_words; i++) { 5205 entry[i] &= ~new_mask[i]; 5206 entry[i] |= new_data[i]; 5207 } 5208 BCM_IF_ERROR_RETURN 5209 (_bcm_l2_replace_limit_count_update(unit, mem, rep_st, entry)); 5210 5211 /* Enhancement: use memory write range (per chunk) for replacing l2 entry data */ 5212 return BCM_E_NONE; 5213 } 5214 } 5215 5216 if (rep_st->flags & BCM_L2_REPLACE_MATCH_VLAN) { 5217 if (rep_st->key_vfi != -1) { 5218 #ifdef BCM_TRIUMPH_SUPPORT 5219 if (EXT_L2_ENTRYm == mem) { 5220 if (soc_mem_field32_get(unit, mem, entry, KEY_TYPE_VFIf) != 5221 1) { 5222 return BCM_E_NONE; 5223 } 5224 } 5225 #endif /* BCM_TRIUMPH_SUPPORT */ 5226 if (soc_mem_field32_get(unit, mem, entry, VFIf) != 5227 rep_st->key_vfi) { 5228 return BCM_E_NONE; 5229 } 5230 } else { 5231 #ifdef BCM_TRIUMPH_SUPPORT 5232 if (EXT_L2_ENTRYm == mem) { 5233 if (soc_mem_field32_get(unit, mem, entry, KEY_TYPE_VFIf) != 5234 0) { 5235 return BCM_E_NONE; 5236 } 5237 } 5238 #endif /* BCM_TRIUMPH_SUPPORT */ 5239 if (soc_mem_field32_get(unit, mem, entry, VLAN_IDf) != 5240 rep_st->key_vlan) { 5241 return BCM_E_NONE; 5242 } 5243 } 5244 } 5245 5246 if (rep_st->flags & BCM_L2_REPLACE_MATCH_MAC) { 5247 soc_mem_mac_addr_get(unit, mem, entry, MAC_ADDRf, l2mac); 5248 if (ENET_CMP_MACADDR(rep_st->key_mac, l2mac)) { 5249 return BCM_E_NONE; 5250 } 5251 } 5252 5253 if (rep_st->flags & BCM_L2_REPLACE_MATCH_DEST) { 5254 vp_val = -1; 5255 trunk_val = -1; 5256 mod_val = -1; 5257 port_val = -1; 5258 if (soc_mem_field_valid(unit, mem, DEST_TYPEf) && 5259 soc_mem_field32_get(unit, mem, entry, DEST_TYPEf) == 2) { 5260 vp_val = soc_mem_field32_get(unit, mem, entry, DESTINATIONf); 5261 } else if (soc_feature(unit, soc_feature_trunk_group_overlay)) { 5262 if (soc_mem_field32_get(unit, mem, entry, Tf)) { 5263 trunk_val = soc_mem_field32_get(unit, mem, entry, TGIDf); 5264 } else { 5265 mod_val = soc_mem_field32_get(unit, mem, entry, MODULE_IDf); 5266 port_val = soc_mem_field32_get(unit, mem, entry, PORT_NUMf); 5267 } 5268 } else { 5269 mod_val = soc_mem_field32_get(unit, mem, entry, MODULE_IDf); 5270 port_val = soc_mem_field32_get(unit, mem, entry, TGID_PORTf); 5271 if (port_val & BCM_TGID_TRUNK_INDICATOR(unit)) { 5272 trunk_val = BCM_MODIDf_TGIDf_TO_TRUNK(unit, mod_val, port_val); 5273 } 5274 } 5275 5276 if (rep_st->match_dest.vp != -1) { 5277 if (rep_st->match_dest.vp != vp_val) { 5278 return BCM_E_NONE; 5279 } 5280 } else if (rep_st->match_dest.trunk != -1) { 5281 if (rep_st->match_dest.trunk != trunk_val) { 5282 return BCM_E_NONE; 5283 } 5284 } else { 5285 if (rep_st->match_dest.module != mod_val) { 5286 return BCM_E_NONE; 5287 } 5288 if (rep_st->match_dest.port != port_val) { 5289 return BCM_E_NONE; 5290 } 5291 } 5292 } 5293 5294 if (!(rep_st->flags & BCM_L2_REPLACE_MATCH_STATIC)) { 5295 /* BCM_L2_REPLACE_MATCH_STATIC means to replace static as well as 5296 * non-static entries */ 5297 if (soc_mem_field32_get(unit, mem, entry, STATIC_BITf)) { 5298 return BCM_E_NONE; 5299 } 5300 } 5301 5302 /* BCM_L2_REPLACE_PENDING means to only replace pending entries, 5303 * !BCM_L2_REPLACE_PENDING means to only replace non-pending entries. */ 5304 if (soc_mem_field_valid(unit, mem, PENDINGf)) { 5305 if (soc_mem_field32_get(unit, mem, entry, PENDINGf)) { 5306 if (!(rep_st->flags & BCM_L2_REPLACE_PENDING)) { 5307 return (BCM_E_NONE); 5308 } 5309 } else { 5310 if (rep_st->flags & BCM_L2_REPLACE_PENDING) { 5311 return (BCM_E_NONE); 5312 } 5313 } 5314 } 5315 5316 if (rep_st->flags & BCM_L2_REPLACE_DELETE) { 5317 if (mem != EXT_L2_ENTRYm) { 5318 MEM_LOCK(unit, mem); 5319 if (SOC_L2_DEL_SYNC_LOCK(soc) < 0) { 5320 MEM_UNLOCK(unit, mem); 5321 return BCM_E_RESOURCE; 5322 } 5323 rv = soc_mem_delete(unit, mem, MEM_BLOCK_ALL, entry); 5324 if (BCM_FAILURE(rv)) { 5325 SOC_L2_DEL_SYNC_UNLOCK(soc); 5326 MEM_UNLOCK(unit, mem); 5327 return rv; 5328 } 5329 #ifdef BCM_XGS_SWITCH_SUPPORT 5330 { 5331 uint32 soc_flags = 0; 5332 soc_flags = (rep_st->flags & BCM_L2_REPLACE_NO_CALLBACKS) ? 5333 SOC_L2X_NO_CALLBACKS : 0; 5334 rv = soc_l2x_sync_delete(unit, entry, idx, soc_flags); 5335 } 5336 #endif /* BCM_XGS_SWITCH_SUPPORT */ 5337 SOC_L2_DEL_SYNC_UNLOCK(soc); 5338 MEM_UNLOCK(unit, mem); 5339 return rv; 5340 } 5341 } else { 5342 if (rep_st->new_dest.vp != -1) { /* New destination is virtual port */ 5343 soc_mem_field32_set(unit, mem, entry, DEST_TYPEf, 0x2); 5344 soc_mem_field32_set(unit, mem, entry, DESTINATIONf, 5345 rep_st->new_dest.vp); 5346 } else if (soc_feature(unit, soc_feature_trunk_group_overlay)) { 5347 if (rep_st->new_dest.trunk != -1) { /* New destination is trunk */ 5348 soc_mem_field32_set(unit, mem, entry, DEST_TYPEf, 1); 5349 soc_mem_field32_set(unit, mem, entry, TGIDf, 5350 rep_st->new_dest.trunk); 5351 } else { /* New destination is mod port */ 5352 soc_mem_field32_set(unit, mem, entry, DEST_TYPEf, 0); 5353 soc_mem_field32_set(unit, mem, entry, MODULE_IDf, 5354 rep_st->new_dest.module); 5355 soc_mem_field32_set(unit, mem, entry, PORT_NUMf, 5356 rep_st->new_dest.port); 5357 } 5358 } else { 5359 if (rep_st->new_dest.trunk != -1) { /* New destination is trunk */ 5360 mod_val = BCM_TRUNK_TO_MODIDf(unit, rep_st->new_dest.trunk); 5361 port_val = BCM_TRUNK_TO_TGIDf(unit, rep_st->new_dest.trunk); 5362 soc_mem_field32_set(unit, mem, entry, MODULE_IDf, mod_val); 5363 soc_mem_field32_set(unit, mem, entry, TGID_PORTf, port_val); 5364 } else { /* New destination is mod port */ 5365 soc_mem_field32_set(unit, mem, entry, MODULE_IDf, 5366 rep_st->new_dest.module); 5367 soc_mem_field32_set(unit, mem, entry, TGID_PORTf, 5368 rep_st->new_dest.port); 5369 } 5370 } 5371 BCM_IF_ERROR_RETURN( 5372 _bcm_l2_replace_limit_count_update(unit, mem, rep_st, entry)); 5373 } 5374 #ifdef BCM_TRIUMPH_SUPPORT 5375 if (EXT_L2_ENTRYm == mem) { 5376 if (rep_st->flags & BCM_L2_REPLACE_DELETE) { 5377 BCM_IF_ERROR_RETURN( 5378 soc_mem_generic_delete(unit, mem, MEM_BLOCK_ANY, 0, 5379 entry, entry, NULL)); 5380 /* learn limit counters should not be updated for static entries */ 5381 /* unless specifically instructed by API */ 5382 if ((rep_st->flags & BCM_L2_REPLACE_MATCH_STATIC) 5383 && !(rep_st->flags & BCM_L2_REPLACE_LEARN_LIMIT) ) { 5384 rv = BCM_E_NONE; 5385 } else { 5386 rv = soc_triumph_learn_count_update(unit, (void *)entry, 5387 TRUE, -1); 5388 } 5389 } else { 5390 rv = soc_mem_generic_insert(unit, mem, MEM_BLOCK_ALL, 0, 5391 entry, entry, 0); 5392 if (rv == BCM_E_EXISTS) { 5393 rv = BCM_E_NONE; 5394 } 5395 } 5396 return rv; 5397 } 5398 #endif /* BCM_TRIUMPH_SUPPORT */ 5399 5400 return soc_mem_write(unit, mem, MEM_BLOCK_ALL, idx, entry); 5401 } 5402 5403 /* 5404 * Function: 5405 * _bcm_l2_replace_by_hw 5406 * Description: 5407 * Helper function to bcm_l2_replace API to replace l2 entries by hardware 5408 * Parameters: 5409 * unit device number 5410 * flags flags BCM_L2_REPLACE_* 5411 * rep_st structure with information of what to replace 5412 * Return: 5413 * BCM_E_XXX 5414 */ 5415 STATIC int 5416 _bcm_l2_replace_by_hw(int unit, uint32 flags, _bcm_l2_replace_t *rep_st) 5417 { 5418 #ifdef BCM_TRX_SUPPORT 5419 if (SOC_IS_TRX(unit)) { 5420 return _bcm_tr_l2_replace_by_hw(unit, rep_st); 5421 } 5422 #endif /* BCM_TRX_SUPPORT */ 5423 #ifdef BCM_FIREBOLT_SUPPORT 5424 if (SOC_IS_FBX(unit)) { 5425 return _bcm_fb_l2_addr_replace_by_vlan_dest(unit, flags, rep_st); 5426 } 5427 #endif /* BCM_FIREBOLT_SUPPORT */ 5428 5429 return BCM_E_UNAVAIL; 5430 } 5431 5432 /* 5433 * Function: 5434 * _bcm_l2_replace_dest_setup 5435 * Description: 5436 * Helper function to bcm_l2_replace API to setup a destination 5437 */ 5438 STATIC int 5439 _bcm_l2_replace_dest_setup(int unit, bcm_module_t module, bcm_port_t port, 5440 bcm_trunk_t trunk, int is_trunk, 5441 _bcm_l2_replace_dest_t *dest) 5442 { 5443 int tid_is_vp_lag; 5444 int vp; 5445 #if defined(BCM_TRIDENT2_SUPPORT) && defined(INCLUDE_L3) 5446 int vp_lag_vp; 5447 #endif /* BCM_TRIDENT2_SUPPORT && INCLUDE_L3 */ 5448 5449 /* If all are -1, means ignore the replacement with new destination */ 5450 if (module == -1 && port == -1 && trunk == -1) { 5451 dest->module = dest->port = dest->trunk = dest->vp = -1; 5452 return BCM_E_NONE; 5453 } 5454 5455 if (BCM_GPORT_IS_SET(port)) { 5456 if (BCM_GPORT_IS_MPLS_PORT(port) || 5457 BCM_GPORT_IS_SUBPORT_GROUP(port) || 5458 BCM_GPORT_IS_SUBPORT_PORT(port) || 5459 BCM_GPORT_IS_MIM_PORT(port) || 5460 BCM_GPORT_IS_VLAN_PORT(port) || 5461 BCM_GPORT_IS_WLAN_PORT(port) || 5462 BCM_GPORT_IS_TRILL_PORT(port) || 5463 BCM_GPORT_IS_NIV_PORT(port) || 5464 BCM_GPORT_IS_VXLAN_PORT(port) || 5465 BCM_GPORT_IS_L2GRE_PORT(port) || 5466 BCM_GPORT_IS_EXTENDER_PORT(port)) { 5467 5468 #ifdef BCM_KATANA2_SUPPORT 5469 if (BCM_GPORT_IS_SUBPORT_PORT(port) && 5470 _BCM_KT2_GPORT_IS_LINKPHY_OR_SUBTAG_SUBPORT_GPORT(unit, port)) { 5471 } else 5472 #endif 5473 { 5474 /* all these gport has similar encoding format */ 5475 vp = port & 0xffffff; 5476 5477 if (!SOC_MEM_IS_VALID(unit, SOURCE_VPm) || 5478 vp > soc_mem_index_max(unit, SOURCE_VPm)) { 5479 return BCM_E_PORT; 5480 } 5481 dest->vp = vp; 5482 } 5483 } else { 5484 BCM_IF_ERROR_RETURN 5485 (_bcm_esw_gport_resolve(unit, port, &dest->module, &dest->port, 5486 &dest->trunk, &dest->vp)); 5487 } 5488 5489 #if defined(BCM_HGPROXY_COE_SUPPORT) 5490 if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) && 5491 _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port)) { 5492 BCM_IF_ERROR_RETURN 5493 (_bcm_esw_gport_resolve(unit, port, &dest->module, &dest->port, 5494 &dest->trunk, &dest->vp)); 5495 dest->vp = -1; 5496 } 5497 #endif 5498 5499 #if defined(BCM_KATANA2_SUPPORT) 5500 if (_BCM_KT2_GPORT_IS_LINKPHY_OR_SUBTAG_SUBPORT_GPORT(unit, port)) { 5501 BCM_IF_ERROR_RETURN 5502 (_bcm_esw_gport_resolve(unit, port, &dest->module, &dest->port, 5503 &dest->trunk, &dest->vp)); 5504 dest->vp = -1; 5505 } 5506 #endif 5507 } else if (is_trunk) { 5508 BCM_IF_ERROR_RETURN(_bcm_trunk_id_validate(unit, trunk)); 5509 BCM_IF_ERROR_RETURN( 5510 _bcm_esw_trunk_id_is_vp_lag(unit, trunk, &tid_is_vp_lag)); 5511 if (tid_is_vp_lag) { 5512 #if defined(BCM_TRIDENT2_SUPPORT) && defined(INCLUDE_L3) 5513 if (soc_feature(unit, soc_feature_vp_lag)) { 5514 /* Get the VP value representing VP LAG */ 5515 BCM_IF_ERROR_RETURN( 5516 _bcm_esw_trunk_tid_to_vp_lag_vp(unit, trunk, &vp_lag_vp)); 5517 dest->vp = vp_lag_vp; 5518 dest->trunk = -1; 5519 } else 5520 #endif /* BCM_TRIDENT2_SUPPORT && INCLUDE_L3 */ 5521 { 5522 return BCM_E_PORT; 5523 } 5524 } else { 5525 dest->trunk = trunk; 5526 dest->vp = -1; 5527 } 5528 } else { 5529 BCM_IF_ERROR_RETURN 5530 (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_SET, module, port, 5531 &dest->module, &dest->port)); 5532 if (!SOC_MODID_ADDRESSABLE(unit, dest->module)) { 5533 return BCM_E_BADID; 5534 } 5535 if (!SOC_PORT_ADDRESSABLE(unit, dest->port)) { 5536 return BCM_E_PORT; 5537 } 5538 dest->trunk = -1; 5539 dest->vp = -1; 5540 } 5541 5542 return BCM_E_NONE; 5543 } 5544 5545 STATIC int 5546 _bcm_l2_replace_data_mask_setup(int unit, _bcm_l2_replace_t *rep) 5547 { 5548 bcm_mac_t mac_mask; 5549 bcm_mac_t mac_data; 5550 int field_len; 5551 uint32 module, port; 5552 5553 sal_memset(&rep->match_mask, 0, sizeof(l2x_entry_t)); 5554 sal_memset(&rep->match_data, 0, sizeof(l2x_entry_t)); 5555 sal_memset(&rep->new_mask, 0, sizeof(l2x_entry_t)); 5556 sal_memset(&rep->new_data, 0, sizeof(l2x_entry_t)); 5557 5558 if (soc_feature(unit, soc_feature_base_valid)) { 5559 soc_mem_field32_set(unit, L2Xm, &rep->match_mask, BASE_VALIDf, 1); 5560 soc_mem_field32_set(unit, L2Xm, &rep->match_data, BASE_VALIDf, 1); 5561 } else if (soc_mem_field_valid(unit, L2Xm, VALIDf)) { 5562 soc_mem_field32_set(unit, L2Xm, &rep->match_mask, VALIDf, 1); 5563 soc_mem_field32_set(unit, L2Xm, &rep->match_data, VALIDf, 1); 5564 } 5565 5566 if (SOC_IS_TR_VL(unit) && (rep->key_type != -1)) { 5567 field_len = soc_mem_field_length(unit, L2Xm, KEY_TYPEf); 5568 soc_mem_field32_set(unit, L2Xm, &rep->match_mask, KEY_TYPEf, 5569 (1 << field_len) - 1); 5570 soc_mem_field32_set(unit, L2Xm, &rep->match_data, KEY_TYPEf, 5571 rep->key_type); 5572 } 5573 5574 if (rep->flags & BCM_L2_REPLACE_MATCH_VLAN) { 5575 if (rep->key_vfi != -1) { 5576 field_len = soc_mem_field_length(unit, L2Xm, VFIf); 5577 soc_mem_field32_set(unit, L2Xm, &rep->match_mask, VFIf, 5578 (1 << field_len) - 1); 5579 soc_mem_field32_set(unit, L2Xm, &rep->match_data, VFIf, 5580 rep->key_vfi); 5581 } else { 5582 soc_mem_field32_set(unit, L2Xm, &rep->match_mask, VLAN_IDf, 0xfff); 5583 soc_mem_field32_set(unit, L2Xm, &rep->match_data, VLAN_IDf, 5584 rep->key_vlan); 5585 } 5586 } 5587 5588 if (rep->flags & BCM_L2_REPLACE_MATCH_MAC) { 5589 sal_memset(&mac_mask, 0xff, sizeof(mac_mask)); 5590 soc_mem_mac_addr_set(unit, L2Xm, &rep->match_mask, MAC_ADDRf, 5591 mac_mask); 5592 soc_mem_mac_addr_set(unit, L2Xm, &rep->match_data, MAC_ADDRf, 5593 rep->key_mac); 5594 } 5595 5596 if ((rep->flags & BCM_L2_REPLACE_MATCH_UC) && 5597 !(rep->flags & BCM_L2_REPLACE_MATCH_MC)) { 5598 /* The 40th bit of Unicast must be 0 */ 5599 sal_memset(&mac_mask, 0x00, sizeof(mac_mask)); 5600 mac_mask[0] = 0x01; 5601 sal_memset(&mac_data, 0x00, sizeof(mac_data)); 5602 soc_mem_mac_addr_set(unit, L2Xm, &rep->match_mask, MAC_ADDRf, 5603 mac_mask); 5604 soc_mem_mac_addr_set(unit, L2Xm, &rep->match_data, MAC_ADDRf, 5605 mac_data); 5606 } else if ((rep->flags & BCM_L2_REPLACE_MATCH_MC) && 5607 !(rep->flags & BCM_L2_REPLACE_MATCH_UC)) { 5608 /* The 40th bit of Multicast must be 1 */ 5609 sal_memset(&mac_mask, 0x00, sizeof(mac_mask)); 5610 mac_mask[0] = 0x01; 5611 sal_memset(&mac_data, 0x00, sizeof(mac_data)); 5612 mac_data[0] = 0x01; 5613 soc_mem_mac_addr_set(unit, L2Xm, &rep->match_mask, MAC_ADDRf, 5614 mac_mask); 5615 soc_mem_mac_addr_set(unit, L2Xm, &rep->match_data, MAC_ADDRf, 5616 mac_data); 5617 } 5618 5619 if (rep->flags & BCM_L2_REPLACE_MATCH_DEST) { 5620 if (rep->match_dest.vp != -1) { 5621 if (soc_feature(unit, soc_feature_generic_dest)) { 5622 field_len = soc_mem_field_length(unit, L2Xm, DESTINATIONf); 5623 soc_mem_field32_set(unit, L2Xm, &rep->match_mask, DESTINATIONf, 5624 (1 << field_len) - 1); 5625 soc_mem_field32_dest_set(unit, L2Xm, &rep->match_data, 5626 DESTINATIONf, SOC_MEM_FIF_DEST_DVP, rep->match_dest.vp); 5627 } else { 5628 field_len = soc_mem_field_length(unit, L2Xm, DEST_TYPEf); 5629 soc_mem_field32_set(unit, L2Xm, &rep->match_mask, DEST_TYPEf, 5630 (1 << field_len) - 1); 5631 soc_mem_field32_set(unit, L2Xm, &rep->match_data, DEST_TYPEf, 2); 5632 5633 field_len = soc_mem_field_length(unit, L2Xm, DESTINATIONf); 5634 soc_mem_field32_set(unit, L2Xm, &rep->match_mask, DESTINATIONf, 5635 (1 << field_len) - 1); 5636 soc_mem_field32_set(unit, L2Xm, &rep->match_data, DESTINATIONf, 5637 rep->match_dest.vp); 5638 } 5639 } else { 5640 if (soc_feature(unit, soc_feature_trunk_group_overlay)) { 5641 if (soc_feature(unit, soc_feature_generic_dest)) { 5642 field_len = soc_mem_field_length(unit, L2Xm, DESTINATIONf); 5643 if (rep->match_dest.trunk != -1) { 5644 soc_mem_field32_set(unit, L2Xm, &rep->match_mask, DESTINATIONf, 5645 (1 << field_len) - 1); 5646 soc_mem_field32_dest_set(unit, L2Xm, &rep->match_data, 5647 DESTINATIONf, SOC_MEM_FIF_DEST_LAG, rep->match_dest.trunk); 5648 } else { 5649 if (rep->match_dest.port != -1) { 5650 soc_mem_field32_set(unit, L2Xm, &rep->match_mask, DESTINATIONf, 5651 (1 << field_len) - 1); 5652 soc_mem_field32_dest_set(unit, L2Xm, &rep->match_data, 5653 DESTINATIONf, SOC_MEM_FIF_DEST_DGPP, 5654 rep->match_dest.module << SOC_MEM_FIF_DGPP_MOD_ID_SHIFT_BITS | 5655 rep->match_dest.port); 5656 } else { 5657 soc_mem_field32_dest_set(unit, L2Xm, &rep->match_mask, 5658 DESTINATIONf, SOC_MEM_FIF_DEST_DGPP, 5659 0xff << SOC_MEM_FIF_DGPP_MOD_ID_SHIFT_BITS | 0); 5660 soc_mem_field32_dest_set(unit, L2Xm, &rep->match_data, 5661 DESTINATIONf, SOC_MEM_FIF_DEST_DGPP, 5662 rep->match_dest.module << SOC_MEM_FIF_DGPP_MOD_ID_SHIFT_BITS | 5663 0); 5664 } 5665 5666 if (!(rep->flags & BCM_L2_REPLACE_MATCH_MAC)) { 5667 /* Ignore multicast mac from bulk delete */ 5668 mac_mask[0] = 0x01; 5669 mac_mask[1] = mac_mask[2] = mac_mask[3] = 5670 mac_mask[4] = mac_mask[5] = 0x00; 5671 soc_mem_mac_addr_set(unit, L2Xm, &rep->match_mask, 5672 MAC_ADDRf, mac_mask); 5673 } 5674 } 5675 } else { 5676 field_len = soc_mem_field_length(unit, L2Xm, DEST_TYPEf); 5677 soc_mem_field32_set(unit, L2Xm, &rep->match_mask, DEST_TYPEf, 5678 (1 << field_len) - 1); 5679 5680 if (rep->match_dest.trunk != -1) { 5681 soc_mem_field32_set(unit, L2Xm, &rep->match_data, 5682 DEST_TYPEf, 1); 5683 5684 field_len = soc_mem_field_length(unit, L2Xm, TGIDf); 5685 soc_mem_field32_set(unit, L2Xm, &rep->match_mask, TGIDf, 5686 (1 << field_len) - 1); 5687 soc_mem_field32_set(unit, L2Xm, &rep->match_data, TGIDf, 5688 rep->match_dest.trunk); 5689 } else { 5690 /* DEST_TYPE field in data is 0 */ 5691 5692 field_len = soc_mem_field_length(unit, L2Xm, MODULE_IDf); 5693 soc_mem_field32_set(unit, L2Xm, &rep->match_mask, 5694 MODULE_IDf, (1 << field_len) - 1); 5695 soc_mem_field32_set(unit, L2Xm, &rep->match_data, 5696 MODULE_IDf, rep->match_dest.module); 5697 if (rep->match_dest.port != -1) { 5698 field_len = soc_mem_field_length(unit, L2Xm, PORT_NUMf); 5699 soc_mem_field32_set(unit, L2Xm, &rep->match_mask, 5700 PORT_NUMf, (1 << field_len) - 1); 5701 soc_mem_field32_set(unit, L2Xm, &rep->match_data, 5702 PORT_NUMf, rep->match_dest.port); 5703 } 5704 5705 if (!(rep->flags & BCM_L2_REPLACE_MATCH_MAC)) { 5706 /* Ignore multicast mac from bulk delete */ 5707 mac_mask[0] = 0x01; 5708 mac_mask[1] = mac_mask[2] = mac_mask[3] = 5709 mac_mask[4] = mac_mask[5] = 0x00; 5710 soc_mem_mac_addr_set(unit, L2Xm, &rep->match_mask, 5711 MAC_ADDRf, mac_mask); 5712 } 5713 } 5714 } /* soc_feature_generic_dest */ 5715 } else { 5716 if (rep->match_dest.trunk != -1) { 5717 module = BCM_TRUNK_TO_MODIDf(unit, rep->match_dest.trunk); 5718 port = BCM_TRUNK_TO_TGIDf(unit, rep->match_dest.trunk); 5719 } else { 5720 module = rep->match_dest.module; 5721 port = rep->match_dest.port; 5722 } 5723 5724 field_len = soc_mem_field_length(unit, L2Xm, MODULE_IDf); 5725 soc_mem_field32_set(unit, L2Xm, &rep->match_mask, MODULE_IDf, 5726 (1 << field_len) - 1); 5727 soc_mem_field32_set(unit, L2Xm, &rep->match_data, MODULE_IDf, 5728 module); 5729 if (port != -1) { 5730 field_len = soc_mem_field_length(unit, L2Xm, TGID_PORTf); 5731 soc_mem_field32_set(unit, L2Xm, &rep->match_mask, TGID_PORTf, 5732 (1 << field_len) - 1); 5733 soc_mem_field32_set(unit, L2Xm, &rep->match_data, TGID_PORTf, 5734 port); 5735 } 5736 } 5737 } 5738 } 5739 5740 /* BCM_L2_REPLACE_MATCH_STATIC means to replace static as well as 5741 * non-static entries */ 5742 if (!(rep->flags & BCM_L2_REPLACE_MATCH_STATIC)) { 5743 if (rep->int_flags & _BCM_L2_REPLACE_INT_MATCH_ONLY_STATIC) { 5744 soc_mem_field32_set(unit, L2Xm, &rep->match_mask, STATIC_BITf, 1); 5745 soc_mem_field32_set(unit, L2Xm, &rep->match_data, STATIC_BITf, 1); 5746 } else { 5747 soc_mem_field32_set(unit, L2Xm, &rep->match_mask, STATIC_BITf, 1); 5748 /* STATIC_BIT field in data is 0 */ 5749 } 5750 } 5751 /* STATIC_BIT field in mask is 0 */ 5752 #ifdef BCM_TRIDENT2PLUS_SUPPORT 5753 if (SOC_IS_TRIDENT2PLUS(unit) || SOC_IS_TRIDENT3X(unit)) { 5754 if (rep->flags & BCM_L2_REPLACE_MATCH_CLASS_ID) { 5755 soc_mem_field32_set(unit, L2Xm, &rep->match_mask, CLASS_IDf, 0x3f); 5756 soc_mem_field32_set(unit, L2Xm, &rep->match_data, CLASS_IDf, rep->key_class_id); 5757 } 5758 if (rep->flags & BCM_L2_REPLACE_MATCH_INT_PRI) { 5759 soc_mem_field32_set(unit, L2Xm, &rep->match_mask, RPEf, 0x1); 5760 soc_mem_field32_set(unit, L2Xm, &rep->match_data, RPEf, 1); 5761 soc_mem_field32_set(unit, L2Xm, &rep->match_mask, PRIf, 0x1); 5762 soc_mem_field32_set(unit, L2Xm, &rep->match_data, PRIf, rep->key_int_pri); 5763 } 5764 } 5765 #endif /*BCM_TRIDENT2PLUS_SUPPORT*/ 5766 if (soc_mem_field_valid(unit, L2Xm, PENDINGf)) { 5767 soc_mem_field32_set(unit, L2Xm, &rep->match_mask, PENDINGf, 1); 5768 if (rep->flags & BCM_L2_REPLACE_PENDING) { 5769 soc_mem_field32_set(unit, L2Xm, &rep->match_data, PENDINGf, 1); 5770 } 5771 } 5772 5773 if (rep->int_flags & _BCM_L2_REPLACE_INT_MATCH_DISCARD_SRC) { 5774 soc_mem_field32_set(unit, L2Xm, &rep->match_mask, SRC_DISCARDf, 1); 5775 if (rep->key_l2_flags & BCM_L2_DISCARD_SRC) { 5776 soc_mem_field32_set(unit, L2Xm, &rep->match_data, SRC_DISCARDf, 1); 5777 } 5778 } 5779 5780 if (rep->int_flags & _BCM_L2_REPLACE_INT_MATCH_SRC_HIT) { 5781 soc_mem_field32_set(unit, L2Xm, &rep->match_mask, HITSAf, 1); 5782 if (rep->key_l2_flags & BCM_L2_SRC_HIT) { 5783 soc_mem_field32_set(unit, L2Xm, &rep->match_data, HITSAf, 1); 5784 } 5785 } 5786 if (rep->int_flags & _BCM_L2_REPLACE_INT_MATCH_DES_HIT) { 5787 soc_mem_field32_set(unit, L2Xm, &rep->match_mask, HITDAf, 1); 5788 if (rep->key_l2_flags & BCM_L2_DES_HIT) { 5789 soc_mem_field32_set(unit, L2Xm, &rep->match_data, HITDAf, 1); 5790 } 5791 } 5792 if (SOC_MEM_FIELD_VALID(unit, L2Xm, LOCAL_SAf)) { 5793 if (rep->int_flags & _BCM_L2_REPLACE_INT_MATCH_NATIVE) { 5794 soc_mem_field32_set(unit, L2Xm, &rep->match_mask, LOCAL_SAf, 1); 5795 if (rep->key_l2_flags & BCM_L2_NATIVE) { 5796 soc_mem_field32_set(unit, L2Xm, &rep->match_data, LOCAL_SAf, 5797 1); 5798 } 5799 } 5800 } 5801 if (_CLEAR_ALL_ENTRIES_SRC_OR_DES_HIT_BIT(rep->flags)) { 5802 if (rep->flags & BCM_L2_REPLACE_DES_HIT_CLEAR) { 5803 soc_mem_field32_set(unit, L2Xm, &rep->match_mask, HITDAf, 1); 5804 soc_mem_field32_set(unit, L2Xm, &rep->match_data, HITDAf, 1); 5805 } 5806 if (rep->flags & BCM_L2_REPLACE_SRC_HIT_CLEAR) { 5807 soc_mem_field32_set(unit, L2Xm, &rep->match_mask, HITSAf, 1); 5808 soc_mem_field32_set(unit, L2Xm, &rep->match_data, HITSAf, 1); 5809 } 5810 } 5811 if (!(rep->flags & (BCM_L2_REPLACE_DELETE | BCM_L2_REPLACE_AGE))) { 5812 if (!_CLEAR_ALL_ENTRIES_SRC_OR_DES_HIT_BIT(rep->flags)) { 5813 if (rep->new_dest.vp != -1) { 5814 if (soc_feature(unit, soc_feature_generic_dest)) { 5815 field_len = soc_mem_field_length(unit, L2Xm, DESTINATIONf); 5816 soc_mem_field32_set(unit, L2Xm, &rep->new_mask, DESTINATIONf, 5817 (1 << field_len) - 1); 5818 soc_mem_field32_dest_set(unit, L2Xm, &rep->new_data, 5819 DESTINATIONf, SOC_MEM_FIF_DEST_DVP, rep->new_dest.vp); 5820 } else { 5821 field_len = soc_mem_field_length(unit, L2Xm, DEST_TYPEf); 5822 soc_mem_field32_set(unit, L2Xm, &rep->new_mask, DEST_TYPEf, 5823 (1 << field_len) - 1); 5824 soc_mem_field32_set(unit, L2Xm, &rep->new_data, DEST_TYPEf, 2); 5825 field_len = soc_mem_field_length(unit, L2Xm, DESTINATIONf); 5826 soc_mem_field32_set(unit, L2Xm, &rep->new_mask, DESTINATIONf, 5827 (1 << field_len) - 1); 5828 soc_mem_field32_set(unit, L2Xm, &rep->new_data, DESTINATIONf, 5829 rep->new_dest.vp); 5830 } 5831 } else { 5832 if (soc_feature(unit, soc_feature_trunk_group_overlay)) { 5833 if (soc_feature(unit, soc_feature_generic_dest)) { 5834 field_len = soc_mem_field_length(unit, L2Xm, DESTINATIONf); 5835 soc_mem_field32_set(unit, L2Xm, &rep->new_mask, DESTINATIONf, 5836 (1 << field_len) - 1); 5837 if (rep->new_dest.trunk != -1) { 5838 soc_mem_field32_dest_set(unit, L2Xm, &rep->new_data, 5839 DESTINATIONf, SOC_MEM_FIF_DEST_LAG, rep->new_dest.trunk); 5840 } else { 5841 soc_mem_field32_dest_set(unit, L2Xm, &rep->new_data, 5842 DESTINATIONf, SOC_MEM_FIF_DEST_DGPP, 5843 rep->new_dest.module << SOC_MEM_FIF_DGPP_MOD_ID_SHIFT_BITS | 5844 rep->new_dest.port); 5845 } 5846 } else { 5847 if (rep->new_dest.trunk != -1) { 5848 field_len = soc_mem_field_length(unit, L2Xm, DEST_TYPEf); 5849 soc_mem_field32_set(unit, L2Xm, &rep->new_mask, DEST_TYPEf, 5850 (1 << field_len) - 1); 5851 5852 soc_mem_field32_set(unit, L2Xm, &rep->new_data, DEST_TYPEf, 5853 1); 5854 5855 /* 5856 * Writing to DESTINATION field instead of TGIDf 5857 * to ensure the MSB bits of DESTINATION are cleared. 5858 */ 5859 field_len = soc_mem_field_length(unit, L2Xm, 5860 DESTINATIONf); 5861 soc_mem_field32_set(unit, L2Xm, &rep->new_mask, 5862 DESTINATIONf, (1 << field_len) - 1); 5863 soc_mem_field32_set(unit, L2Xm, &rep->new_data, 5864 DESTINATIONf, rep->new_dest.trunk); 5865 } else if (rep->new_dest.port != -1 5866 && rep->new_dest.module != -1) { 5867 /* DEST_TYPE field in data is 0 */ 5868 field_len = soc_mem_field_length(unit, L2Xm, DEST_TYPEf); 5869 soc_mem_field32_set(unit, L2Xm, &rep->new_mask, DEST_TYPEf, 5870 (1 << field_len) - 1); 5871 5872 field_len = soc_mem_field_length(unit, L2Xm, MODULE_IDf); 5873 soc_mem_field32_set(unit, L2Xm, &rep->new_mask, 5874 MODULE_IDf, (1 << field_len) - 1); 5875 soc_mem_field32_set(unit, L2Xm, &rep->new_data, 5876 MODULE_IDf, rep->new_dest.module); 5877 5878 field_len = soc_mem_field_length(unit, L2Xm, PORT_NUMf); 5879 soc_mem_field32_set(unit, L2Xm, &rep->new_mask, 5880 PORT_NUMf, (1 << field_len) - 1); 5881 soc_mem_field32_set(unit, L2Xm, &rep->new_data, 5882 PORT_NUMf, rep->new_dest.port); 5883 } 5884 } /* soc_feature_generic_dest */ 5885 } else { 5886 if (soc_feature(unit, soc_feature_trunk_group_overlay)) { 5887 if (rep->new_dest.trunk != -1) { 5888 field_len = soc_mem_field_length(unit, L2Xm, DEST_TYPEf); 5889 soc_mem_field32_set(unit, L2Xm, &rep->new_mask, DEST_TYPEf, 5890 (1 << field_len) - 1); 5891 soc_mem_field32_set(unit, L2Xm, &rep->new_data, DEST_TYPEf, 5892 1); 5893 /* 5894 * Writing to DESTINATION field instead of TGIDf 5895 * to ensure the MSB bits of DESTINATION are cleared. 5896 */ 5897 field_len = soc_mem_field_length(unit, L2Xm, 5898 DESTINATIONf); 5899 soc_mem_field32_set(unit, L2Xm, &rep->new_mask, 5900 DESTINATIONf, (1 << field_len) - 1); 5901 soc_mem_field32_set(unit, L2Xm, &rep->new_data, 5902 DESTINATIONf, rep->new_dest.trunk); 5903 } else if (rep->new_dest.port != -1 5904 && rep->new_dest.module != -1) { 5905 /* DEST_TYPE field in data is 0 */ 5906 field_len = soc_mem_field_length(unit, L2Xm, DEST_TYPEf); 5907 soc_mem_field32_set(unit, L2Xm, &rep->new_mask, DEST_TYPEf, 5908 (1 << field_len) - 1); 5909 field_len = soc_mem_field_length(unit, L2Xm, MODULE_IDf); 5910 soc_mem_field32_set(unit, L2Xm, &rep->new_mask, 5911 MODULE_IDf, (1 << field_len) - 1); 5912 soc_mem_field32_set(unit, L2Xm, &rep->new_data, 5913 MODULE_IDf, rep->new_dest.module); 5914 field_len = soc_mem_field_length(unit, L2Xm, PORT_NUMf); 5915 soc_mem_field32_set(unit, L2Xm, &rep->new_mask, 5916 PORT_NUMf, (1 << field_len) - 1); 5917 soc_mem_field32_set(unit, L2Xm, &rep->new_data, 5918 PORT_NUMf, rep->new_dest.port); 5919 } 5920 } else { 5921 if (rep->new_dest.trunk != -1) { 5922 module = BCM_TRUNK_TO_MODIDf(unit, rep->new_dest.trunk); 5923 port = BCM_TRUNK_TO_TGIDf(unit, rep->new_dest.trunk); 5924 } else if (rep->new_dest.port != -1 5925 && rep->new_dest.module != -1) { 5926 module = rep->new_dest.module; 5927 port = rep->new_dest.port; 5928 } else { 5929 module = port = -1; 5930 } 5931 if (module != -1 && port != -1) { 5932 field_len = soc_mem_field_length(unit, L2Xm, MODULE_IDf); 5933 soc_mem_field32_set(unit, L2Xm, &rep->new_mask, MODULE_IDf, 5934 (1 << field_len) - 1); 5935 soc_mem_field32_set(unit, L2Xm, &rep->new_data, MODULE_IDf, 5936 module); 5937 field_len = soc_mem_field_length(unit, L2Xm, TGID_PORTf); 5938 soc_mem_field32_set(unit, L2Xm, &rep->new_mask, TGID_PORTf, 5939 (1 << field_len) - 1); 5940 soc_mem_field32_set(unit, L2Xm, &rep->new_data, TGID_PORTf, 5941 port); 5942 } 5943 } 5944 } 5945 } 5946 } 5947 if (rep->flags & BCM_L2_REPLACE_DES_HIT_CLEAR) { 5948 soc_mem_field32_set(unit, L2Xm, &rep->new_mask, HITDAf, 1); 5949 } 5950 if (rep->flags & BCM_L2_REPLACE_SRC_HIT_CLEAR) { 5951 soc_mem_field32_set(unit, L2Xm, &rep->new_mask, HITSAf, 1); 5952 } 5953 } 5954 5955 return BCM_E_NONE; 5956 } 5957 5958 STATIC int 5959 _soc_l2_sync_mem_cache(int unit, _bcm_l2_replace_t *rep_st) 5960 { 5961 uint8 *vmap; 5962 soc_mem_t mem = L2Xm; 5963 uint32 *cache, *entry, *match_data, *match_mask; 5964 uint32 *new_data, *new_mask; 5965 int index_max, idx, i; 5966 int entry_dw = soc_mem_entry_words(unit, mem); 5967 int entry_words = soc_mem_entry_words(unit, mem); 5968 int copyno = SOC_MEM_BLOCK_ANY(unit, mem); 5969 soc_field_t vld_fld = VALIDf; 5970 5971 cache = SOC_MEM_STATE(unit, mem).cache[copyno]; 5972 if (cache == NULL) { 5973 return BCM_E_NONE; 5974 } 5975 5976 if (soc_feature(unit, soc_feature_base_valid)) { 5977 vld_fld = BASE_VALIDf; 5978 } 5979 vmap = SOC_MEM_STATE(unit, mem).vmap[copyno]; 5980 index_max = soc_mem_index_max(unit, mem); 5981 for (idx = 0; idx <= index_max; idx++) { 5982 if (!CACHE_VMAP_TST(vmap, idx)) { 5983 continue; 5984 } 5985 entry = cache + (idx * entry_dw); 5986 if (!soc_mem_field32_get(unit, mem, entry, vld_fld)) { 5987 continue; 5988 } 5989 if (!soc_mem_field32_get(unit, mem, entry, STATIC_BITf)) { 5990 continue; 5991 } 5992 match_data = (uint32 *)&rep_st->match_data; 5993 match_mask = (uint32 *)&rep_st->match_mask; 5994 for (i = 0; i < entry_words; i++) { 5995 if ((entry[i] ^ match_data[i]) & match_mask[i]) { 5996 break; 5997 } 5998 } 5999 if (i != entry_words) { 6000 continue; 6001 } 6002 /* Match found, delete or replace entry */ 6003 LOG_VERBOSE(BSL_LS_SOC_COMMON, 6004 (BSL_META_U(unit, 6005 "Match found in L2 bulk cache op: %d\n"), idx)); 6006 if (rep_st->flags & BCM_L2_REPLACE_DELETE) { 6007 /* Delete op - invalidate the entry */ 6008 CACHE_VMAP_CLR(vmap, idx); 6009 } else { 6010 /* Replace op - update entry */ 6011 new_data = (uint32 *)&rep_st->new_data; 6012 new_mask = (uint32 *)&rep_st->new_mask; 6013 for (i = 0; i < entry_words; i++) { 6014 entry[i] ^= (entry[i] ^ new_data[i]) & new_mask[i]; 6015 } 6016 } 6017 } 6018 return BCM_E_NONE; 6019 } 6020 6021 STATIC int 6022 _is_soc_l2_mem_cache_enabled(int unit) 6023 { 6024 soc_mem_t mem = L2Xm; 6025 uint32 *cache; 6026 int copyno = SOC_MEM_BLOCK_ANY(unit, mem); 6027 6028 cache = SOC_MEM_STATE(unit, mem).cache[copyno]; 6029 6030 if (cache == NULL) { 6031 return FALSE; 6032 } 6033 6034 return TRUE; 6035 } 6036 6037 STATIC int 6038 _bcm_esw_l2_replace(int unit, uint32 flags, uint32 int_flags, 6039 bcm_l2_addr_t *match_addr, bcm_module_t new_module, 6040 bcm_port_t new_port, bcm_trunk_t new_trunk, 6041 bcm_l2_traverse_cb trav_fn, void *user_data) 6042 { 6043 uint32 cmp_flags; 6044 _bcm_l2_replace_t rep_st; 6045 _bcm_l2_traverse_t trav_st; 6046 _bcm_l2_match_ctrl_t *match_ctrl; 6047 int entry_rd_idx, buf_index, entry_index, do_trav_cb; 6048 int rv = BCM_E_UNAVAIL; 6049 int use_hw_ppa, do_freeze; 6050 int mode; 6051 l2x_entry_t l2x_entry, *l2x_entry_ptr; 6052 bcm_l2_addr_t l2_addr; 6053 int tid_is_vp_lag; 6054 uint32 rval = 0; 6055 uint32 l2_memwr = 0; 6056 #if defined(BCM_TRIDENT2_SUPPORT) && defined(INCLUDE_L3) 6057 source_vp_entry_t svp; 6058 uint32 etype; 6059 #endif /* BCM_TRIDENT2_SUPPORT && INCLUDE_L3 */ 6060 #ifdef BCM_TRIDENT3_SUPPORT 6061 uint32 flow_handle; 6062 #endif /* BCM_TRIDENT3_SUPPORT */ 6063 6064 sal_memset(&rep_st, 0, sizeof(_bcm_l2_replace_t)); 6065 sal_memset(&trav_st, 0, sizeof(_bcm_l2_traverse_t)); 6066 6067 rep_st.trav_fn = trav_fn; 6068 rep_st.user_data = user_data; 6069 rep_st.flags = flags; 6070 rep_st.int_flags = int_flags; 6071 if ((int_flags & _BCM_L2_REPLACE_IGNORE_PORTID) && 6072 !(flags & BCM_L2_REPLACE_DELETE) && 6073 !(flags & BCM_L2_REPLACE_MATCH_DEST)) { 6074 return BCM_E_PARAM; 6075 } 6076 if (!(flags & (BCM_L2_REPLACE_DELETE | BCM_L2_REPLACE_AGE)) && 6077 !(int_flags & _BCM_L2_REPLACE_INT_NO_ACTION)) { 6078 BCM_IF_ERROR_RETURN(_bcm_l2_replace_dest_setup 6079 (unit, new_module, new_port, new_trunk, 6080 flags & BCM_L2_REPLACE_NEW_TRUNK, 6081 &rep_st.new_dest)); 6082 } 6083 6084 if (match_addr == NULL) { 6085 if (flags & BCM_L2_REPLACE_VPN_TYPE) { 6086 rep_st.key_type = 3; /* VFI Type */ 6087 } 6088 } else { 6089 rep_st.key_l2_flags = match_addr->flags; 6090 6091 if (flags & BCM_L2_REPLACE_MATCH_DEST) { 6092 if (int_flags & _BCM_L2_REPLACE_IGNORE_PORTID) { 6093 if (!SOC_MODID_ADDRESSABLE(unit, match_addr->modid)) { 6094 return BCM_E_BADID; 6095 } 6096 rep_st.match_dest.vp = -1; 6097 rep_st.match_dest.trunk = -1; 6098 rep_st.match_dest.port = -1; 6099 rep_st.match_dest.module = match_addr->modid; 6100 } else { 6101 BCM_IF_ERROR_RETURN(_bcm_l2_replace_dest_setup 6102 (unit, match_addr->modid, match_addr->port, 6103 match_addr->tgid, 6104 match_addr->flags & BCM_L2_TRUNK_MEMBER, 6105 &rep_st.match_dest)); 6106 } 6107 if (rep_st.match_dest.vp != -1) { 6108 if(match_addr->flags & BCM_L2_TRUNK_MEMBER) { 6109 BCM_IF_ERROR_RETURN( 6110 _bcm_esw_trunk_id_is_vp_lag(unit, match_addr->tgid, 6111 &tid_is_vp_lag)); 6112 if (tid_is_vp_lag) { 6113 #if defined(BCM_TRIDENT2_SUPPORT) && defined(INCLUDE_L3) 6114 if (soc_feature(unit, soc_feature_vp_lag)) { 6115 BCM_IF_ERROR_RETURN( 6116 soc_mem_read(unit, SOURCE_VPm, MEM_BLOCK_ANY, 6117 rep_st.match_dest.vp, &svp)); 6118 if (SOC_MEM_FIELD_VALID(unit, 6119 SOURCE_VPm, ENTRY_TYPEf)) { 6120 etype = soc_SOURCE_VPm_field32_get(unit, &svp, 6121 ENTRY_TYPEf); 6122 switch(etype) { 6123 case 1: /* VPLS SVP and use VFI */ 6124 rep_st.key_type = 3; /* VFI */ 6125 break; 6126 case 3: /* VLAN-based Forwarding */ 6127 rep_st.key_type = 0; /* L2 Bridge */ 6128 break; 6129 default: /* 0: INVALID */ 6130 rep_st.key_type = -1; /* Do not care key type */ 6131 break; 6132 } 6133 } 6134 } else 6135 #endif /* BCM_TRIDENT2_SUPPORT && INCLUDE_L3 */ 6136 { 6137 return BCM_E_PORT; 6138 } 6139 } else { 6140 return BCM_E_PARAM; 6141 } 6142 } else { 6143 if (!BCM_GPORT_IS_WLAN_PORT(match_addr->port) && 6144 !BCM_GPORT_IS_NIV_PORT(match_addr->port) && 6145 !BCM_GPORT_IS_TRILL_PORT(match_addr->port) && 6146 !BCM_GPORT_IS_VLAN_PORT(match_addr->port) && 6147 !BCM_GPORT_IS_EXTENDER_PORT(match_addr->port)) { 6148 /* Note: For MPLS, MiM, L2GRE, VXLAN VFI types only */ 6149 rep_st.key_type = 3; /* VFI Type */ 6150 } 6151 } 6152 } 6153 } 6154 6155 if (flags & BCM_L2_REPLACE_MATCH_VLAN) { 6156 rep_st.key_vfi = -1; 6157 #ifdef BCM_TRIUMPH_SUPPORT 6158 if (SOC_MEM_IS_VALID(unit, VFIm)) { 6159 if (_BCM_VPN_VFI_IS_SET(match_addr->vid)) { 6160 _BCM_VPN_GET(rep_st.key_vfi, _BCM_VPN_TYPE_VFI, match_addr->vid); 6161 } 6162 } 6163 #endif /* BCM_TRIUMPH_SUPPORT */ 6164 if (rep_st.key_vfi != -1) { 6165 if (rep_st.key_vfi > soc_mem_index_max(unit, VFIm)) { 6166 return BCM_E_PARAM; 6167 } 6168 rep_st.key_type = 3; /* VFI Type */ 6169 } else { 6170 VLAN_CHK_ID(unit, match_addr->vid); 6171 rep_st.key_vlan = match_addr->vid; 6172 rep_st.key_type = 0; /* L2 Bridge */ 6173 } 6174 } 6175 6176 if (flags & BCM_L2_REPLACE_MATCH_MAC) { 6177 sal_memcpy(&rep_st.key_mac, match_addr->mac, sizeof(bcm_mac_t)); 6178 } 6179 6180 /* When replace L2 by MAC, key type must be provided. */ 6181 /* Key type is 0 by default for L2 Bridge. */ 6182 /* Here add support for explicitly assigned VFI type */ 6183 if (flags & BCM_L2_REPLACE_VPN_TYPE) { 6184 rep_st.key_type = 3; /* VFI Type */ 6185 } 6186 #ifdef BCM_TRIDENT2PLUS_SUPPORT 6187 if (SOC_IS_TRIDENT2PLUS(unit) || SOC_IS_TRIDENT3X(unit)) { 6188 if (flags & BCM_L2_REPLACE_MATCH_INT_PRI) { 6189 rep_st.key_int_pri = match_addr->cos_dst; 6190 } 6191 if (flags & BCM_L2_REPLACE_MATCH_CLASS_ID) { 6192 rep_st.key_class_id= match_addr->group; 6193 } 6194 } 6195 #endif 6196 } 6197 #ifdef BCM_TRIDENT3_SUPPORT 6198 if (match_addr != NULL) { 6199 flow_handle = match_addr->flow_handle; 6200 } 6201 else { 6202 flow_handle = 0; 6203 } 6204 6205 if (soc_feature(unit, soc_feature_flex_flow) && 6206 flow_handle != 0) { 6207 6208 /* Get view id corresponding to the specified flow. */ 6209 rv = soc_flow_db_ffo_to_mem_view_id_get(unit, 6210 match_addr->flow_handle, 6211 match_addr->flow_option_handle, 6212 SOC_FLOW_DB_FUNC_L2_SWITCH_ID, 6213 &rep_st.view_id); 6214 BCM_IF_ERROR_RETURN(rv); 6215 6216 BCM_IF_ERROR_RETURN(_bcm_td3_flex_l2_replace_data_mask_setup(unit, &rep_st)); 6217 } 6218 else 6219 #endif 6220 { 6221 BCM_IF_ERROR_RETURN(_bcm_l2_replace_data_mask_setup(unit, &rep_st)); 6222 } 6223 6224 /* Validate matching destination only if match all was not set */ 6225 cmp_flags = flags & (BCM_L2_REPLACE_MATCH_MAC | BCM_L2_REPLACE_MATCH_VLAN | 6226 BCM_L2_REPLACE_MATCH_DEST); 6227 use_hw_ppa = TRUE; 6228 switch (cmp_flags) { 6229 case BCM_L2_REPLACE_MATCH_MAC: 6230 case BCM_L2_REPLACE_MATCH_MAC | BCM_L2_REPLACE_MATCH_DEST: 6231 case BCM_L2_REPLACE_MATCH_MAC | BCM_L2_REPLACE_MATCH_VLAN: 6232 if (!soc_feature(unit, soc_feature_l2_bulk_control)) { 6233 use_hw_ppa = FALSE; 6234 } else if (soc_feature(unit, soc_feature_l2_bulk_bypass_replace)) { 6235 if (!( flags & (BCM_L2_REPLACE_DELETE | BCM_L2_REPLACE_AGE)) && 6236 !(int_flags & _BCM_L2_REPLACE_INT_NO_ACTION)) { 6237 use_hw_ppa = FALSE; 6238 } 6239 } 6240 break; 6241 case BCM_L2_REPLACE_MATCH_VLAN: 6242 case BCM_L2_REPLACE_MATCH_DEST: 6243 case BCM_L2_REPLACE_MATCH_VLAN | BCM_L2_REPLACE_MATCH_DEST: 6244 if (SOC_CONTROL(unit)->l2x_ppa_bypass) { 6245 use_hw_ppa = FALSE; 6246 } else if (!soc_feature(unit, soc_feature_l2_bulk_control) && 6247 !soc_feature(unit, soc_feature_ppa_match_vp) && 6248 (rep_st.flags & BCM_L2_REPLACE_MATCH_DEST) && 6249 rep_st.match_dest.vp != -1) { 6250 use_hw_ppa = FALSE; 6251 } else if (soc_feature(unit, soc_feature_l2_bulk_bypass_replace)) { 6252 if (!(flags & (BCM_L2_REPLACE_DELETE | BCM_L2_REPLACE_AGE)) && 6253 !(int_flags & _BCM_L2_REPLACE_INT_NO_ACTION)) { 6254 if (cmp_flags != BCM_L2_REPLACE_MATCH_DEST || 6255 rep_st.match_dest.vp != -1 || 6256 rep_st.match_dest.trunk != -1) { 6257 use_hw_ppa = FALSE; 6258 } 6259 } 6260 } else if (!soc_feature(unit, soc_feature_l2_bulk_control) && 6261 (flags & BCM_L2_REPLACE_SRC_HIT_CLEAR || 6262 flags & BCM_L2_REPLACE_DES_HIT_CLEAR)) { 6263 /* 6264 * For devices without supporting L2 bulk feature: 6265 * - It doesn't support to reset SRC/DST Hit-bit respectively by Hardware L2 PPA 6266 * register for L2 replace function. 6267 * - To traverse the L2 table and replace given entry if any L2 entry matches. 6268 */ 6269 use_hw_ppa = FALSE; 6270 } 6271 break; 6272 default: 6273 break; 6274 } 6275 #ifdef PLISIM 6276 #if defined(BCM_KATANA_SUPPORT) 6277 /* Forcefully setting hw_ppa flag to false in KatanaSimulationEnvironment */ 6278 if (SOC_IS_KATANAX(unit) && (SAL_BOOT_PLISIM || SAL_BOOT_BCMSIM)) { 6279 use_hw_ppa = FALSE; 6280 } 6281 #endif 6282 #endif 6283 6284 /* Hardware L2 PPA register don't support to delete by UC, MC entries or both respectively */ 6285 if (use_hw_ppa && 6286 (flags & BCM_L2_REPLACE_DELETE) && 6287 (flags & (BCM_L2_REPLACE_MATCH_UC | BCM_L2_REPLACE_MATCH_MC))) { 6288 if (SOC_REG_IS_VALID(unit, PER_PORT_AGE_CONTROLr) || 6289 SOC_REG_IS_VALID(unit, PER_PORT_AGE_CONTROL_64r)) { 6290 return BCM_E_UNAVAIL; 6291 } 6292 } 6293 6294 mode = SOC_CONTROL(unit)->l2x_mode; 6295 /* Delete operation don't require freeze */ 6296 do_freeze = FALSE; 6297 if (use_hw_ppa && (int_flags & _BCM_L2_REPLACE_INT_NO_ACTION)) { 6298 if (soc_feature(unit, soc_feature_l2_bulk_control) && 6299 mode == L2MODE_FIFO) { 6300 _bcm_l2_match_ctrl[unit]->entry_wr_idx = 0; 6301 } else { 6302 use_hw_ppa = FALSE; 6303 } 6304 } else if ((!use_hw_ppa && 6305 !(flags & (BCM_L2_REPLACE_DELETE | BCM_L2_REPLACE_AGE))) || 6306 mode != L2MODE_FIFO || 6307 ((flags & BCM_L2_REPLACE_MATCH_STATIC) && 6308 _is_soc_l2_mem_cache_enabled(unit))) { 6309 do_freeze = TRUE; 6310 } 6311 6312 if (do_freeze) { 6313 BCM_IF_ERROR_RETURN(bcm_esw_l2_addr_freeze(unit)); 6314 } 6315 if (use_hw_ppa) { 6316 rv = _bcm_l2_replace_by_hw(unit, flags, &rep_st); 6317 if (BCM_SUCCESS(rv) && (int_flags & _BCM_L2_REPLACE_INT_NO_ACTION)) { 6318 match_ctrl = _bcm_l2_match_ctrl[unit]; 6319 if (SOC_REG_IS_VALID(unit,L2_MOD_FIFO_ENABLEr)) { 6320 rv = READ_L2_MOD_FIFO_ENABLEr(unit, &rval); 6321 l2_memwr = soc_reg_field_get(unit, L2_MOD_FIFO_ENABLEr, rval, 6322 L2_MEMWRf); 6323 if (BCM_SUCCESS(rv)) { 6324 rv = soc_reg_field32_modify(unit, L2_MOD_FIFO_ENABLEr, 6325 REG_PORT_ANY, L2_MEMWRf, 1); 6326 } 6327 } else { 6328 rv = READ_AUX_ARB_CONTROLr(unit, &rval); 6329 l2_memwr = soc_reg_field_get(unit, AUX_ARB_CONTROLr, rval, 6330 L2_MOD_FIFO_ENABLE_MEMWRf); 6331 if (BCM_SUCCESS(rv)) { 6332 rv = soc_reg_field32_modify(unit, AUX_ARB_CONTROLr,REG_PORT_ANY, 6333 L2_MOD_FIFO_ENABLE_MEMWRf, 1); 6334 } 6335 } 6336 if (BCM_SUCCESS(rv)) { 6337 rv = soc_mem_read(unit, L2Xm, MEM_BLOCK_ANY, 0, &l2x_entry); 6338 if (BCM_SUCCESS(rv)) { 6339 (void)soc_mem_write(unit, L2Xm, MEM_BLOCK_ALL, 0, 6340 &l2x_entry); 6341 } 6342 if (SOC_REG_IS_VALID(unit,L2_MOD_FIFO_ENABLEr)) { 6343 (void)soc_reg_field32_modify(unit, L2_MOD_FIFO_ENABLEr, 6344 REG_PORT_ANY, L2_MEMWRf, l2_memwr); 6345 } else { 6346 (void)soc_reg_field32_modify(unit, AUX_ARB_CONTROLr, 6347 REG_PORT_ANY, 6348 L2_MOD_FIFO_ENABLE_MEMWRf, l2_memwr); 6349 } 6350 } 6351 entry_rd_idx = 0; 6352 do_trav_cb = TRUE; 6353 while (1) { 6354 if (entry_rd_idx == match_ctrl->entry_wr_idx) { 6355 if (sal_sem_take(_bcm_l2_match_ctrl[unit]->sem, 5000000)) { 6356 /* If waiting too long, something happened in HW */ 6357 if (SOC_CONTROL(unit)->l2x_pid == SAL_THREAD_ERROR) { 6358 for (buf_index = entry_rd_idx / _BCM_L2_MATCH_ENTRY_BUF_SIZE; 6359 buf_index >= 0; 6360 buf_index --) { 6361 sal_free(match_ctrl->l2x_entry_buf[buf_index]); 6362 } 6363 } 6364 rv = BCM_E_INTERNAL; 6365 break; 6366 } 6367 6368 continue; 6369 } 6370 buf_index = entry_rd_idx / _BCM_L2_MATCH_ENTRY_BUF_SIZE; 6371 entry_index = entry_rd_idx % _BCM_L2_MATCH_ENTRY_BUF_SIZE; 6372 l2x_entry_ptr = 6373 &match_ctrl->l2x_entry_buf[buf_index][entry_index]; 6374 6375 if (l2x_entry_ptr->entry_data[0] == 0) { 6376 for (; buf_index >= 0; buf_index--) { 6377 sal_free(match_ctrl->l2x_entry_buf[buf_index]); 6378 } 6379 break; 6380 } 6381 if (do_trav_cb) { 6382 (void)_bcm_esw_l2_from_l2x(unit, 0, &l2_addr, 6383 (uint32 *)l2x_entry_ptr); 6384 if (trav_fn(unit, &l2_addr, user_data) < 0) { 6385 do_trav_cb = FALSE; 6386 } 6387 } 6388 if (do_trav_cb) { 6389 entry_rd_idx++; 6390 } else { 6391 /* skip to the last buffered entry */ 6392 entry_rd_idx = match_ctrl->entry_wr_idx - 1; 6393 } 6394 } 6395 } 6396 } else { 6397 trav_st.user_data = (void *)&rep_st; 6398 trav_st.int_cb = _bcm_l2_entry_replace; 6399 rv = _bcm_esw_l2_traverse(unit, &trav_st); 6400 } 6401 6402 if (use_hw_ppa && !(int_flags & _BCM_L2_REPLACE_INT_NO_ACTION) && 6403 SOC_SUCCESS(rv) && (rep_st.flags & BCM_L2_REPLACE_MATCH_STATIC)) { 6404 /* update the entries in mem cache with the bulk op results */ 6405 rv = _soc_l2_sync_mem_cache(unit, &rep_st); 6406 } 6407 6408 if (do_freeze) { 6409 BCM_IF_ERROR_RETURN(bcm_esw_l2_addr_thaw(unit)); 6410 } 6411 6412 return rv; 6413 } 6414 6415 /* 6416 * Function: 6417 * bcm_esw_l2_replace 6418 * Description: 6419 * To replace destination (or delete) multiple L2 entries 6420 * Parameters: 6421 * unit device number 6422 * flags flags BCM_L2_REPLACE_* 6423 * match_addr L2 parameters to match on delete/replace 6424 * new_module new module ID for a replace 6425 * new_port new port for a replace 6426 * new_trunk new trunk for a replace 6427 * Return: 6428 * BCM_E_XXX 6429 */ 6430 int 6431 bcm_esw_l2_replace(int unit, uint32 flags, bcm_l2_addr_t *match_addr, 6432 bcm_module_t new_module, bcm_port_t new_port, 6433 bcm_trunk_t new_trunk) 6434 { 6435 #if defined(BCM_TOMAHAWK3_SUPPORT) 6436 /* Added to handle SDK functions calling esw version, 6437 * instead of Tomahawk3's version 6438 */ 6439 if (SOC_IS_TOMAHAWK3(unit)) { 6440 return bcm_tomahawk3_l2_replace(unit, flags, match_addr, new_module, 6441 new_port, new_trunk); 6442 } 6443 #endif /* BCM_TOMAHAWK3_SUPPORT */ 6444 6445 L2_INIT(unit); 6446 6447 #if defined(BCM_TRIUMPH3_SUPPORT) 6448 if (soc_feature(unit, soc_feature_ism_memory)) { 6449 return bcm_tr3_l2_replace(unit, flags, match_addr, 6450 new_module, new_port, new_trunk); 6451 } 6452 #endif /* BCM_TRIUMPH3_SUPPORT */ 6453 6454 if (!flags) { 6455 return BCM_E_PARAM; 6456 } 6457 if (( flags & (BCM_L2_REPLACE_DELETE | BCM_L2_REPLACE_AGE) ) && 6458 (flags & BCM_L2_REPLACE_NEW_TRUNK)) { 6459 return BCM_E_PARAM; 6460 } 6461 6462 if ((flags & BCM_L2_REPLACE_DELETE) && (flags & BCM_L2_REPLACE_MATCH_MAC) && 6463 ((flags & BCM_L2_REPLACE_MATCH_UC) || (flags & BCM_L2_REPLACE_MATCH_MC))) { 6464 return BCM_E_PARAM; 6465 } 6466 6467 if (flags & BCM_L2_REPLACE_AGE) { 6468 if (!soc_feature(unit, soc_feature_l2_bulk_control)) { 6469 return BCM_E_PARAM; 6470 } 6471 } 6472 6473 /* matching L2 address allowed to be NULL together with */ 6474 /* BCM_L2_REPLACE_DELETE flag indicating to delete all entries. */ 6475 if (NULL == match_addr) { 6476 if (!(flags & (BCM_L2_REPLACE_DELETE | BCM_L2_REPLACE_AGE) ) && 6477 !(flags & (BCM_L2_REPLACE_SRC_HIT_CLEAR | BCM_L2_REPLACE_DES_HIT_CLEAR))) { 6478 return BCM_E_PARAM; 6479 } 6480 flags &= ~(BCM_L2_REPLACE_MATCH_VLAN | BCM_L2_REPLACE_MATCH_MAC | 6481 BCM_L2_REPLACE_MATCH_DEST); 6482 6483 if (flags & BCM_L2_REPLACE_VLAN_AND_VPN_TYPE) { 6484 BCM_IF_ERROR_RETURN 6485 (_bcm_esw_l2_replace(unit, flags, 0, match_addr, new_module, 6486 new_port, new_trunk, NULL, NULL)); 6487 flags ^= BCM_L2_REPLACE_VPN_TYPE; 6488 } 6489 } 6490 /* coverity[var_deref_op : FALSE] */ 6491 /* coverity[var_deref_model : FALSE] */ 6492 return _bcm_esw_l2_replace(unit, flags, 0, match_addr, new_module, 6493 new_port, new_trunk, NULL, NULL); 6494 } 6495 6496 int 6497 bcm_esw_l2_matched_traverse(int unit, uint32 flags, bcm_l2_addr_t *match_addr, 6498 bcm_l2_traverse_cb trav_fn, void *user_data) 6499 { 6500 uint32 replace_flags, int_flags; 6501 6502 #if defined(BCM_TOMAHAWK3_SUPPORT) 6503 /* Added to handle SDK functions calling esw version, 6504 * instead of Tomahawk3's version 6505 */ 6506 if (SOC_IS_TOMAHAWK3(unit)) { 6507 return bcm_tomahawk3_l2_matched_traverse(unit, flags, match_addr, 6508 trav_fn, user_data); 6509 } 6510 #endif /* BCM_TOMAHAWK3_SUPPORT */ 6511 6512 if (soc_feature(unit, soc_feature_ism_memory)) { 6513 return _bcm_esw_l2_matched_traverse(unit, flags, match_addr, trav_fn, 6514 user_data); 6515 } 6516 6517 if (!trav_fn) { 6518 return BCM_E_PARAM; 6519 } 6520 6521 if (!match_addr) { 6522 return BCM_E_PARAM; 6523 } 6524 6525 replace_flags = 0; 6526 int_flags = _BCM_L2_REPLACE_INT_NO_ACTION; 6527 /* 6528 * 1/ If BCM_L2_TRAVERSE_MATCH_DYNAMIC and BCM_L2_TRAVERSE_MATCH_STATIC 6529 * are passed simultaneously to API bcm_l2_matched_traverse, 6530 * this API will match all entries. 6531 * 2/ If both BCM_L2_TRAVERSE_MATCH_DYNAMIC and BCM_L2_TRAVERSE_MATCH_STATIC 6532 * are not passed to API bcm_l2_matched_traverse, 6533 * this API will also match all entries as before. This is the legacy behavior. 6534 * 3/ If only BCM_L2_TRAVERSE_MATCH_DYNAMIC is passed to 6535 * API bcm_l2_matched_traverse, this API will only match dynamic entries. 6536 * 4/ If only BCM_L2_TRAVERSE_MATCH_STATIC is passed to 6537 * API bcm_l2_matched_traverse, this API will only match static entries. 6538 */ 6539 if (((flags & BCM_L2_TRAVERSE_MATCH_STATIC)?1:0) == 6540 ((flags & BCM_L2_TRAVERSE_MATCH_DYNAMIC)?1:0)) { 6541 /* BCM_L2_REPLACE_MATCH_STATIC means to replace static as well as 6542 * non-static entries */ 6543 replace_flags |= BCM_L2_REPLACE_MATCH_STATIC; 6544 } 6545 if (flags & BCM_L2_TRAVERSE_MATCH_MAC) { 6546 replace_flags |= BCM_L2_REPLACE_MATCH_MAC; 6547 } 6548 if (flags & BCM_L2_TRAVERSE_MATCH_VLAN) { 6549 replace_flags |= BCM_L2_REPLACE_MATCH_VLAN; 6550 } 6551 if (flags & BCM_L2_TRAVERSE_MATCH_DEST) { 6552 replace_flags |= BCM_L2_REPLACE_MATCH_DEST; 6553 } 6554 if (!(flags & BCM_L2_TRAVERSE_IGNORE_DISCARD_SRC)) { 6555 int_flags |= _BCM_L2_REPLACE_INT_MATCH_DISCARD_SRC; 6556 } 6557 if (!(flags & BCM_L2_TRAVERSE_IGNORE_DES_HIT)) { 6558 int_flags |= _BCM_L2_REPLACE_INT_MATCH_DES_HIT; 6559 } 6560 if (!(flags & BCM_L2_TRAVERSE_IGNORE_SRC_HIT)) { 6561 int_flags |= _BCM_L2_REPLACE_INT_MATCH_SRC_HIT; 6562 } 6563 if (flags & BCM_L2_TRAVERSE_MATCH_NATIVE) { 6564 int_flags |= _BCM_L2_REPLACE_INT_MATCH_NATIVE; 6565 } 6566 6567 if ((flags & BCM_L2_TRAVERSE_MATCH_STATIC) && 6568 !(flags & BCM_L2_TRAVERSE_MATCH_DYNAMIC)){ 6569 int_flags |= _BCM_L2_REPLACE_INT_MATCH_ONLY_STATIC; 6570 } 6571 6572 return _bcm_esw_l2_replace(unit, replace_flags, int_flags, match_addr, 0, 6573 0, 0, trav_fn, user_data); 6574 } 6575 6576 /* 6577 * Function: 6578 * bcm_esw_l2_station_add 6579 * Description: 6580 * Add an entry to L2 Station Table 6581 * Parameters: 6582 * unit - (IN) BCM device number 6583 * station_id - (IN/OUT) Station ID 6584 * station - (IN) Pointer to station address information 6585 * Return: 6586 * BCM_E_XXX 6587 */ 6588 int 6589 bcm_esw_l2_station_add(int unit, int *station_id, bcm_l2_station_t *station) 6590 { 6591 int rv = BCM_E_UNAVAIL; 6592 6593 #if defined(BCM_TOMAHAWK3_SUPPORT) 6594 /* Added to handle SDK functions calling esw version, 6595 * instead of Tomahawk3's version 6596 */ 6597 if (SOC_IS_TOMAHAWK3(unit)) { 6598 return bcm_tomahawk3_l2_station_add(unit, station_id, station); 6599 } 6600 #endif /* BCM_TOMAHAWK3_SUPPORT */ 6601 6602 6603 #if defined(BCM_TRIUMPH_SUPPORT) 6604 if (SOC_IS_TRIDENT(unit) || SOC_IS_TRIDENT2X(unit) || SOC_IS_TOMAHAWKX(unit) 6605 || SOC_IS_KATANAX(unit) || SOC_IS_TRIUMPH3(unit) || SOC_IS_TRIDENT3X(unit) 6606 || soc_feature(unit, soc_feature_gh2_my_station)) { 6607 rv = bcm_tr_l2_station_add(unit, station_id, station); 6608 } 6609 #endif 6610 6611 return (rv); 6612 } 6613 6614 /* 6615 * Function: 6616 * bcm_esw_l2_station_delete 6617 * Description: 6618 * Delete an entry from L2 Station Table 6619 * Parameters: 6620 * unit - (IN) BCM device number 6621 * station_id - (IN) Station ID 6622 * Return: 6623 * BCM_E_XXX 6624 */ 6625 int 6626 bcm_esw_l2_station_delete(int unit, int station_id) 6627 { 6628 6629 int rv = BCM_E_UNAVAIL; 6630 6631 #if defined(BCM_TOMAHAWK3_SUPPORT) 6632 /* Added to handle SDK functions calling esw version, 6633 * instead of Tomahawk3's version 6634 */ 6635 if (SOC_IS_TOMAHAWK3(unit)) { 6636 return bcm_tomahawk3_l2_station_delete(unit, station_id); 6637 } 6638 #endif /* BCM_TOMAHAWK3_SUPPORT */ 6639 6640 #if defined(BCM_TRIUMPH_SUPPORT) 6641 if (SOC_IS_TRIDENT(unit) || SOC_IS_TRIDENT2X(unit) || SOC_IS_TOMAHAWKX(unit) 6642 || SOC_IS_KATANAX(unit) || SOC_IS_TRIUMPH3(unit) || SOC_IS_TRIDENT3X(unit) 6643 || soc_feature(unit, soc_feature_gh2_my_station)) { 6644 rv = bcm_tr_l2_station_delete(unit, station_id); 6645 } 6646 #endif 6647 return (rv); 6648 } 6649 6650 /* 6651 * Function: 6652 * bcm_esw_l2_station_delete_all 6653 * Description: 6654 * Clear all L2 Station Table entries 6655 * Parameters: 6656 * unit - (IN) BCM device number 6657 * Return: 6658 * BCM_E_XXX 6659 */ 6660 int 6661 bcm_esw_l2_station_delete_all(int unit) 6662 { 6663 int rv = BCM_E_UNAVAIL; 6664 6665 #if defined(BCM_TOMAHAWK3_SUPPORT) 6666 /* Added to handle SDK functions calling esw version, 6667 * instead of Tomahawk3's version 6668 */ 6669 if (SOC_IS_TOMAHAWK3(unit)) { 6670 return bcm_tomahawk3_l2_station_delete_all(unit); 6671 } 6672 #endif /* BCM_TOMAHAWK3_SUPPORT */ 6673 6674 #if defined(BCM_TRIUMPH_SUPPORT) 6675 if (SOC_IS_TRIDENT(unit) || SOC_IS_TRIDENT2X(unit) || SOC_IS_TOMAHAWKX(unit) 6676 || SOC_IS_KATANAX(unit) || SOC_IS_TRIUMPH3(unit) || SOC_IS_TRIDENT3X(unit) 6677 || soc_feature(unit, soc_feature_gh2_my_station)) { 6678 rv = bcm_tr_l2_station_delete_all(unit); 6679 } 6680 #endif 6681 6682 return (rv); 6683 } 6684 6685 /* 6686 * Function: 6687 * bcm_esw_l2_station_get 6688 * Description: 6689 * Get L2 station entry detail from Station Table 6690 * Parameters: 6691 * unit - (IN) BCM device number 6692 * station_id - (IN) Station ID 6693 * station - (OUT) Pointer to station address information. 6694 * Return: 6695 * BCM_E_XXX 6696 */ 6697 int 6698 bcm_esw_l2_station_get(int unit, int station_id, bcm_l2_station_t *station) 6699 { 6700 int rv = BCM_E_UNAVAIL; 6701 6702 #if defined(BCM_TOMAHAWK3_SUPPORT) 6703 /* Added to handle SDK functions calling esw version, 6704 * instead of Tomahawk3's version 6705 */ 6706 if (SOC_IS_TOMAHAWK3(unit)) { 6707 return bcm_tomahawk3_l2_station_get(unit, station_id, station); 6708 } 6709 #endif /* BCM_TOMAHAWK3_SUPPORT */ 6710 6711 #if defined(BCM_TRIUMPH_SUPPORT) 6712 if (SOC_IS_TRIDENT(unit) || SOC_IS_TRIDENT2X(unit) || SOC_IS_TOMAHAWKX(unit) 6713 || SOC_IS_KATANAX(unit) || SOC_IS_TRIUMPH3(unit) || SOC_IS_TRIDENT3X(unit) 6714 || soc_feature(unit, soc_feature_gh2_my_station)) { 6715 rv = bcm_tr_l2_station_get(unit, station_id, station); 6716 } 6717 #endif 6718 6719 return (rv); 6720 } 6721 6722 /* 6723 * Function: 6724 * bcm_esw_l2_station_size_get 6725 * Description: 6726 * Get size of L2 Station Table 6727 * Parameters: 6728 * unit - (IN) BCM device number 6729 * size - (OUT) L2 Station table size 6730 * Return: 6731 * BCM_E_XXX 6732 */ 6733 int 6734 bcm_esw_l2_station_size_get(int unit, int *size) 6735 { 6736 int rv = BCM_E_UNAVAIL; 6737 6738 #if defined(BCM_TOMAHAWK3_SUPPORT) 6739 /* Added to handle SDK functions calling esw version, 6740 * instead of Tomahawk3's version 6741 */ 6742 if (SOC_IS_TOMAHAWK3(unit)) { 6743 return bcm_tomahawk3_l2_station_size_get(unit, size); 6744 } 6745 #endif /* BCM_TOMAHAWK3_SUPPORT */ 6746 6747 #if defined(BCM_TRIUMPH_SUPPORT) 6748 if (SOC_IS_TRIDENT(unit) || SOC_IS_TRIDENT2X(unit) || SOC_IS_TOMAHAWKX(unit) 6749 || SOC_IS_KATANAX(unit) || SOC_IS_TRIUMPH3(unit) || SOC_IS_TRIDENT3X(unit) 6750 || soc_feature(unit, soc_feature_gh2_my_station)) { 6751 rv = bcm_tr_l2_station_size_get(unit, size); 6752 } 6753 #endif 6754 6755 return (rv); 6756 } 6757 6758 /* 6759 * Function: 6760 * bcm_esw_l2_station_traverse 6761 * Description: 6762 * Traverse L2 station entry from Station Table 6763 * Parameters: 6764 * unit - (IN) BCM device number 6765 * trav_fn - (IN) Customer defines function is used to traverse 6766 * user_data - (IN) Pointer to information of customer. 6767 * Return: 6768 * BCM_E_XXX 6769 */ 6770 int 6771 bcm_esw_l2_station_traverse(int unit, bcm_l2_station_traverse_cb trav_fn, void *user_data) 6772 { 6773 int rv = BCM_E_UNAVAIL; 6774 6775 #if defined(BCM_TOMAHAWK3_SUPPORT) 6776 /* Added to handle SDK functions calling esw version, 6777 * instead of Tomahawk3's version 6778 */ 6779 if (SOC_IS_TOMAHAWK3(unit)) { 6780 return bcm_tomahawk3_l2_station_traverse(unit, trav_fn, user_data); 6781 } 6782 #endif /* BCM_TOMAHAWK3_SUPPORT */ 6783 6784 #if defined(BCM_TRIUMPH_SUPPORT) 6785 if (SOC_IS_TRIDENT(unit) || SOC_IS_TRIDENT2X(unit) || SOC_IS_TOMAHAWKX(unit) 6786 || SOC_IS_KATANAX(unit) || SOC_IS_TRIUMPH3(unit) || SOC_IS_TRIDENT3X(unit) 6787 || soc_feature(unit, soc_feature_gh2_my_station)) { 6788 rv = bcm_tr_l2_station_traverse(unit, trav_fn, user_data); 6789 } 6790 #endif 6791 6792 return (rv); 6793 } 6794 6795 int 6796 bcm_esw_l2_ring_replace( int unit, bcm_l2_ring_t *l2_ring) 6797 { 6798 int rv = BCM_E_UNAVAIL; 6799 6800 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_KATANA2_SUPPORT) 6801 if (soc_feature(unit, soc_feature_failover) && 6802 (SOC_IS_TRIUMPH3(unit) || SOC_IS_KATANA2(unit))) { 6803 return bcm_tr3_l2_ring_replace(unit, l2_ring); 6804 } 6805 #endif 6806 6807 return rv; 6808 } 6809 6810 /* 6811 * Function: 6812 * bcm_esw_l2_mac_port_create 6813 * Description: 6814 * Create a MAC port. 6815 * Parameters: 6816 * unit - (IN) BCM device number 6817 * mac_port - (IN/OUT) MAC port info 6818 * Return: 6819 * BCM_E_XXX 6820 */ 6821 int 6822 bcm_esw_l2_mac_port_create(int unit, bcm_l2_mac_port_t *mac_port) 6823 { 6824 return BCM_E_UNAVAIL; 6825 } 6826 6827 /* 6828 * Function: 6829 * bcm_esw_l2_mac_port_destroy 6830 * Description: 6831 * Destroy a MAC port. 6832 * Parameters: 6833 * unit - (IN) BCM device number 6834 * mac_port_id - (IN) MAC port GPORT ID 6835 * Return: 6836 * BCM_E_XXX 6837 */ 6838 int 6839 bcm_esw_l2_mac_port_destroy(int unit, bcm_gport_t mac_port_id) 6840 { 6841 return BCM_E_UNAVAIL; 6842 } 6843 6844 /* 6845 * Function: 6846 * bcm_esw_l2_mac_port_destroy_all 6847 * Description: 6848 * Destroy all MAC ports. 6849 * Parameters: 6850 * unit - (IN) BCM device number 6851 * Return: 6852 * BCM_E_XXX 6853 */ 6854 int 6855 bcm_esw_l2_mac_port_destroy_all(int unit) 6856 { 6857 return BCM_E_UNAVAIL; 6858 } 6859 6860 /* 6861 * Function: 6862 * bcm_esw_l2_mac_port_get 6863 * Description: 6864 * Get info about a MAC port. 6865 * Parameters: 6866 * unit - (IN) BCM device number 6867 * mac_port - (IN/OUT) MAC port info 6868 * Return: 6869 * BCM_E_XXX 6870 */ 6871 int 6872 bcm_esw_l2_mac_port_get(int unit, bcm_l2_mac_port_t *mac_port) 6873 { 6874 return BCM_E_UNAVAIL; 6875 } 6876 6877 /* 6878 * Function: 6879 * bcm_esw_l2_mac_port_traverse 6880 * Description: 6881 * Traverse MAC ports. 6882 * Parameters: 6883 * unit - (IN) BCM device number 6884 * cb - (IN) Callback 6885 * user_data - (IN) User data 6886 * Return: 6887 * BCM_E_XXX 6888 */ 6889 int 6890 bcm_esw_l2_mac_port_traverse(int unit, bcm_l2_mac_port_traverse_cb cb, 6891 void *user_data) 6892 { 6893 return BCM_E_UNAVAIL; 6894 } 6895 6896 #ifndef BCM_SW_STATE_DUMP_DISABLE 6897 6898 /* 6899 * Function: 6900 * _bcm_l2_sw_dump 6901 * Purpose: 6902 * Displays L2 information maintained by software. 6903 * Parameters: 6904 * unit - Device unit number 6905 * Returns: 6906 * None 6907 * Note: 6908 * The l2_data structure maintains registration of callbacks routines. 6909 * Dump of l2_data is skipped. 6910 */ 6911 void 6912 _bcm_l2_sw_dump(int unit) 6913 { 6914 6915 LOG_CLI((BSL_META_U(unit, 6916 "\nSW Information L2 - Unit %d\n"), unit)); 6917 LOG_CLI((BSL_META_U(unit, 6918 " Initialized : %d\n"), _l2_init[unit])); 6919 6920 #if defined(BCM_TRX_SUPPORT) 6921 if (SOC_IS_TRX(unit)) { 6922 _bcm_tr_l2_sw_dump(unit); 6923 } 6924 #endif 6925 6926 #if defined(BCM_FIREBOLT_SUPPORT) 6927 if (SOC_IS_FB_FX_HX(unit)) { 6928 _bcm_fb_l2_sw_dump(unit); 6929 } 6930 #endif 6931 return; 6932 } 6933 #endif /* BCM_SW_STATE_DUMP_DISABLE */ 6934 6935 STATIC void 6936 _bcm_esw_l2_vlan_gport_free(int unit, _bcm_l2_del_vlan_port_pair_t *l2_pair) 6937 { 6938 int i; 6939 6940 if (l2_pair) { 6941 if (l2_pair->mod_pair_arr) { 6942 sal_free(l2_pair->mod_pair_arr); 6943 l2_pair->mod_pair_arr = NULL; 6944 } 6945 6946 if (l2_pair->unit_pair_arr) { 6947 for (i = 0; i < BCM_VLAN_MAX + 2; i++) { 6948 sal_free(l2_pair->unit_pair_arr->tbm[i]); 6949 l2_pair->unit_pair_arr->tbm[i] = NULL; 6950 } 6951 sal_free(l2_pair->unit_pair_arr); 6952 l2_pair->unit_pair_arr = NULL; 6953 } 6954 6955 if (soc_feature(unit, soc_feature_vlan_vp)) { 6956 if (l2_pair->vp_pair_arr) { 6957 for (i = 0; i < BCM_VLAN_MAX + 2; i++) { 6958 sal_free(l2_pair->vp_pair_arr->vpbm[i]); 6959 l2_pair->vp_pair_arr->vpbm[i] = NULL; 6960 } 6961 sal_free(l2_pair->vp_pair_arr); 6962 l2_pair->vp_pair_arr = NULL; 6963 } 6964 } 6965 6966 if (l2_pair->vfi_pair_arr) { 6967 for (i = 0; i < soc_mem_index_count(unit,VFIm); i++) { 6968 if (l2_pair->vfi_pair_arr[i]) { 6969 sal_free(l2_pair->vfi_pair_arr[i]); 6970 l2_pair->vfi_pair_arr[i] = NULL; 6971 } 6972 } 6973 sal_free(l2_pair->vfi_pair_arr); 6974 l2_pair->vfi_pair_arr = NULL; 6975 } 6976 6977 if (l2_pair->del_by_vfi_vec) { 6978 sal_free(l2_pair->del_by_vfi_vec); 6979 l2_pair->del_by_vfi_vec = NULL; 6980 } 6981 } 6982 return; 6983 } 6984 6985 #if defined(BCM_TRX_SUPPORT) && defined(INCLUDE_L3) 6986 /* 6987 * Function: 6988 * _bcm_is_gport_valid_vp_type 6989 * Purpose: 6990 * Returns TRUE if supplied gport is a valid VP type 6991 * Parameters: 6992 * gport_type - (IN) Gport type to be validated 6993 * Returns: 6994 * TRUE if 'gport' is a valid VP type, FALSE otherwise 6995 */ 6996 6997 int _bcm_is_gport_valid_vp_type(int gport_type) 6998 { 6999 switch(gport_type) { 7000 case BCM_GPORT_MPLS_PORT: 7001 case BCM_GPORT_SUBPORT_GROUP: 7002 case BCM_GPORT_SUBPORT_PORT: 7003 case BCM_GPORT_MIM_PORT: 7004 case BCM_GPORT_VLAN_PORT: 7005 case BCM_GPORT_TRILL_PORT: 7006 case BCM_GPORT_NIV_PORT: 7007 case BCM_GPORT_L2GRE_PORT: 7008 case BCM_GPORT_VXLAN_PORT: 7009 case BCM_GPORT_EXTENDER_PORT: 7010 return 1; 7011 default: 7012 return 0; 7013 } 7014 } 7015 7016 /* 7017 * Function: 7018 * _bcm_is_gport_vp_in_use 7019 * Purpose: 7020 * Returns TRUE if supplied gport-VP type is in use 7021 * Parameters: 7022 * unit - (IN) Unit number 7023 * gport - (IN) Gport to check if in use 7024 * Returns: 7025 * TRUE if 'gport-vp' is a valid and in use, FALSE otherwise. 7026 */ 7027 int _bcm_is_gport_vp_in_use(int unit, int gport) 7028 { 7029 int vp; 7030 7031 /* Extract the vp */ 7032 if (BCM_GPORT_IS_MPLS_PORT(gport)) { 7033 vp = _SHR_GPORT_MPLS_PORT_ID_GET(gport); 7034 return _bcm_vp_used_get(unit, vp, _bcmVpTypeMpls); 7035 } else if (BCM_GPORT_IS_MIM_PORT(gport)) { 7036 vp = _SHR_GPORT_MIM_PORT_ID_GET(gport); 7037 return _bcm_vp_used_get(unit, vp, _bcmVpTypeMim); 7038 } else if (BCM_GPORT_IS_L2GRE_PORT(gport)) { 7039 vp = _SHR_GPORT_L2GRE_PORT_ID_GET(gport); 7040 return _bcm_vp_used_get(unit, vp, _bcmVpTypeL2Gre); 7041 } else if (BCM_GPORT_IS_SUBPORT_GROUP(gport)){ 7042 vp = _SHR_GPORT_SUBPORT_GROUP_GET(gport); 7043 return _bcm_vp_used_get(unit, vp, _bcmVpTypeSubport); 7044 } else if (BCM_GPORT_IS_WLAN_PORT(gport)) { 7045 vp = _SHR_GPORT_WLAN_PORT_ID_GET(gport); 7046 return _bcm_vp_used_get(unit, vp, _bcmVpTypeWlan); 7047 } else if (BCM_GPORT_IS_VLAN_PORT(gport)) { 7048 vp = _SHR_GPORT_VLAN_PORT_ID_GET(gport); 7049 return _bcm_vp_used_get(unit, vp, _bcmVpTypeVlan); 7050 } else if (BCM_GPORT_IS_TRILL_PORT(gport)) { 7051 vp = _SHR_GPORT_TRILL_PORT_ID_GET(gport); 7052 return _bcm_vp_used_get(unit, vp, _bcmVpTypeTrill); 7053 } else if (BCM_GPORT_IS_NIV_PORT(gport)) { 7054 vp = _SHR_GPORT_NIV_PORT_ID_GET(gport); 7055 return _bcm_vp_used_get(unit, vp, _bcmVpTypeNiv); 7056 } else if (BCM_GPORT_IS_EXTENDER_PORT(gport)) { 7057 vp = _SHR_GPORT_EXTENDER_PORT_ID_GET(gport); 7058 return _bcm_vp_used_get(unit, vp, _bcmVpTypeExtender); 7059 } else if (BCM_GPORT_IS_VXLAN_PORT(gport)) { 7060 vp = _SHR_GPORT_VXLAN_PORT_ID_GET(gport); 7061 return _bcm_vp_used_get(unit, vp, _bcmVpTypeVxlan); 7062 } else { 7063 return 0; 7064 } 7065 } 7066 7067 #endif /* defined(BCM_TRX_SUPPORT) && defined(INCLUDE_L3) */ 7068 7069 /* 7070 * Function: 7071 * _bcm_esw_l2_vlan_gport_matched_delete 7072 * Purpose: 7073 * L2 Traverse callback function to Purge L2 entry belongs 7074 * to set of (vlan,port) tuple. 7075 * Parameters: 7076 * unit - (IN) Device unit number 7077 * info - (IN) Reference to L2 entry, delete on match 7078 * user_data - (IN) User specified cookie 7079 * Returns: 7080 * BCM_E_XXX 7081 * Note: 7082 * If one of the elements of the (vlan,gport) pair is invalid 7083 * (if vlan value is BCM_VLAN_INVALID or port value is BCM_GPORT_INVALID), 7084 * it is a wildcard. 7085 */ 7086 7087 7088 int 7089 _bcm_esw_l2_vlan_gport_matched_delete(int unit, bcm_l2_addr_t *info, 7090 void *user_data) 7091 { 7092 int rv = BCM_E_NONE; 7093 int entry_found=FALSE; 7094 _bcm_l2_del_vlan_port_pair_t *l2_pair; 7095 int useGport; 7096 #if defined(BCM_TRX_SUPPORT) && defined(INCLUDE_L3) 7097 int gport_type; 7098 bcm_port_t local_port; 7099 #endif /* defined(BCM_TRX_SUPPORT) && defined(INCLUDE_L3) */ 7100 int vfi_num; 7101 7102 l2_pair = (void *)user_data; 7103 7104 if (l2_pair == NULL) { 7105 return BCM_E_NOT_FOUND; 7106 } 7107 7108 if ((info->flags & BCM_L2_STATIC) && 7109 (!(l2_pair->replace_flags & BCM_L2_REPLACE_MATCH_STATIC))) { 7110 _l2_dbg_unmatched_entries[unit]++; 7111 return BCM_E_NONE; 7112 } 7113 7114 if ((info->flags & BCM_L2_PENDING) && 7115 (!(l2_pair->replace_flags & BCM_L2_REPLACE_PENDING))) { 7116 _l2_dbg_unmatched_entries[unit]++; 7117 return BCM_E_NONE; 7118 } 7119 7120 BCM_IF_ERROR_RETURN 7121 (bcm_esw_switch_control_get(unit, bcmSwitchUseGport, &useGport)); 7122 7123 #if defined(BCM_TRX_SUPPORT) && defined(INCLUDE_L3) 7124 /* Extract the gport_type */ 7125 gport_type = (((info->port) >> _SHR_GPORT_TYPE_SHIFT) & _SHR_GPORT_TYPE_MASK); 7126 if (_bcm_is_gport_valid_vp_type(gport_type)) { 7127 BCM_IF_ERROR_RETURN( 7128 bcm_esw_port_local_get(unit, info->port, &local_port)); 7129 } 7130 #endif /* defined(BCM_TRX_SUPPORT) && defined(INCLUDE_L3) */ 7131 if (_BCM_VPN_VFI_IS_SET(info->vid)) { 7132 _BCM_VPN_GET(vfi_num, _BCM_VPN_TYPE_VFI, info->vid); 7133 if (l2_pair->del_by_vfi_vec && 7134 (SHR_BITGET(l2_pair->del_by_vfi_vec, vfi_num))) { 7135 entry_found = TRUE; 7136 } 7137 #if defined(BCM_TRX_SUPPORT) && defined(INCLUDE_L3) 7138 else if (_bcm_is_gport_valid_vp_type(gport_type)) { 7139 if (l2_pair->vfi_pair_arr && 7140 (vfi_num < soc_mem_index_count(unit,VFIm)) && 7141 l2_pair->vfi_pair_arr[vfi_num]) { 7142 if (SHR_BITGET(l2_pair->vfi_pair_arr[vfi_num], local_port)) { 7143 entry_found = TRUE; 7144 } 7145 } 7146 } 7147 #endif /* defined(BCM_TRX_SUPPORT) && defined(INCLUDE_L3) */ 7148 7149 } else if (BCM_VLAN_VEC_GET(l2_pair->del_by_vlan_vec, info->vid)) { 7150 /* Delete by vlan operation */ 7151 entry_found = TRUE; 7152 } else if ((useGport) && (BCM_GPORT_IS_MODPORT(info->port)) && 7153 BCM_PBMP_MEMBER (l2_pair->mod_pair_arr[info->modid].pbm[BCM_VLAN_MAX+1], 7154 _SHR_GPORT_LOCAL_GET(info->port))) { 7155 /* Delete by (mod, gport) operation */ 7156 entry_found = TRUE; 7157 } else if ((!useGport) && (!BCM_GPORT_IS_SET(info->port)) && 7158 BCM_PBMP_MEMBER (l2_pair->mod_pair_arr[info->modid].pbm[BCM_VLAN_MAX+1], 7159 info->port)) { 7160 /* Delete by (mod, port) operation */ 7161 entry_found = TRUE; 7162 } else if ((useGport) && BCM_GPORT_IS_MODPORT(info->port) && 7163 BCM_PBMP_MEMBER(l2_pair->mod_pair_arr[info->modid].pbm[info->vid], 7164 _SHR_GPORT_LOCAL_GET(info->port))) { 7165 /* Delete by (vlan, (mod, gport)) operation */ 7166 entry_found = TRUE; 7167 } else if (((!useGport) && (!BCM_GPORT_IS_SET(info->port)) && 7168 BCM_PBMP_MEMBER(l2_pair->mod_pair_arr[info->modid].pbm[info->vid], 7169 info->port))) { 7170 /* Delete by (vlan, (mod, port)) operation */ 7171 entry_found = TRUE; 7172 } else if (info->flags & BCM_L2_TRUNK_MEMBER) { 7173 if (SHR_BITGET(l2_pair->unit_pair_arr[0].tbm[BCM_VLAN_MAX+1], info->tgid)) { 7174 /* Delete by (tid) operation */ 7175 entry_found = TRUE; 7176 } else if (SHR_BITGET(l2_pair->unit_pair_arr[0].tbm[info->vid], info->tgid)) { 7177 /* Delete by (vlan, tid) operation */ 7178 entry_found = TRUE; 7179 } 7180 } else { 7181 7182 #if defined(BCM_TRX_SUPPORT) && defined(INCLUDE_L3) 7183 if (_bcm_is_gport_valid_vp_type(gport_type)) { 7184 if (SHR_BITGET(l2_pair->vp_pair_arr[0].vpbm[BCM_VLAN_MAX+1], 7185 local_port)) { 7186 /* Delete by (vp) operation */ 7187 entry_found = TRUE; 7188 } else if (SHR_BITGET(l2_pair->vp_pair_arr[0].vpbm[info->vid], 7189 local_port)) { 7190 /* Delete by (vlan, vp) operation */ 7191 entry_found = TRUE; 7192 } 7193 } 7194 #endif /* defined(BCM_TRX_SUPPORT) && defined(INCLUDE_L3) */ 7195 } 7196 7197 if (entry_found == TRUE) { 7198 /* Entry found - Delete the entry */ 7199 #if defined(BCM_TRIUMPH3_SUPPORT) 7200 if (soc_feature(unit, soc_feature_ism_memory)) { 7201 rv = bcm_tr3_l2_addr_delete(unit, info->mac, info->vid); 7202 } else 7203 #endif /* BCM_TRIUMPH3_SUPPORT */ 7204 rv = mbcm_driver[unit]->mbcm_l2_addr_delete(unit, info->mac, 7205 info->vid); 7206 if (rv == BCM_E_NONE) { 7207 _l2_dbg_matched_entries[unit]++; 7208 } 7209 } else { 7210 _l2_dbg_unmatched_entries[unit]++; 7211 } 7212 7213 return rv; 7214 } 7215 7216 /* 7217 * Function: 7218 * bcm_esw_l2_addr_delete_by_vlan_gport_multi 7219 * Purpose: 7220 * Purge L2 entries belong to set of (vlan,port) tuple. 7221 * Parameters: 7222 * unit - (IN) Device unit number 7223 * flags - (IN) Only accept BCM_L2_REPLACE_DELETE, BCM_L2_REPLACE_NO_CALLBACKS. 7224 * num_pairs - (IN) Size of (vlan,port) pair array. 7225 * vlan - (IN) Reference to array of VLAN list. 7226 * gport - (IN) Reference to array of gport list. 7227 * Returns: 7228 * BCM_E_XXX 7229 * Note: 7230 * If one of the elements of the (vlan,gport) pair is invalid 7231 * (if vlan value is BCM_VLAN_INVALID or port value is BCM_GPORT_INVALID), 7232 * it is a wildcard. 7233 * Entries are removed only if BCM_L2_REPLACE_DELETE flag is used. With 7234 * flag BCM_L2_REPLACE_NO_CALLBACKS, l2 aging and learning are disabled 7235 * during this operation. 7236 */ 7237 7238 int 7239 bcm_esw_l2_addr_delete_by_vlan_gport_multi(int unit, uint32 flags, 7240 int num_pairs, bcm_vlan_t *vlan, 7241 bcm_gport_t *gport) 7242 { 7243 sal_usecs_t interval=0; 7244 bcm_module_t mod_in, modid = 0; 7245 bcm_port_t port_in, port = 0; 7246 bcm_trunk_t trunk_id = 0; 7247 int id = 0, ct, i; 7248 int rv2 = 0, rv = BCM_E_UNAVAIL; 7249 soc_control_t *soc = SOC_CONTROL(unit); 7250 uint32 max_modid; 7251 _bcm_l2_vlan_port_pair_t *mod_l2_pair_arr = NULL; 7252 _bcm_l2_vlan_trunk_pair_t *l2_trunk_pair_arr = NULL; 7253 _bcm_l2_vlan_vp_pair_t *l2_vp_pair_arr = NULL; 7254 _bcm_l2_del_vlan_port_pair_t l2_pair; 7255 int alloc_size; 7256 int fifo_modified = FALSE; 7257 int vfi_num; 7258 int vfi_max; 7259 uint32 rval = 0; 7260 uint32 l2_delete = 0; 7261 7262 #if defined(BCM_TOMAHAWK3_SUPPORT) 7263 /* Added to handle SDK functions calling esw version, 7264 * instead of Tomahawk3's version 7265 */ 7266 if (SOC_IS_TOMAHAWK3(unit)) { 7267 return bcm_tomahawk3_l2_addr_delete_by_vlan_gport_multi(unit, flags, 7268 num_pairs, vlan, 7269 gport); 7270 } 7271 #endif /* BCM_TOMAHAWK3_SUPPORT */ 7272 7273 /* Validate the input parameters */ 7274 if (vlan == NULL || gport == NULL || num_pairs == 0) { 7275 return BCM_E_PARAM; 7276 } 7277 7278 /* Validate flag parameter, no action will be proceeded with extra flags */ 7279 if ((flags & ~(BCM_L2_REPLACE_DELETE | BCM_L2_REPLACE_NO_CALLBACKS | 7280 BCM_L2_REPLACE_MATCH_STATIC | 7281 BCM_L2_REPLACE_PENDING )) != 0) { 7282 return BCM_E_NONE; 7283 } 7284 7285 if (SOC_MEM_IS_VALID(unit, VFIm)) { 7286 vfi_max = soc_mem_index_count(unit,VFIm); 7287 } else { 7288 vfi_max = 0; 7289 } 7290 sal_memset(&l2_pair, 0x0, sizeof(l2_pair)); 7291 7292 /* Prepare (vlan, (mod, port)) pair */ 7293 max_modid = SOC_MODID_MAX(unit) + 1; 7294 alloc_size = sizeof(_bcm_l2_vlan_port_pair_t) * max_modid; 7295 mod_l2_pair_arr = sal_alloc(alloc_size, "l2_addr_vlan_gport_multi_delete"); 7296 if (mod_l2_pair_arr == NULL) { 7297 return BCM_E_MEMORY; 7298 } 7299 sal_memset(mod_l2_pair_arr, 0x0, alloc_size); 7300 7301 /* Prepare (vlan, tid) pair */ 7302 l2_pair.mod_pair_arr = mod_l2_pair_arr; 7303 alloc_size = sizeof(_bcm_l2_vlan_trunk_pair_t); 7304 l2_trunk_pair_arr = sal_alloc(alloc_size, "l2_addr_vlan_gport_multi_delete"); 7305 if (l2_trunk_pair_arr == NULL) { 7306 rv = BCM_E_MEMORY; 7307 goto _free_exit; 7308 } 7309 sal_memset(l2_trunk_pair_arr, 0x0, alloc_size); 7310 l2_pair.unit_pair_arr = l2_trunk_pair_arr; 7311 7312 alloc_size = SHR_BITALLOCSIZE(_bcm_esw_trunk_group_num(unit)); 7313 for (i = 0; i < BCM_VLAN_MAX + 2; i++) { 7314 l2_trunk_pair_arr->tbm[i] = sal_alloc(alloc_size, \ 7315 "l2_addr_vlan_gport_multi_delete"); 7316 if (l2_trunk_pair_arr->tbm[i] == NULL) { 7317 rv = BCM_E_MEMORY; 7318 goto _free_exit; 7319 } 7320 sal_memset(l2_trunk_pair_arr->tbm[i], 0x0, alloc_size); 7321 } 7322 7323 if (soc_feature(unit, soc_feature_vlan_vp)) { 7324 /* Prepare (vlan, vp) pair */ 7325 alloc_size = sizeof(_bcm_l2_vlan_vp_pair_t); 7326 l2_vp_pair_arr = sal_alloc(alloc_size, "l2_addr_vlan_gport_multi_delete"); 7327 if (l2_vp_pair_arr == NULL) { 7328 rv = BCM_E_MEMORY; 7329 goto _free_exit; 7330 } 7331 sal_memset(l2_vp_pair_arr, 0x0, alloc_size); 7332 l2_pair.vp_pair_arr = l2_vp_pair_arr; 7333 7334 alloc_size = SHR_BITALLOCSIZE(soc_mem_index_count(unit, SOURCE_VPm)); 7335 for (i = 0; i < BCM_VLAN_MAX + 2; i++) { 7336 l2_vp_pair_arr->vpbm[i] = sal_alloc(alloc_size, \ 7337 "l2_addr_vlan_gport_multi_delete"); 7338 if (l2_vp_pair_arr->vpbm[i] == NULL) { 7339 rv = BCM_E_MEMORY; 7340 goto _free_exit; 7341 } 7342 sal_memset(l2_vp_pair_arr->vpbm[i], 0x0, alloc_size); 7343 } 7344 } 7345 7346 if (SOC_MEM_IS_VALID(unit, VFIm) && 7347 SOC_MEM_IS_VALID(unit,SOURCE_VPm)) { 7348 alloc_size = sizeof(SHR_BITDCL *) * vfi_max; 7349 l2_pair.vfi_pair_arr = sal_alloc(alloc_size, 7350 "l2_addr_vlan_gport_multi_delete:vfi_pair_arr"); 7351 if (l2_pair.vfi_pair_arr == NULL) { 7352 rv = BCM_E_MEMORY; 7353 goto _free_exit; 7354 } 7355 7356 sal_memset(l2_pair.vfi_pair_arr, 0x0, alloc_size); 7357 7358 alloc_size = SHR_BITALLOCSIZE(vfi_max); 7359 l2_pair.del_by_vfi_vec = sal_alloc(alloc_size, 7360 "l2_addr_vlan_gport_multi_delete:del_by_vfi_vec"); 7361 if (l2_pair.del_by_vfi_vec == NULL) { 7362 rv = BCM_E_MEMORY; 7363 goto _free_exit; 7364 } 7365 sal_memset(l2_pair.del_by_vfi_vec, 0x0, alloc_size); 7366 7367 } 7368 7369 /* Validate vlan & gport */ 7370 for (ct = 0; ct < num_pairs; ct++) { 7371 if (vlan[ct] == BCM_VLAN_INVALID && 7372 gport[ct] == BCM_GPORT_INVALID) { 7373 rv = BCM_E_PARAM; 7374 goto _free_exit; 7375 } 7376 7377 if (vlan[ct] != BCM_VLAN_INVALID) { 7378 if ((vlan[ct] > BCM_VLAN_MAX) && 7379 (!_BCM_VPN_VFI_IS_SET(vlan[ct]))) { 7380 rv = BCM_E_PARAM; 7381 goto _free_exit; 7382 } 7383 } 7384 7385 if (_BCM_VPN_VFI_IS_SET(vlan[ct])) { 7386 if (gport[ct] != BCM_GPORT_INVALID) { 7387 #if defined(BCM_TRX_SUPPORT) && defined(INCLUDE_L3) 7388 if(!(_bcm_is_gport_vp_in_use(unit, gport[ct]))) { 7389 rv = BCM_E_PARAM; 7390 goto _free_exit; 7391 } 7392 #endif /* defined(BCM_TRX_SUPPORT) && defined(INCLUDE_L3) */ 7393 } 7394 } 7395 if (gport[ct] != BCM_GPORT_INVALID) { 7396 7397 if (BCM_GPORT_IS_MODPORT(gport[ct])) { 7398 mod_in = BCM_GPORT_MODPORT_MODID_GET(gport[ct]); 7399 port_in = BCM_GPORT_MODPORT_PORT_GET(gport[ct]); 7400 rv = _bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, 7401 mod_in, port_in, &modid, &port); 7402 if (BCM_FAILURE(rv)) { 7403 goto _free_exit; 7404 } 7405 } else { 7406 rv = _bcm_esw_gport_resolve(unit, gport[ct], 7407 &modid, &port, &trunk_id, &id); 7408 if (BCM_FAILURE(rv)) { 7409 goto _free_exit; 7410 } 7411 7412 if (BCM_GPORT_IS_TRUNK(gport[ct])) { 7413 rv = _bcm_trunk_id_validate(unit, trunk_id); 7414 if (BCM_FAILURE(rv)) { 7415 rv = BCM_E_PARAM; 7416 goto _free_exit; 7417 } 7418 } else { 7419 /* If the VP type is not in use, return error */ 7420 #if defined(BCM_TRX_SUPPORT) && defined(INCLUDE_L3) 7421 if(!(_bcm_is_gport_vp_in_use(unit, gport[ct]))) { 7422 rv = BCM_E_PARAM; 7423 goto _free_exit; 7424 } 7425 #else 7426 rv = BCM_E_PARAM; 7427 goto _free_exit; 7428 #endif /* defined(BCM_TRX_SUPPORT) && defined(INCLUDE_L3) */ 7429 } 7430 } 7431 } 7432 7433 if (vlan[ct] == BCM_VLAN_INVALID) { 7434 if (BCM_GPORT_IS_TRUNK(gport[ct])) { 7435 SHR_BITSET(l2_pair.unit_pair_arr[0].tbm[BCM_VLAN_MAX+1], \ 7436 trunk_id); 7437 } else if (BCM_GPORT_IS_MODPORT(gport[ct])){ 7438 BCM_PBMP_PORT_ADD( \ 7439 l2_pair.mod_pair_arr[modid].pbm[BCM_VLAN_MAX+1], port); 7440 } else { 7441 if (soc_feature(unit, soc_feature_vlan_vp)) { 7442 /* VP case, set relevant bit */ 7443 SHR_BITSET(l2_pair.vp_pair_arr[0].vpbm[BCM_VLAN_MAX+1], \ 7444 id); 7445 } 7446 } 7447 } else if (gport[ct] == BCM_GPORT_INVALID) { 7448 if (_BCM_VPN_VFI_IS_SET(vlan[ct])) { 7449 _BCM_VPN_GET(vfi_num, _BCM_VPN_TYPE_VFI, vlan[ct]); 7450 if (l2_pair.del_by_vfi_vec == NULL || 7451 vfi_num >= vfi_max) { 7452 rv = BCM_E_PARAM; 7453 goto _free_exit; 7454 } 7455 SHR_BITSET(l2_pair.del_by_vfi_vec,vfi_num); 7456 } else { 7457 BCM_VLAN_VEC_SET(l2_pair.del_by_vlan_vec, vlan[ct]); 7458 } 7459 } else { 7460 if (BCM_GPORT_IS_TRUNK(gport[ct])) { 7461 SHR_BITSET(l2_pair.unit_pair_arr[0].tbm[vlan[ct]], \ 7462 trunk_id); 7463 } else if (BCM_GPORT_IS_MODPORT(gport[ct])){ 7464 BCM_PBMP_PORT_ADD(l2_pair.mod_pair_arr[modid].pbm[vlan[ct]], \ 7465 port); 7466 } else { 7467 if (_BCM_VPN_VFI_IS_SET(vlan[ct])) { 7468 _BCM_VPN_GET(vfi_num, _BCM_VPN_TYPE_VFI, vlan[ct]); 7469 if (l2_pair.vfi_pair_arr == NULL || 7470 vfi_num >= vfi_max) { 7471 rv = BCM_E_PARAM; 7472 goto _free_exit; 7473 } 7474 if (l2_pair.vfi_pair_arr[vfi_num] == NULL) { 7475 alloc_size = SHR_BITALLOCSIZE(soc_mem_index_count(unit,SOURCE_VPm)); 7476 l2_pair.vfi_pair_arr[vfi_num] = sal_alloc(alloc_size, 7477 "l2_addr_vlan_gport_multi_delete"); 7478 if (l2_pair.vfi_pair_arr[vfi_num] == NULL) { 7479 rv = BCM_E_MEMORY; 7480 goto _free_exit; 7481 } 7482 sal_memset(l2_pair.vfi_pair_arr[vfi_num], 0x0, alloc_size); 7483 } 7484 SHR_BITSET(l2_pair.vfi_pair_arr[vfi_num], id); 7485 7486 } else if (soc_feature(unit, soc_feature_vlan_vp)) { 7487 /* Vlan VP case, set relevant bit */ 7488 SHR_BITSET(l2_pair.vp_pair_arr[0].vpbm[vlan[ct]], \ 7489 id); 7490 } 7491 } 7492 } 7493 } 7494 7495 if (flags & BCM_L2_REPLACE_DELETE) { 7496 _l2_dbg_matched_entries[unit] = 0; 7497 _l2_dbg_unmatched_entries[unit] = 0; 7498 7499 if (flags & BCM_L2_REPLACE_NO_CALLBACKS) { 7500 interval = soc->l2x_interval; 7501 rv = bcm_esw_l2_addr_freeze(unit); 7502 if (BCM_FAILURE(rv)) { 7503 goto _free_exit; 7504 } 7505 7506 if (SOC_CONTROL(unit)->l2x_mode == L2MODE_FIFO && 7507 soc_l2mod_running(unit, NULL, NULL)) { 7508 if (SOC_REG_IS_VALID(unit, L2_MOD_FIFO_ENABLEr)) { 7509 rv2 = READ_L2_MOD_FIFO_ENABLEr(unit, &rval); 7510 if (rv2 < 0) { 7511 goto _free_exit; 7512 } 7513 l2_delete = soc_reg_field_get(unit, L2_MOD_FIFO_ENABLEr, rval, 7514 L2_DELETEf); 7515 rv2 = soc_reg_field32_modify(unit, L2_MOD_FIFO_ENABLEr, 7516 REG_PORT_ANY, L2_DELETEf, 0); 7517 } else { 7518 if (soc_reg_field_valid(unit, AUX_ARB_CONTROLr, 7519 L2_MOD_FIFO_ENABLE_L2_DELETEf)) { 7520 rv2 = READ_AUX_ARB_CONTROLr(unit, &rval); 7521 if (rv2 < 0) { 7522 goto _free_exit; 7523 } 7524 l2_delete = soc_reg_field_get(unit, AUX_ARB_CONTROLr, rval, 7525 L2_MOD_FIFO_ENABLE_L2_DELETEf); 7526 rv2 = soc_reg_field32_modify(unit, AUX_ARB_CONTROLr, 7527 REG_PORT_ANY, L2_MOD_FIFO_ENABLE_L2_DELETEf, 0); 7528 } 7529 } 7530 7531 if (rv2 < 0) { 7532 goto _free_exit; 7533 } 7534 fifo_modified = TRUE; 7535 } else if (SOC_CONTROL(unit)->l2x_mode != L2MODE_FIFO) { 7536 rv2 = soc_l2x_stop(unit); 7537 if (rv2 < 0) { 7538 goto _free_exit; 7539 } 7540 } 7541 7542 LOG_INFO(BSL_LS_BCM_ARL, 7543 (BSL_META_U(unit, "L2 Freeze and stop L2 thread\n"))); 7544 } 7545 7546 l2_pair.replace_flags = flags; 7547 rv = bcm_esw_l2_traverse(unit, _bcm_esw_l2_vlan_gport_matched_delete, 7548 &l2_pair); 7549 if (rv == BCM_E_NONE) { 7550 LOG_INFO(BSL_LS_BCM_ARL, 7551 (BSL_META_U(unit, 7552 "Total number of L2 Entries: %d [Deleted:%d Left:%d]\n\r"), 7553 _l2_dbg_matched_entries[unit] + _l2_dbg_unmatched_entries[unit], 7554 _l2_dbg_matched_entries[unit], _l2_dbg_unmatched_entries[unit])); 7555 } 7556 7557 if (flags & BCM_L2_REPLACE_NO_CALLBACKS) { 7558 LOG_INFO(BSL_LS_BCM_ARL, 7559 (BSL_META_U(unit, "L2 Thaw and start L2 thread\n"))); 7560 7561 if (fifo_modified) { 7562 if (SOC_REG_IS_VALID(unit, L2_MOD_FIFO_ENABLEr)) { 7563 rv2 = soc_reg_field32_modify(unit, L2_MOD_FIFO_ENABLEr, 7564 REG_PORT_ANY, L2_DELETEf, l2_delete); 7565 } else { 7566 if (soc_reg_field_valid(unit, AUX_ARB_CONTROLr, 7567 L2_MOD_FIFO_ENABLE_L2_DELETEf)) { 7568 rv2 = soc_reg_field32_modify(unit, AUX_ARB_CONTROLr, 7569 REG_PORT_ANY, L2_MOD_FIFO_ENABLE_L2_DELETEf, l2_delete); 7570 } 7571 } 7572 7573 if (rv2 < 0) { 7574 goto _free_exit; 7575 } 7576 } else if (SOC_CONTROL(unit)->l2x_mode != L2MODE_FIFO) { 7577 rv2 = soc_l2x_start(unit, soc->l2x_flags, interval); 7578 if (rv2 < 0) { 7579 goto _free_exit; 7580 } 7581 } 7582 7583 rv2 = bcm_esw_l2_addr_thaw(unit); 7584 if (rv2 < 0) { 7585 goto _free_exit; 7586 } 7587 } 7588 } 7589 7590 _free_exit: 7591 _bcm_esw_l2_vlan_gport_free(unit, &l2_pair); 7592 7593 if (rv < 0) { 7594 return rv; 7595 } else if (rv2 < 0) { 7596 return rv2; 7597 } else { 7598 return rv; 7599 } 7600 } 7601 7602 #if defined(INCLUDE_L3) 7603 /* 7604 * Function: 7605 * bcm_esw_l2_change_fields_add 7606 * Description: 7607 * Add a Change L2 fields entry to the egress xlate table. 7608 * Parameters: 7609 * unit - (IN) Device number. 7610 * l2_change_fields - (IN) 7611 * IN: l2 header info: rewrite L2 fields 7612 * Returns: 7613 * BCM_E_XXX 7614 */ 7615 int 7616 bcm_esw_l2_change_fields_add( 7617 int unit, 7618 bcm_l2_change_fields_t *l2_info) 7619 { 7620 #if defined(BCM_TRIDENT3_SUPPORT) 7621 if (soc_feature(unit, soc_feature_vfi_switched_l2_change_fields)) { 7622 /* validate input */ 7623 if (NULL == l2_info) { 7624 return BCM_E_PARAM; 7625 } 7626 7627 /* validate opaque object id */ 7628 if (l2_info->change_l2_fields_class_id > 0xffff) { 7629 return BCM_E_PARAM; 7630 } 7631 7632 VLAN_CHK_ID(unit, l2_info->vlan); 7633 7634 return _bcm_td3_l2_change_fields_add(unit, l2_info); 7635 } 7636 #endif /* BCM_TRIDENT3_SUPPORT */ 7637 7638 return BCM_E_UNAVAIL; 7639 } 7640 7641 /* Function: 7642 * bcm_esw_l2_change_fields_delete 7643 * Description: 7644 * Delete the l2 change fields from EVXLT table. 7645 * Parameters: 7646 * unit - (IN) Device number. 7647 * l2_info - (IN) key fields to be deleted. 7648 */ 7649 int 7650 bcm_esw_l2_change_fields_delete( 7651 int unit, 7652 bcm_l2_change_fields_t *l2_info) 7653 { 7654 #if defined(BCM_TRIDENT3_SUPPORT) 7655 soc_mem_t mem = EGR_VLAN_XLATE_2_DOUBLEm; 7656 soc_field_t tag_act_f = CHANGE_L2_FIELDS__TAG_ACTION_PROFILE_PTRf; 7657 soc_field_t tpid_f = CHANGE_L2_FIELDS__TPID_INDEXf; 7658 uint32 entry[SOC_MAX_MEM_WORDS]; 7659 uint32 return_entry[SOC_MAX_MEM_WORDS]; 7660 uint32 profile_index = 0; 7661 uint32 tpid_inx = 0; 7662 int index = 0; 7663 int action_present=0, action_not_present=0; 7664 7665 if (soc_feature(unit, soc_feature_vfi_switched_l2_change_fields)) { 7666 /* validate input */ 7667 if (NULL == l2_info) { 7668 return BCM_E_PARAM; 7669 } 7670 7671 /* validate opaque object id */ 7672 if (l2_info->change_l2_fields_class_id > 0xffff) { 7673 return BCM_E_PARAM; 7674 } 7675 7676 sal_memset(entry, 0, sizeof(entry)); 7677 7678 BCM_IF_ERROR_RETURN( 7679 _bcm_td3_l2_change_fields_egress_key_set(unit, 7680 mem, l2_info, entry)); 7681 7682 /* first free any tag action profile entry */ 7683 BCM_IF_ERROR_RETURN( 7684 soc_mem_search(unit, mem, MEM_BLOCK_ANY, &index, 7685 entry, return_entry, 0)); 7686 7687 profile_index = soc_mem_field32_get(unit, mem, 7688 return_entry, tag_act_f); 7689 7690 BCM_IF_ERROR_RETURN(_bcm_td3_sd_tag_action_get(unit, 7691 profile_index, &action_present, &action_not_present)); 7692 7693 if (profile_index != 0) { 7694 BCM_IF_ERROR_RETURN( 7695 _bcm_trx_egr_vlan_action_profile_entry_delete(unit, 7696 profile_index)); 7697 } 7698 7699 if ((action_not_present == 0x1) || (action_present == 0x1) || 7700 (action_present == 0x4) || (action_present == 0x7)) { 7701 tpid_inx = soc_mem_field32_get(unit, mem, 7702 return_entry, tpid_f); 7703 7704 BCM_IF_ERROR_RETURN(_bcm_fb2_outer_tpid_entry_delete(unit, 7705 tpid_inx)); 7706 } 7707 7708 /* now delete entry */ 7709 BCM_IF_ERROR_RETURN(soc_mem_delete(unit, 7710 mem, MEM_BLOCK_ANY, entry)); 7711 7712 return BCM_E_NONE; 7713 } 7714 #endif /* BCM_TRIDENT3_SUPPORT */ 7715 7716 return BCM_E_UNAVAIL; 7717 } 7718 7719 /* Function: 7720 * bcm_esw_l2_change_fields_get 7721 * Description: 7722 * Retrieve the change l2 entry given the key fields 7723 * Parameters: 7724 * unit - (IN) Device number. 7725 * nat_id - IN Index of entry to get. 7726 */ 7727 int 7728 bcm_esw_l2_change_fields_get( 7729 int unit, 7730 bcm_l2_change_fields_t *l2_info) 7731 { 7732 #if defined(BCM_TRIDENT3_SUPPORT) 7733 soc_mem_t mem = EGR_VLAN_XLATE_2_DOUBLEm; 7734 uint32 entry[SOC_MAX_MEM_WORDS]; 7735 7736 if (soc_feature(unit, soc_feature_vfi_switched_l2_change_fields)) { 7737 /* validate input */ 7738 if (NULL == l2_info) { 7739 return BCM_E_PARAM; 7740 } 7741 7742 /* validate opaque object id */ 7743 if (l2_info->change_l2_fields_class_id > 0xffff) { 7744 return BCM_E_PARAM; 7745 } 7746 7747 sal_memset(entry, 0, sizeof(entry)); 7748 7749 BCM_IF_ERROR_RETURN( 7750 _bcm_td3_l2_change_fields_egress_key_set(unit, 7751 mem, l2_info, entry)); 7752 7753 return _bcm_td3_l2_change_fields_egress_entry_get(unit, 7754 mem, entry, l2_info); 7755 } 7756 #endif /* BCM_TRIDENT3_SUPPORT */ 7757 return BCM_E_UNAVAIL; 7758 } 7759 7760 /* Function: 7761 * bcm_esw_l2_change_fields_traverse 7762 * 7763 * Description: 7764 * Traverse all valid change L2 entries in the egress translate table 7765 * and call the supplied callback routine for each. 7766 * 7767 * Parameters: 7768 * unit - (IN) Device number. 7769 * cb - (IN) User call-back function 7770 */ 7771 int 7772 bcm_esw_l2_change_fields_traverse( 7773 int unit, 7774 bcm_l2_change_fields_traverse_cb cb, 7775 void *user_data) 7776 { 7777 #if defined(BCM_TRIDENT3_SUPPORT) 7778 if (soc_feature(unit, soc_feature_vfi_switched_l2_change_fields)) { 7779 if (NULL == cb) { 7780 return BCM_E_NONE; 7781 } 7782 7783 return _bcm_td3_change_l2_fields_entry_traverse(unit, 7784 EGR_VLAN_XLATE_2_DOUBLEm, cb, user_data); 7785 } 7786 7787 #endif /* BCM_TRIDENT3_SUPPORT */ 7788 return BCM_E_UNAVAIL; 7789 } 7790 #endif /* INCLUDE_L3 */ 7791 7792 #ifdef BCM_WARM_BOOT_SUPPORT 7793 7794 #define BCM_WB_VERSION_1_0 SOC_SCACHE_VERSION(1,0) 7795 #define BCM_WB_VERSION_1_1 SOC_SCACHE_VERSION(1,1) 7796 #define BCM_WB_DEFAULT_VERSION BCM_WB_VERSION_1_1 7797 7798 /* 7799 * Function: 7800 * _bcm_esw_l2_wb_alloc 7801 * Purpose: 7802 * Allocated L2 module persistent info for Level 2 Warm Boot 7803 * Parameters: 7804 * unit - StrataSwitch unit number. 7805 * Returns: 7806 * BCM_E_XXX 7807 */ 7808 STATIC int 7809 _bcm_esw_l2_wb_alloc(int unit) 7810 { 7811 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_GREYHOUND2_SUPPORT) 7812 int sz = 0; 7813 soc_scache_handle_t scache_handle; 7814 uint8 *scache_ptr; 7815 int rv = BCM_E_NONE; 7816 int stable_size = 0; 7817 _bcm_l2_station_control_t *station_control = NULL; 7818 int sw_aging_support; /* SW Learning supported */ 7819 int underlay_max_entries = 0; 7820 #ifdef BCM_RIOT_SUPPORT 7821 int overlay_max_entries = 0; 7822 #endif /* BCM_RIOT_SUPPORT */ 7823 7824 SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size)); 7825 /* Requires extended scache support warmboot */ 7826 if (stable_size == 0) { 7827 return BCM_E_NONE; 7828 } 7829 7830 rv = _bcm_l2_station_control_get(unit, &station_control); 7831 if (BCM_FAILURE(rv) && (rv != BCM_E_INIT)) { 7832 return rv; 7833 } 7834 7835 sw_aging_support = SOC_IS_TRIUMPH3(unit); 7836 #ifdef BCM_TOMAHAWK_SUPPORT 7837 /* TH/TD3 does not support SW aging. Added only for warmboot upgrade purpose. */ 7838 sw_aging_support = sw_aging_support || SOC_IS_TOMAHAWKX(unit) || SOC_IS_TRIDENT3X(unit); 7839 #endif /* BCM_TOMAHAWK_SUPPORT */ 7840 #ifdef BCM_TRIDENT2_SUPPORT 7841 sw_aging_support = sw_aging_support || SOC_CONTROL(unit)->l2x_sw_aging; 7842 #endif /* BCM_TRIDENT2_SUPPORT */ 7843 7844 if (sw_aging_support || 7845 ((!SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit)) && station_control)) { 7846 7847 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_L2, 0); 7848 7849 if (sw_aging_support) { 7850 /* aging time */ 7851 sz += sizeof(int); 7852 } 7853 7854 if ((!SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit)) && station_control) { 7855 /* Underlay L2 station entry - sid/prio */ 7856 BCM_IF_ERROR_RETURN( 7857 _bcm_tr_l2_station_entry_max_size_get(unit, FALSE, 7858 &underlay_max_entries)); 7859 sz += (underlay_max_entries * (sizeof(int) * 2)); 7860 7861 #ifdef BCM_RIOT_SUPPORT 7862 /* Overlay L2 station entry - sid/prio */ 7863 BCM_IF_ERROR_RETURN( 7864 _bcm_tr_l2_station_entry_max_size_get(unit, TRUE, 7865 &overlay_max_entries)); 7866 7867 sz += (overlay_max_entries * (sizeof(int) * 2)); 7868 #endif /* BCM_RIOT_SUPPORT */ 7869 7870 } 7871 7872 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, TRUE, 7873 sz, &scache_ptr, 7874 BCM_WB_DEFAULT_VERSION, NULL); 7875 7876 if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) { 7877 return rv; 7878 } 7879 } 7880 #endif /* BCM_TRIDENT_SUPPORT || BCM_GREYHOUND2_SUPPORT */ 7881 return BCM_E_NONE; 7882 } 7883 7884 /* 7885 * Function: 7886 * _bcm_esw_l2_wb_sync 7887 * Purpose: 7888 * Record L2 module persistent info for Level 2 Warm Boot 7889 * Parameters: 7890 * unit - StrataSwitch unit number. 7891 * Returns: 7892 * BCM_E_XXX 7893 */ 7894 int 7895 _bcm_esw_l2_wb_sync(int unit) 7896 { 7897 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_GREYHOUND2_SUPPORT) 7898 int sz = 0; 7899 soc_scache_handle_t scache_handle; 7900 uint8 *scache_ptr = NULL; 7901 int aging_time = 0; 7902 _bcm_l2_station_entry_t **entry_arr; 7903 _bcm_l2_station_control_t *station_control = NULL; 7904 int stable_size = 0; 7905 int rv = BCM_E_NONE; 7906 int index = 0; 7907 int init_value = 0; 7908 int sw_aging_support; /* SW Learning supported */ 7909 int underlay_max_entries = 0; 7910 #ifdef BCM_RIOT_SUPPORT 7911 int overlay_max_entries = 0; 7912 #endif /* BCM_RIOT_SUPPORT */ 7913 7914 #if defined(BCM_TOMAHAWK3_SUPPORT) 7915 if (SOC_IS_TOMAHAWK3(unit)) { 7916 return _bcm_th3_l2_wb_sync(unit); 7917 } 7918 #endif /* BCM_TOMAHAWK3_SUPPORT */ 7919 7920 SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size)); 7921 /* Requires extended scache support warmboot */ 7922 if (stable_size == 0) { 7923 return BCM_E_NONE; 7924 } 7925 7926 rv = _bcm_l2_station_control_get(unit, &station_control); 7927 if (BCM_FAILURE(rv) && (rv != BCM_E_INIT)) { 7928 return rv; 7929 } 7930 7931 sw_aging_support = SOC_IS_TRIUMPH3(unit); 7932 #ifdef BCM_TOMAHAWK_SUPPORT 7933 /* TH/TD3 does not support SW aging. Added only for warmboot upgrade purpose. */ 7934 sw_aging_support = sw_aging_support || SOC_IS_TOMAHAWKX(unit) || SOC_IS_TRIDENT3X(unit); 7935 #endif /* BCM_TOMAHAWK_SUPPORT */ 7936 #ifdef BCM_TRIDENT2_SUPPORT 7937 sw_aging_support = sw_aging_support || SOC_CONTROL(unit)->l2x_sw_aging; 7938 #endif /* BCM_TRIDENT2_SUPPORT */ 7939 7940 if (sw_aging_support || 7941 ((!SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit)) && station_control)) { 7942 7943 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_L2, 0); 7944 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 7945 0, &scache_ptr, 7946 BCM_WB_DEFAULT_VERSION, NULL); 7947 7948 if (BCM_FAILURE(rv) && (rv != BCM_E_INTERNAL)) { 7949 return rv; 7950 } 7951 7952 if (sw_aging_support) { 7953 /* aging time */ 7954 BCM_IF_ERROR_RETURN( 7955 _bcm_esw_l2_age_timer_get(unit, &aging_time)); 7956 sz = sizeof(int); 7957 sal_memcpy(scache_ptr, &aging_time, sz); 7958 scache_ptr += sz; 7959 } 7960 7961 if ((!SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit)) && station_control) { 7962 BCM_IF_ERROR_RETURN( 7963 _bcm_tr_l2_station_entry_max_size_get(unit, FALSE, 7964 &underlay_max_entries)); 7965 /* Underlay L2 station entry - sid/prio */ 7966 entry_arr = (station_control->entry_arr); 7967 7968 for (index = 0; index < underlay_max_entries; index++) { 7969 if (entry_arr[index]) { 7970 sal_memcpy(scache_ptr, 7971 &(entry_arr[index]->sid), sizeof(int)); 7972 scache_ptr += sizeof(int); 7973 7974 sal_memcpy(scache_ptr, 7975 &(entry_arr[index]->prio), sizeof(int)); 7976 scache_ptr += sizeof(int); 7977 } else { 7978 sal_memcpy(scache_ptr, &init_value, sizeof(int)); 7979 scache_ptr += sizeof(int); 7980 7981 sal_memcpy(scache_ptr, &init_value, sizeof(int)); 7982 scache_ptr += sizeof(int); 7983 } 7984 } 7985 7986 #ifdef BCM_RIOT_SUPPORT 7987 BCM_IF_ERROR_RETURN( 7988 _bcm_tr_l2_station_entry_max_size_get(unit, TRUE, 7989 &overlay_max_entries)); 7990 /* Overlay L2 station entry - sid/prio */ 7991 entry_arr = (station_control->entry_arr_2); 7992 7993 for (index = 0; index < overlay_max_entries; index++) { 7994 if (entry_arr[index]) { 7995 sal_memcpy(scache_ptr, 7996 &(entry_arr[index]->sid), sizeof(int)); 7997 scache_ptr += sizeof(int); 7998 7999 sal_memcpy(scache_ptr, 8000 &(entry_arr[index]->prio), sizeof(int)); 8001 scache_ptr += sizeof(int); 8002 } else { 8003 sal_memcpy(scache_ptr, &init_value, sizeof(int)); 8004 scache_ptr += sizeof(int); 8005 8006 sal_memcpy(scache_ptr, &init_value, sizeof(int)); 8007 scache_ptr += sizeof(int); 8008 } 8009 } 8010 #endif /* BCM_RIOT_SUPPORT */ 8011 } 8012 } 8013 #endif /* BCM_TRIDENT_SUPPORT || BCM_GREYHOUND2_SUPPORT */ 8014 return BCM_E_NONE; 8015 } 8016 8017 /* 8018 * Function: 8019 * _bcm_esw_l2_wb_recover 8020 * Purpose: 8021 * Recover L2 module persistent info for Level 2 Warm Boot 8022 * Parameters: 8023 * unit - StrataSwitch unit number. 8024 * Returns: 8025 * BCM_E_XXX 8026 */ 8027 STATIC int 8028 _bcm_esw_l2_wb_recover(int unit) 8029 { 8030 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_GREYHOUND2_SUPPORT) 8031 soc_scache_handle_t scache_handle; 8032 uint8 *scache_ptr = NULL; 8033 uint16 recovered_ver = 0; 8034 int aging_time = 0; 8035 int rv = BCM_E_NONE; 8036 int additional_scache_size = 0; 8037 int sw_aging_support; /* SW Learning supported */ 8038 #ifdef BCM_RIOT_SUPPORT 8039 int overlay_max_entries = 0; 8040 #endif /* BCM_RIOT_SUPPORT */ 8041 int underlay_max_entries = 0; 8042 _bcm_l2_station_entry_t **entry_arr; 8043 _bcm_l2_station_control_t *station_control = NULL; 8044 int index = 0; 8045 int sid = 0; 8046 int pri = 0; 8047 int cur_last_sid = 0; 8048 int stable_size = 0; 8049 8050 SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size)); 8051 /* Requires extended scache support warmboot */ 8052 if (stable_size == 0) { 8053 return BCM_E_NONE; 8054 } 8055 8056 rv = _bcm_l2_station_control_get(unit, &station_control); 8057 if (BCM_FAILURE(rv) && (rv != BCM_E_INIT)) { 8058 return rv; 8059 } 8060 8061 sw_aging_support = SOC_IS_TRIUMPH3(unit); 8062 #ifdef BCM_TOMAHAWK_SUPPORT 8063 /* TH/TD3 does not support SW aging. Added only for warmboot upgrade purpose. */ 8064 sw_aging_support = sw_aging_support || SOC_IS_TOMAHAWKX(unit) || SOC_IS_TRIDENT3X(unit); 8065 #endif /* BCM_TOMAHAWK_SUPPORT */ 8066 #ifdef BCM_TRIDENT2_SUPPORT 8067 sw_aging_support = sw_aging_support || SOC_CONTROL(unit)->l2x_sw_aging; 8068 #endif /* BCM_TRIDENT2_SUPPORT */ 8069 8070 if (sw_aging_support || 8071 ((!SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit)) && station_control)) { 8072 8073 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_L2, 0); 8074 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 8075 0, &scache_ptr, 8076 BCM_WB_DEFAULT_VERSION, &recovered_ver); 8077 if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) { 8078 return rv; 8079 } else if (BCM_E_NOT_FOUND == rv) { 8080 return _bcm_esw_l2_wb_alloc(unit); 8081 } 8082 8083 if (scache_ptr != NULL) { 8084 if (sw_aging_support) { 8085 if (recovered_ver >= BCM_WB_VERSION_1_0) { 8086 /* aging time */ 8087 sal_memcpy(&aging_time, scache_ptr, sizeof(int)); 8088 BCM_IF_ERROR_RETURN( 8089 _bcm_esw_l2_age_timer_set(unit, aging_time, aging_time > 0)); 8090 scache_ptr += sizeof(int); 8091 } else { 8092 additional_scache_size += sizeof(int); 8093 } 8094 } 8095 8096 if ((!SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit)) && station_control) { 8097 BCM_IF_ERROR_RETURN( 8098 _bcm_tr_l2_station_entry_max_size_get( 8099 unit, FALSE, &underlay_max_entries)); 8100 #ifdef BCM_RIOT_SUPPORT 8101 BCM_IF_ERROR_RETURN( 8102 _bcm_tr_l2_station_entry_max_size_get( 8103 unit, TRUE, &overlay_max_entries)); 8104 #endif /* BCM_RIOT_SUPPORT */ 8105 8106 /* Recover overlay/underlay L2 station entry */ 8107 if (recovered_ver >= BCM_WB_VERSION_1_1) { 8108 entry_arr = (station_control->entry_arr); 8109 8110 for (index = 0; index < underlay_max_entries; index++) { 8111 sal_memcpy(&sid, scache_ptr, sizeof(int)); 8112 scache_ptr += sizeof(int); 8113 8114 sal_memcpy(&pri, scache_ptr, sizeof(int)); 8115 scache_ptr += sizeof(int); 8116 8117 if (sid > cur_last_sid) { 8118 cur_last_sid = sid; 8119 } 8120 8121 if (entry_arr[index]) { 8122 if (0 == sid) { 8123 /* 8124 * Only recover the L2 station entries created 8125 * by bcm_l2_station APIs 8126 */ 8127 if (index < station_control->entries_total) { 8128 if (NULL != entry_arr[index]->tcam_ent) { 8129 sal_free(entry_arr[index]->tcam_ent); 8130 } 8131 8132 sal_free(entry_arr[index]); 8133 8134 entry_arr[index] = NULL; 8135 station_control->entry_count--; 8136 station_control->entries_free++; 8137 } 8138 } else { 8139 entry_arr[index]->sid = sid; 8140 entry_arr[index]->prio = pri; 8141 } 8142 } 8143 } 8144 8145 rv = _bcm_tr_l2_station_entry_last_sid_set(unit, FALSE, 8146 cur_last_sid); 8147 if (BCM_FAILURE(rv)) { 8148 return rv; 8149 } 8150 #ifdef BCM_RIOT_SUPPORT 8151 cur_last_sid = 0; 8152 8153 entry_arr = (station_control->entry_arr_2); 8154 8155 for (index = 0; index < overlay_max_entries; index++) { 8156 sal_memcpy(&sid, scache_ptr, sizeof(int)); 8157 scache_ptr += sizeof(int); 8158 8159 sal_memcpy(&pri, scache_ptr, sizeof(int)); 8160 scache_ptr += sizeof(int); 8161 8162 if (sid > cur_last_sid) { 8163 cur_last_sid = sid; 8164 } 8165 8166 if (entry_arr[index]) { 8167 if (0 == sid) { 8168 /* 8169 * Only recover the L2 station entries created 8170 * by bcm_l2_station APIs 8171 */ 8172 if (index < station_control->entries_total_2) { 8173 if (NULL != entry_arr[index]->tcam_ent) { 8174 sal_free(entry_arr[index]->tcam_ent); 8175 } 8176 sal_free(entry_arr[index]); 8177 entry_arr[index] = NULL; 8178 station_control->entry_count_2--; 8179 station_control->entries_free_2++; 8180 } 8181 } else { 8182 entry_arr[index]->sid = sid; 8183 entry_arr[index]->prio = pri; 8184 } 8185 } 8186 } 8187 8188 rv = _bcm_tr_l2_station_entry_last_sid_set(unit, TRUE, 8189 cur_last_sid); 8190 if (BCM_FAILURE(rv)) { 8191 return rv; 8192 } 8193 #endif /* BCM_RIOT_SUPPORT */ 8194 } else { 8195 /* Underlay L2 station entry - sid/prio */ 8196 additional_scache_size += 8197 (underlay_max_entries *(sizeof(int) * 2)); 8198 #ifdef BCM_RIOT_SUPPORT 8199 /* Overlay L2 station entry - sid/prio */ 8200 additional_scache_size += 8201 (overlay_max_entries * (sizeof(int) * 2)); 8202 #endif /* BCM_RIOT_SUPPORT */ 8203 } 8204 } 8205 8206 if (additional_scache_size > 0) { 8207 rv = soc_scache_realloc(unit, scache_handle, 8208 additional_scache_size); 8209 if(BCM_FAILURE(rv)) { 8210 return rv; 8211 } 8212 } 8213 } 8214 } 8215 #endif /* BCM_TRIDENT_SUPPORT || BCM_GREYHOUND2_SUPPORT */ 8216 return BCM_E_NONE; 8217 } 8218 8219 #endif /* BCM_WARM_BOOT_SUPPORT */ 8220