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