subport.c (107324B)
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: subport.c 8 * Purpose: Triumph SUBPORT functions 9 */ 10 11 #include <soc/defs.h> 12 #include <sal/core/libc.h> 13 #include <shared/bsl.h> 14 #if defined(BCM_TRIUMPH2_SUPPORT) && defined(INCLUDE_L3) 15 16 #include <soc/drv.h> 17 #include <soc/scache.h> 18 #include <soc/hash.h> 19 #include <soc/util.h> 20 21 #include <bcm/error.h> 22 #include <bcm/subport.h> 23 24 #include <bcm_int/esw/mbcm.h> 25 #include <bcm_int/esw/firebolt.h> 26 #include <bcm_int/esw/trx.h> 27 #include <bcm_int/esw/triumph.h> 28 #include <bcm_int/esw/stack.h> 29 #include <bcm_int/esw/l3.h> 30 #include <bcm_int/esw/virtual.h> 31 #include <bcm_int/esw/triumph2.h> 32 #include <bcm_int/esw/subport.h> 33 34 #include <bcm_int/esw_dispatch.h> 35 36 /* Usage bitmap of subport groups (1 group = 8 VPs) */ 37 STATIC SHR_BITDCL *_tr2_group_bitmap[BCM_MAX_NUM_UNITS] = { 0 }; 38 39 /* Array of L3_INTF IDs per VP (0xffff means unused) */ 40 STATIC uint16 *_tr2_subport_id[BCM_MAX_NUM_UNITS] = { 0 }; 41 42 /* Per-port count of all subports added */ 43 STATIC int _tr2_subport_group_count[BCM_MAX_NUM_UNITS][SOC_MAX_NUM_PORTS] = {{ 0 }}; 44 45 /* 46 * Limited to 4K VPs (instead of actual table size of 8K) 47 * since the IVID field (12-bits) in EGR_VLAN_XLATE table is 48 * used as the DVP value. 49 */ 50 #define _TR2_SUBPORT_NUM_VP (4096) 51 #define _TR2_VP_PER_SUBPORT_GROUP (8) 52 #define _TR2_SUBPORT_NUM_GROUP (_TR2_SUBPORT_NUM_VP / _TR2_VP_PER_SUBPORT_GROUP) 53 54 #define _TR2_SUBPORT_VP_MEM_LOCK(unit) \ 55 do { \ 56 if (SOC_IS_TRIUMPH2(unit) || SOC_MEM_IS_VALID(unit, SOURCE_VPm)) { \ 57 MEM_LOCK(unit, SOURCE_VPm); \ 58 } else { \ 59 sal_mutex_take(_tr2_subport_vp_mutex[unit], sal_mutex_FOREVER); \ 60 } \ 61 } while ((0)) 62 63 #define _TR2_SUBPORT_VP_MEM_UNLOCK(unit) \ 64 do { \ 65 if (SOC_IS_TRIUMPH2(unit) || SOC_MEM_IS_VALID(unit, SOURCE_VPm)) { \ 66 MEM_UNLOCK(unit, SOURCE_VPm); \ 67 } else { \ 68 sal_mutex_give(_tr2_subport_vp_mutex[unit]); \ 69 } \ 70 } while ((0)) 71 72 73 STATIC sal_mutex_t _tr2_subport_vp_mutex[BCM_MAX_NUM_UNITS] = {NULL}; 74 75 #define _TR2_SUBPORT_CHECK_INIT(_unit_) \ 76 if (!_tr2_group_bitmap[_unit_]) \ 77 return BCM_E_INIT 78 79 STATIC int _bcm_tr2_subport_port_delete(int unit, int l3_idx, int vp); 80 STATIC int _bcm_tr2_subport_group_destroy(int unit, int vp_base); 81 82 /* 83 * Subport group usage bitmap operations 84 */ 85 #define _BCM_TR2_GROUP_USED_GET(_u_, _group_) \ 86 SHR_BITGET(_tr2_group_bitmap[_u_], (_group_)) 87 #define _BCM_TR2_GROUP_USED_SET(_u_, _group_) \ 88 SHR_BITSET(_tr2_group_bitmap[_u_], (_group_)) 89 #define _BCM_TR2_GROUP_USED_CLR(_u_, _group_) \ 90 SHR_BITCLR(_tr2_group_bitmap[_u_], (_group_)) 91 92 /* 93 * Subport port usage bitmap operations 94 */ 95 #define _BCM_TR2_SUBPORT_ID_GET(_u_, _subport_) \ 96 (_tr2_subport_id[_u_][_subport_]) 97 #define _BCM_TR2_SUBPORT_ID_SET(_u_, _subport_, _id_) \ 98 (_tr2_subport_id[_u_][_subport_] = _id_) 99 #define _BCM_TR2_SUBPORT_ID_CLR(_u_, _subport_) \ 100 (_tr2_subport_id[_u_][_subport_] = 0xffff) 101 102 #ifdef BCM_KATANA2_SUPPORT 103 #define _BCM_QOS_MAP_TYPE_MASK 0x3ff 104 #define _BCM_QOS_MAP_SHIFT 10 105 #define _BCM_QOS_MAP_ING_QUEUE_OFFSET_MAX 7 106 #define _BCM_QOS_MAP_TYPE_ING_QUEUE_OFFSET_MAP_TABLE 5 107 #define _EH_TAG_TYPE_ING_QUEUE_MAP 2 108 #endif 109 110 /* 111 * Function Vector 112 */ 113 static bcm_esw_subport_drv_t bcmi_tr2_subport_drv = { 114 115 /* subport_init */ bcm_tr2_subport_init, 116 /* subport_group_create */ bcm_tr2_subport_group_create, 117 /* subport_group_get */ bcm_tr2_subport_group_get, 118 /* subport_group_traverse */ NULL, 119 /* subport_group_destroy */ bcm_tr2_subport_group_destroy, 120 /* subport_linkphy_config_set */ NULL, 121 /* subport_linkphy_config_get */ NULL, 122 /* subport_port_add */ bcm_tr2_subport_port_add, 123 /* subport_port_get */ bcm_tr2_subport_port_get, 124 /* subport_port_traverse */ bcm_tr2_subport_port_traverse, 125 /* subport_port_stat_set */ NULL, 126 /* subport_port_stat_get */ NULL, 127 /* subport_port_delete */ bcm_tr2_subport_port_delete, 128 /* subport_cleanup */ bcm_tr2_subport_cleanup, 129 130 /* coe_init */ NULL, 131 /* coe_group_create */ NULL, 132 /* coe_group_get */ NULL, 133 /* coe_group_traverse */ NULL, 134 /* coe_group_destroy */ NULL, 135 /* coe_linkphy_config_set */ NULL, 136 /* coe_linkphy_config_get */ NULL, 137 /* coe_port_add */ NULL, 138 /* coe_port_get */ NULL, 139 /* coe_port_traverse */ NULL, 140 /* coe_port_stat_set */ NULL, 141 /* coe_port_stat_get */ NULL, 142 /* coe_port_delete */ NULL, 143 /* coe_cleanup */ NULL 144 }; 145 146 /* 147 * Function: 148 * _bcm_tr_subport_gport_used 149 * Purpose: 150 * Internal function for testing if a gport is a configured subport type 151 * Parameters: 152 * unit - (IN) Device number. 153 * port - (IN) Gport 154 * Returns: 155 * BCM_X_XXX 156 */ 157 int 158 _bcm_tr2_subport_gport_used(int unit, bcm_gport_t port) 159 { 160 int vp; 161 162 _TR2_SUBPORT_VP_MEM_LOCK(unit); 163 if (BCM_GPORT_IS_SUBPORT_GROUP(port)) { 164 vp = BCM_GPORT_SUBPORT_GROUP_GET(port); 165 if ((vp < 0) || (vp > (_TR2_SUBPORT_NUM_VP - 8))) { 166 _TR2_SUBPORT_VP_MEM_UNLOCK(unit); 167 return BCM_E_PARAM; 168 } 169 if (!_BCM_TR2_GROUP_USED_GET(unit, (vp / 8))) { 170 _TR2_SUBPORT_VP_MEM_UNLOCK(unit); 171 return BCM_E_NOT_FOUND; 172 } 173 } else if (BCM_GPORT_IS_SUBPORT_PORT(port)) { 174 vp = BCM_GPORT_SUBPORT_PORT_GET(port); 175 if (vp >= _TR2_SUBPORT_NUM_VP) { 176 _TR2_SUBPORT_VP_MEM_UNLOCK(unit); 177 return BCM_E_PARAM; 178 } 179 if (_BCM_TR2_SUBPORT_ID_GET(unit, vp) == 0xffff) { 180 _TR2_SUBPORT_VP_MEM_UNLOCK(unit); 181 return BCM_E_NOT_FOUND; 182 } 183 } 184 _TR2_SUBPORT_VP_MEM_UNLOCK(unit); 185 return BCM_E_NONE; 186 } 187 188 /* 189 * Function: 190 * _bcm_tr_subport_vp_alloc 191 * Purpose: 192 * Internal function for allocating a group of VPs 193 * Parameters: 194 * unit - (IN) Device number. 195 * base_vp - (OUT) Base VP index 196 * Returns: 197 * BCM_X_XXX 198 */ 199 STATIC int 200 _bcm_tr2_subport_vp_alloc(int unit, int *base_vp) 201 { 202 int i; 203 /* 204 * VP allocation is normally done by the MPLS module. However, 205 * for builds without MPLS support, the VP allocation is done here. 206 */ 207 if (soc_feature(unit, soc_feature_subport_enhanced)) { 208 int rv; 209 _bcm_vp_info_t vp_info; 210 /* 211 * Allocate a group of 8 consecutive VPs since 3-bit prio 212 * is added to DVP-group to get the final DVP in the L2 lookup. 213 * Only allocate from the 0 - 4k range since only 12-bits 214 * are used in the EGR_VLAN_XLATE table key. 215 * (the IVID field is used as the DVP in EGR_VLAN_XLATE) 216 */ 217 _bcm_vp_info_init(&vp_info); 218 vp_info.vp_type = _bcmVpTypeSubport; 219 rv = _bcm_vp_alloc(unit, 0, 4095, 8, SOURCE_VPm, vp_info, base_vp); 220 if (rv < 0) { 221 return rv; 222 } 223 _BCM_TR2_GROUP_USED_SET(unit, *base_vp / 8); 224 return BCM_E_NONE; 225 } 226 227 _TR2_SUBPORT_VP_MEM_LOCK(unit); 228 for (i = 0; i < _TR2_SUBPORT_NUM_GROUP; i++) { 229 if (!_BCM_TR2_GROUP_USED_GET(unit, i)) { 230 break; 231 } 232 } 233 if (i == _TR2_SUBPORT_NUM_GROUP) { 234 _TR2_SUBPORT_VP_MEM_UNLOCK(unit); 235 return BCM_E_RESOURCE; 236 } 237 *base_vp = i * 8; 238 239 _BCM_TR2_GROUP_USED_SET(unit, i); 240 _TR2_SUBPORT_VP_MEM_UNLOCK(unit); 241 return BCM_E_NONE; 242 } 243 244 /* 245 * Function: 246 * _bcm_tr_subport_vp_free 247 * Purpose: 248 * Internal function for freeing a group of VPs 249 * Parameters: 250 * unit - (IN) Device number. 251 * base_vp - (IN) Base VP index 252 * Returns: 253 * BCM_X_XXX 254 */ 255 STATIC int 256 _bcm_tr2_subport_vp_free(int unit, int base_vp) 257 { 258 /* 259 * VP freeing is normally done by the MPLS module. However, 260 * for builds without MPLS support, the VP free is done here. 261 */ 262 if (soc_feature(unit, soc_feature_subport_enhanced)) { 263 int rv; 264 265 rv = _bcm_vp_free(unit, _bcmVpTypeSubport, 8, base_vp); 266 BCM_IF_ERROR_RETURN (rv); 267 } 268 269 _BCM_TR2_GROUP_USED_CLR(unit, base_vp / 8); 270 271 return BCM_E_NONE; 272 } 273 274 STATIC void 275 _bcm_tr2_subport_free_resource(int unit) 276 { 277 if (_tr2_group_bitmap[unit]) { 278 sal_free(_tr2_group_bitmap[unit]); 279 _tr2_group_bitmap[unit] = NULL; 280 } 281 if (_tr2_subport_id[unit]) { 282 sal_free(_tr2_subport_id[unit]); 283 _tr2_subport_id[unit] = NULL; 284 } 285 286 if (_tr2_subport_vp_mutex[unit] != NULL) { 287 sal_mutex_destroy(_tr2_subport_vp_mutex[unit]); 288 _tr2_subport_vp_mutex[unit] = NULL; 289 } 290 } 291 292 #ifdef BCM_WARM_BOOT_SUPPORT 293 /* 294 * Function: 295 * _bcm_tr2_subport_reinit 296 * Purpose: 297 * Reinit for warm boot. 298 * Parameters: 299 * unit : (IN) Device Unit Number 300 * Returns: 301 * BCM_E_XXX 302 */ 303 STATIC int 304 _bcm_tr2_subport_reinit(int unit) 305 { 306 int vpbase_gprtid, stable_size; 307 int idx, grp_base_idx = 0, vp_count = 0, vp = 0; 308 int num_vp = soc_mem_index_count(unit, SOURCE_VPm); 309 int index_min, index_max, fs_index, tpid_enable, index; 310 source_vp_entry_t svp_entry; 311 egr_l3_intf_entry_t egr_l3_entry; 312 _bcm_vp_info_t vp_info; 313 314 _bcm_vp_info_init(&vp_info); 315 vp_info.vp_type = _bcmVpTypeSubport; 316 SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size)); 317 318 /* Reconstruct s/w state: Subport IDs */ 319 index_min = soc_mem_index_min(unit, EGR_L3_INTFm); 320 index_max = soc_mem_index_max(unit, EGR_L3_INTFm); 321 322 for (idx = index_min; idx <= index_max; idx++) { 323 SOC_IF_ERROR_RETURN(soc_mem_read(unit, EGR_L3_INTFm, MEM_BLOCK_ANY, 324 idx, &egr_l3_entry)); 325 if (soc_mem_field_valid(unit, EGR_L3_INTFm, IVID_VALIDf)) { 326 if (0 == soc_EGR_L3_INTFm_field32_get(unit, &egr_l3_entry, 327 IVID_VALIDf)) { 328 continue; 329 } 330 } else { 331 if (1 != soc_EGR_L3_INTFm_field32_get(unit, &egr_l3_entry, 332 IVID_PRESENT_ACTIONf) && 333 1 != soc_EGR_L3_INTFm_field32_get(unit, &egr_l3_entry, 334 IVID_ABSENT_ACTIONf)) { 335 continue; 336 } 337 } 338 if ((vp = soc_EGR_L3_INTFm_field32_get(unit, &egr_l3_entry, IVIDf)) == 0){ 339 continue; 340 } 341 if ((stable_size == 0) || SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit)) { 342 BCM_IF_ERROR_RETURN( 343 _bcm_vp_used_set(unit, vp, vp_info)); 344 _BCM_TR2_SUBPORT_ID_SET(unit, vp, idx); 345 BCM_L3_INTF_USED_SET(unit, idx); 346 } else { 347 /* Extended scache based (Level 2) recovery */ 348 if (_bcm_vp_used_get(unit, vp, _bcmVpTypeSubport)) { 349 _BCM_TR2_SUBPORT_ID_SET(unit, vp, idx); 350 BCM_L3_INTF_USED_SET(unit, idx); 351 } 352 } 353 } 354 355 /* Reconstruct s/w state: Subport Groups */ 356 index_min = soc_mem_index_min(unit, SOURCE_VPm); 357 index_max = soc_mem_index_max(unit, SOURCE_VPm); 358 for (idx = 0; idx < num_vp ; idx++) { 359 SOC_IF_ERROR_RETURN(soc_mem_read(unit, SOURCE_VPm, MEM_BLOCK_ANY, 360 idx, &svp_entry)); 361 362 if (0x3 != soc_SOURCE_VPm_field32_get(unit, &svp_entry, ENTRY_TYPEf)) { 363 continue; 364 } 365 366 /* A Subport group consists of a contiguous chunk of eight VPs */ 367 if (0 == grp_base_idx) { 368 grp_base_idx = idx; 369 } 370 371 if (_TR2_VP_PER_SUBPORT_GROUP == ++vp_count) { 372 if((grp_base_idx + _TR2_VP_PER_SUBPORT_GROUP) == 373 (idx + 1)) {/* if VP is the base VP of group */ 374 _BCM_TR2_GROUP_USED_SET(unit, (idx/_TR2_VP_PER_SUBPORT_GROUP)); 375 /* Update flex stats */ 376 if (soc_feature(unit, soc_feature_gport_service_counters)) { 377 if (soc_mem_field_valid(unit, SOURCE_VPm, VINTF_CTR_IDXf)) { 378 fs_index = soc_SOURCE_VPm_field32_get(unit, &svp_entry, 379 VINTF_CTR_IDXf); 380 if (fs_index) { 381 BCM_GPORT_SUBPORT_GROUP_SET(vpbase_gprtid, 382 grp_base_idx); 383 _bcm_esw_flex_stat_reinit_add(unit, 384 _bcmFlexStatTypeGport, fs_index, vpbase_gprtid); 385 } 386 } 387 } 388 grp_base_idx = 0; vp_count = 0; /* Reset for next group */ 389 } 390 } 391 392 /* Recover TPID ref count */ 393 if (soc_SOURCE_VPm_field32_get(unit, &svp_entry, SD_TAG_MODEf) == 1) { 394 tpid_enable = soc_SOURCE_VPm_field32_get(unit, &svp_entry, 395 TPID_ENABLEf); 396 for (index = 0; index < 4; index++) { 397 if (tpid_enable & (1 << index)) { 398 BCM_IF_ERROR_RETURN(_bcm_fb2_outer_tpid_tab_ref_count_add( 399 unit, index, 1)); 400 break; 401 } 402 } 403 } 404 } 405 406 return BCM_E_NONE; 407 } 408 #endif /* BCM_WARM_BOOT_SUPPORT */ 409 410 /* 411 * Function: 412 * bcm_subport_init 413 * Purpose: 414 * Initialize the SUBPORT software module 415 * Parameters: 416 * unit - Device Number 417 * Returns: 418 * BCM_E_XXX 419 */ 420 int 421 bcm_tr2_subport_init(int unit) 422 { 423 int i; 424 int rv = BCM_E_NONE; 425 426 /* Make sure module was initialized. */ 427 if (!BCM_XGS3_L3_INITIALIZED(unit)) { 428 return (BCM_E_INIT); 429 } 430 431 /* 432 * Include hook to flex stats 433 */ 434 435 if (_tr2_subport_id[unit] == NULL) { 436 _tr2_subport_id[unit] = 437 sal_alloc(_TR2_SUBPORT_NUM_VP * sizeof(uint16), "subport_bitmap"); 438 if (_tr2_subport_id[unit] == NULL) { 439 return BCM_E_MEMORY; 440 } 441 } 442 for (i = 0; i < _TR2_SUBPORT_NUM_VP; i++) { 443 _BCM_TR2_SUBPORT_ID_CLR(unit, i); 444 } 445 446 if (_tr2_group_bitmap[unit] == NULL) { 447 _tr2_group_bitmap[unit] = 448 sal_alloc(SHR_BITALLOCSIZE(_TR2_SUBPORT_NUM_GROUP), "subport_group_bitmap"); 449 if (_tr2_group_bitmap[unit] == NULL) { 450 _bcm_tr2_subport_free_resource(unit); 451 return BCM_E_MEMORY; 452 } 453 } 454 sal_memset(_tr2_group_bitmap[unit], 0, SHR_BITALLOCSIZE(_TR2_SUBPORT_NUM_GROUP)); 455 /* Don't use VP 0 (HW restriction) : mark group 0 as used */ 456 _BCM_TR2_GROUP_USED_SET(unit, 0); 457 458 for (i = 0; i < SOC_MAX_NUM_PORTS; i++) { 459 _tr2_subport_group_count[unit][i] = 0; 460 } 461 462 if (!SOC_MEM_IS_VALID(unit, SOURCE_VPm)) { 463 if (NULL == _tr2_subport_vp_mutex[unit]) { 464 _tr2_subport_vp_mutex[unit] = sal_mutex_create("subport vp mutex"); 465 if (_tr2_subport_vp_mutex[unit] == NULL) { 466 _bcm_tr2_subport_free_resource(unit); 467 return BCM_E_MEMORY; 468 } 469 } 470 } 471 #ifdef BCM_WARM_BOOT_SUPPORT 472 if(SOC_WARM_BOOT(unit)) { 473 rv = _bcm_tr2_subport_reinit(unit); 474 if (rv != BCM_E_NONE) { 475 _bcm_tr2_subport_free_resource(unit); 476 } 477 } 478 #endif /* BCM_WARM_BOOT_SUPPORT */ 479 480 /* Initialize common SUBPORT module */ 481 BCM_IF_ERROR_RETURN 482 (bcmi_subport_common_init(unit, &bcmi_tr2_subport_drv)); 483 484 return rv; 485 } 486 487 /* 488 * Function: 489 * bcm_tr2_subport_hw_clear 490 * Purpose: 491 * Cleanup the SUBPORT hw module. 492 * Parameters: 493 * unit - Device Number 494 * Returns: 495 * BCM_E_XXX 496 */ 497 STATIC int 498 _bcm_tr2_subport_hw_clear(int unit) 499 { 500 int i, rv, vp, l3_idx; 501 502 503 /* _bcm_tr2_subport_port_delete() is taking VLAN_XLATEm lock. */ 504 _TR2_SUBPORT_VP_MEM_LOCK(unit); 505 /* Delete all existing subports */ 506 for (vp = 0; vp < _TR2_SUBPORT_NUM_VP; vp++) { 507 l3_idx = _BCM_TR2_SUBPORT_ID_GET(unit, vp); 508 if (l3_idx != 0xffff) { 509 rv = _bcm_tr2_subport_port_delete(unit, l3_idx, vp); 510 if (rv < 0) { 511 _TR2_SUBPORT_VP_MEM_UNLOCK(unit); 512 return rv; 513 } 514 } 515 } 516 517 /* Delete all existing groups (Group 0 reserved).*/ 518 for (i = 1; i < _TR2_SUBPORT_NUM_GROUP; i++) { 519 if (_BCM_TR2_GROUP_USED_GET(unit, i)) { 520 rv = _bcm_tr2_subport_group_destroy(unit, (i * 8)); 521 if (rv < 0) { 522 _TR2_SUBPORT_VP_MEM_UNLOCK(unit); 523 return rv; 524 } 525 } 526 } 527 _TR2_SUBPORT_VP_MEM_UNLOCK(unit); 528 return BCM_E_NONE; 529 } 530 531 /* 532 * Function: 533 * bcm_tr2_subport_cleanup 534 * Purpose: 535 * Cleanup the SUBPORT software module 536 * Parameters: 537 * unit - Device Number 538 * Returns: 539 * BCM_E_XXX 540 */ 541 int 542 bcm_tr2_subport_cleanup(int unit) 543 { 544 int rv; /* Operation return status. */ 545 546 if (NULL == _tr2_group_bitmap[unit]) { 547 return (BCM_E_NONE); 548 } 549 550 if (0 == SOC_HW_ACCESS_DISABLE(unit)) { 551 rv = _bcm_tr2_subport_hw_clear(unit); 552 BCM_IF_ERROR_RETURN(rv); 553 } 554 555 _bcm_tr2_subport_free_resource(unit); 556 return BCM_E_NONE; 557 } 558 559 /* 560 * Function: 561 * bcm_subport_group_create 562 * Purpose: 563 * Create a subport group 564 * Parameters: 565 * unit - (IN) Device Number 566 * config - (IN) Subport group config information 567 * group - (OUT) GPORT (generic port) identifier 568 * Returns: 569 * BCM_E_XXX 570 */ 571 int 572 bcm_tr2_subport_group_create(int unit, bcm_subport_group_config_t *config, 573 bcm_gport_t *group) 574 { 575 int gport_id, rv, vp_base = -1, nh_index = -1, nh_group = -1, nh_profile_idx=0, priority; 576 initial_ing_l3_next_hop_entry_t initial_ing_nh; 577 ing_l3_next_hop_entry_t ing_nh; 578 egr_l3_next_hop_entry_t egr_nh; 579 source_vp_entry_t svp; 580 ing_dvp_table_entry_t dvp; 581 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 582 ing_dvp_2_table_entry_t dvp_2; 583 #endif 584 nhi_group_tc_profile_entry_t nhi_entry; 585 bcm_l3_egress_t nh_info; 586 uint32 nh_flags; 587 bcm_module_t mod_out, my_modid; 588 bcm_port_t port_out; 589 bcm_trunk_t trunk_id; 590 #ifdef BCM_KATANA2_SUPPORT 591 int queue_base; 592 #endif /* BCM_KATANA2_SUPPORT */ 593 594 _TR2_SUBPORT_CHECK_INIT(unit); 595 596 if ((config == NULL) || (group == NULL) || (config->vlan > BCM_VLAN_MAX)) { 597 return BCM_E_PARAM; 598 } 599 #ifdef BCM_KATANA2_SUPPORT 600 queue_base = BCM_GPORT_UCAST_SUBSCRIBER_QUEUE_GROUP_QID_GET(config->queue_base); 601 if (soc_feature(unit, soc_feature_extended_queueing)) { 602 ing_queue_map_entry_t queue_map_entry; 603 if (config->flags & BCM_SUBPORT_GROUP_QUEUE) { 604 if (queue_base != -1) { 605 if ((((config->qos_map_id >> _BCM_QOS_MAP_SHIFT) != 606 _BCM_QOS_MAP_TYPE_ING_QUEUE_OFFSET_MAP_TABLE)) || 607 ((config->qos_map_id & _BCM_QOS_MAP_TYPE_MASK) > 608 _BCM_QOS_MAP_ING_QUEUE_OFFSET_MAX)) { 609 return BCM_E_PARAM; 610 } 611 } else { 612 return BCM_E_PARAM; 613 } 614 615 /* configure queue map: base queue and map index */ 616 sal_memset(&queue_map_entry, 0, sizeof(ing_queue_map_entry_t)); 617 soc_mem_field32_set(unit, ING_QUEUE_MAPm, &queue_map_entry, 618 QUEUE_SET_BASEf, queue_base); 619 soc_mem_field32_set(unit, ING_QUEUE_MAPm, &queue_map_entry, 620 QUEUE_OFFSET_PROFILE_INDEXf, 621 (config->qos_map_id & _BCM_QOS_MAP_TYPE_MASK)); 622 /* take base queue number as ING_QUEUE_MAP entry index */ 623 BCM_IF_ERROR_RETURN(soc_mem_write(unit, ING_QUEUE_MAPm, MEM_BLOCK_ALL, 624 queue_base, &queue_map_entry)); 625 } 626 } 627 #endif /* BCM_KATANA2_SUPPORT */ 628 rv = _bcm_esw_gport_resolve(unit, config->port, &mod_out, &port_out, &trunk_id, 629 &gport_id); 630 BCM_IF_ERROR_RETURN(rv); 631 632 BCM_IF_ERROR_RETURN (bcm_esw_stk_my_modid_get(unit, &my_modid)); 633 634 if (config->flags & BCM_SUBPORT_GROUP_WITH_ID) { 635 vp_base = BCM_GPORT_SUBPORT_GROUP_GET(*group); 636 _TR2_SUBPORT_VP_MEM_LOCK(unit); 637 if ((vp_base < 0) || (vp_base > (4096 - 8))) { 638 rv = BCM_E_PARAM; 639 } else if (_BCM_TR2_GROUP_USED_GET(unit, (vp_base / 8))) { 640 rv = BCM_E_EXISTS; 641 } else { 642 _BCM_TR2_GROUP_USED_SET(unit, vp_base / 8); 643 } 644 _TR2_SUBPORT_VP_MEM_UNLOCK(unit); 645 } else { 646 /* 647 * Allocate a group of 8 consecutive VPs since 3-bit prio 648 * is added to DVP-group to get the final DVP in the L2 lookup. 649 * Only allocate from the 0 - 4k range since only 12-bits 650 * are used in the EGR_VLAN_XLATE table key. 651 * (the IVID field is used as the DVP in EGR_VLAN_XLATE) 652 */ 653 rv = _bcm_tr2_subport_vp_alloc(unit, &vp_base); 654 } 655 BCM_IF_ERROR_RETURN (rv); 656 657 for (priority=0; priority < 8; priority++) { 658 /* 659 * Allocate a next-hop entry. By calling bcm_xgs3_nh_add() 660 * with _BCM_L3_SHR_WRITE_DISABLE flag, a next-hop index is 661 * allocated but nothing is written to hardware. The "nh_info" 662 * in this case is not used, so just set to all zeros. 663 */ 664 sal_memset(&nh_info, 0, sizeof(nh_info)); 665 nh_flags = _BCM_L3_SHR_MATCH_DISABLE | _BCM_L3_SHR_WRITE_DISABLE; 666 rv = bcm_xgs3_nh_add(unit, nh_flags, &nh_info, &nh_index); 667 if (rv < 0) { 668 goto cleanup; 669 } 670 if (priority == 0) { 671 nh_group = nh_index; 672 } 673 674 /* 675 * The EGR_L3_NEXT_HOP is not actually used in the datapath. 676 * Instead, the DVP value is passed through the MMU in the 677 * IVID field. At the egress, the IVID (DVP) is used in the 678 * egress vlan translate table key. Here we use the 679 * EGR_L3_NEXT_HOP just to store the subport group's vlan 680 * for warm reboot purposes for Triumph. 681 */ 682 683 if (soc_feature(unit, soc_feature_subport_enhanced)) { 684 /* Write EGR_L3_NEXT_HOP entry */ 685 sal_memset(&egr_nh, 0, sizeof(egr_l3_next_hop_entry_t)); 686 687 if ((config->flags == BCM_SUBPORT_GROUP_TYPE_SUBPORT_PKTTAG) && 688 soc_feature(unit, soc_feature_lltag)){ 689 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 690 SD_TAG__SD_TAG_VIDf, config->vlan); 691 } else { 692 if (soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, L3__OVIDf)) 693 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, L3__OVIDf, 694 config->vlan); 695 else 696 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, OVIDf, 697 config->vlan); 698 } 699 rv = soc_mem_write(unit, EGR_L3_NEXT_HOPm, 700 MEM_BLOCK_ALL, nh_index, &egr_nh); 701 if (rv < 0) { 702 goto cleanup; 703 } 704 } 705 706 /* Write ING_L3_NEXT_HOP entry */ 707 sal_memset(&ing_nh, 0, sizeof(ing_l3_next_hop_entry_t)); 708 709 /* Set module id. */ 710 if (soc_feature(unit, soc_feature_generic_dest)) { 711 if (BCM_GPORT_IS_TRUNK(config->port)) { 712 soc_mem_field32_dest_set(unit, ING_L3_NEXT_HOPm, &ing_nh, 713 DESTINATIONf, SOC_MEM_FIF_DEST_LAG, trunk_id); 714 } else { 715 soc_mem_field32_dest_set(unit, ING_L3_NEXT_HOPm, &ing_nh, 716 DESTINATIONf, SOC_MEM_FIF_DEST_DGPP, (mod_out << 717 SOC_MEM_FIF_DGPP_MOD_ID_SHIFT_BITS | port_out)); 718 } 719 } else { 720 if (BCM_GPORT_IS_TRUNK(config->port)) { 721 soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, &ing_nh, Tf, 1); 722 soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, 723 &ing_nh, TGIDf, trunk_id); 724 } else { 725 soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, 726 &ing_nh, PORT_NUMf, port_out); 727 soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, 728 &ing_nh, MODULE_IDf, mod_out); 729 } 730 } 731 /* Use all 8 DVPs in the group except lltag suport since it uses next hop profile table 732 * to address the DVP 733 */ 734 if ((soc_feature(unit, soc_feature_lltag)) && 735 (config->flags & BCM_SUBPORT_GROUP_TYPE_SUBPORT_PKTTAG)) { 736 soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, 737 &ing_nh, DVP_RES_INFOf, 0); 738 } else { 739 soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, 740 &ing_nh, DVP_RES_INFOf, 0x7f); 741 } 742 743 if (soc_feature(unit, soc_feature_subport_enhanced)) { 744 soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, 745 &ing_nh, ENTRY_TYPEf, 0x3); /* GPON DVP */ 746 } 747 748 #ifdef BCM_KATANA2_SUPPORT 749 if (soc_feature(unit, soc_feature_extended_queueing)) { 750 if (config->flags & BCM_SUBPORT_GROUP_QUEUE) { 751 if (SOC_MEM_FIELD_VALID(unit, ING_L3_NEXT_HOPm,EH_QUEUE_TAGf)) { 752 soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, &ing_nh, 753 EH_QUEUE_TAGf, queue_base); 754 } 755 if (SOC_MEM_FIELD_VALID(unit, ING_L3_NEXT_HOPm,EH_TAG_TYPEf)) { 756 soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, &ing_nh, 757 EH_TAG_TYPEf, _EH_TAG_TYPE_ING_QUEUE_MAP); 758 } 759 } 760 } 761 #endif /* BCM_KATANA2_SUPPORT */ 762 763 rv = soc_mem_write (unit, ING_L3_NEXT_HOPm, 764 MEM_BLOCK_ALL, nh_index, &ing_nh); 765 if (rv < 0) { 766 goto cleanup; 767 } 768 769 /* Write INITIAL_ING_L3_NEXT_HOP entry */ 770 sal_memset(&initial_ing_nh, 0, sizeof(initial_ing_l3_next_hop_entry_t)); 771 772 if (soc_feature(unit, soc_feature_generic_dest)) { 773 if (BCM_GPORT_IS_TRUNK(config->port)) { 774 soc_mem_field32_dest_set(unit, INITIAL_ING_L3_NEXT_HOPm, 775 &initial_ing_nh, 776 DESTINATIONf, SOC_MEM_FIF_DEST_LAG, trunk_id); 777 } else { 778 soc_mem_field32_dest_set(unit, INITIAL_ING_L3_NEXT_HOPm, 779 &initial_ing_nh, 780 DESTINATIONf, SOC_MEM_FIF_DEST_DGPP, (mod_out << 781 SOC_MEM_FIF_DGPP_MOD_ID_SHIFT_BITS | port_out)); 782 } 783 } else { 784 if (BCM_GPORT_IS_TRUNK(config->port)) { 785 soc_mem_field32_set(unit, INITIAL_ING_L3_NEXT_HOPm, &initial_ing_nh, Tf, 1); 786 soc_mem_field32_set(unit, INITIAL_ING_L3_NEXT_HOPm, 787 &initial_ing_nh, TGIDf, trunk_id); 788 } else { 789 soc_mem_field32_set(unit, INITIAL_ING_L3_NEXT_HOPm, 790 &initial_ing_nh, PORT_NUMf, port_out); 791 soc_mem_field32_set(unit, INITIAL_ING_L3_NEXT_HOPm, 792 &initial_ing_nh, MODULE_IDf, mod_out); 793 } 794 } 795 796 rv = soc_mem_write(unit, INITIAL_ING_L3_NEXT_HOPm, 797 MEM_BLOCK_ALL, nh_index, &initial_ing_nh); 798 if (rv < 0) { 799 goto cleanup; 800 } 801 802 if (soc_feature(unit, soc_feature_subport_enhanced)) { 803 /* Write ING_DVP_TABLE entry */ 804 sal_memset(&dvp, 0, sizeof(ing_dvp_table_entry_t)); 805 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 806 if (soc_feature(unit, soc_feature_dvp_2_config_required)) { 807 sal_memset(&dvp_2, 0, sizeof(ing_dvp_2_table_entry_t)); 808 } 809 #endif 810 if ((soc_feature(unit, soc_feature_lltag)) && 811 (config->flags & BCM_SUBPORT_GROUP_TYPE_SUBPORT_PKTTAG)) { 812 soc_ING_DVP_TABLEm_field32_set(unit, &dvp, NHI_GROUPf, nh_group); 813 soc_ING_DVP_TABLEm_field32_set(unit, &dvp, NHI_GROUP_ENf, 1); 814 soc_ING_DVP_TABLEm_field32_set(unit, &dvp, TC_PROFILE_INDEXf, 0); 815 } else { 816 soc_ING_DVP_TABLEm_field32_set(unit, &dvp, NEXT_HOP_INDEXf, nh_index); 817 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 818 if (soc_feature(unit, soc_feature_dvp_2_config_required)) { 819 soc_ING_DVP_2_TABLEm_field32_set(unit, &dvp_2, NEXT_HOP_INDEXf, nh_index); 820 } 821 #endif 822 } 823 rv = WRITE_ING_DVP_TABLEm(unit, MEM_BLOCK_ALL, (vp_base+priority), &dvp); 824 if (rv < 0) { 825 goto cleanup; 826 } 827 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 828 if (soc_feature(unit, soc_feature_dvp_2_config_required)) { 829 rv = WRITE_ING_DVP_2_TABLEm(unit, MEM_BLOCK_ALL, (vp_base+priority), &dvp_2); 830 if (rv < 0) { 831 goto cleanup; 832 } 833 } 834 #endif 835 /* Write SOURCE_VP table entry */ 836 sal_memset(&svp, 0, sizeof(svp)); 837 soc_SOURCE_VPm_field32_set(unit, &svp, ENTRY_TYPEf, 0x3); /* GPON */ 838 soc_SOURCE_VPm_field32_set(unit, &svp, CLASS_IDf, config->if_class); 839 if (soc_feature(unit, soc_feature_generic_dest)) { 840 soc_mem_field32_dest_set(unit, SOURCE_VPm, &svp, 841 DESTINATIONf, SOC_MEM_FIF_DEST_DVP, vp_base); 842 } else { 843 soc_SOURCE_VPm_field32_set(unit, &svp, DVPf, vp_base); /* DVP = vp_base */ 844 } 845 846 /* Set the CML to PVP_CML_SWITCH by default (hw learn and forward) */ 847 848 soc_SOURCE_VPm_field32_set(unit, &svp, CML_FLAGS_NEWf, 0x8); 849 soc_SOURCE_VPm_field32_set(unit, &svp, CML_FLAGS_MOVEf, 0x8); 850 rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, (vp_base+priority), &svp); 851 if (rv < 0) { 852 goto cleanup; 853 } 854 } 855 } 856 857 if (mod_out == my_modid) { 858 if (_tr2_subport_group_count[unit][port_out]++ == 0) { 859 860 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 861 if (soc_feature(unit, soc_feature_egr_ipmc_cfg2_is_memory)) { 862 SOC_IF_ERROR_RETURN 863 (soc_mem_field32_modify(unit, EGR_IPMC_CFG2m, port_out, 864 DISABLE_TTL_CHECKf, 1)); 865 } else 866 #endif 867 if (SOC_REG_IS_VALID(unit, EGR_IPMC_CFG2r)) { 868 SOC_IF_ERROR_RETURN 869 (soc_reg_field32_modify(unit, EGR_IPMC_CFG2r, port_out, 870 DISABLE_TTL_CHECKf, 1)); 871 } 872 } 873 } 874 875 BCM_GPORT_SUBPORT_GROUP_SET(*group, vp_base); 876 877 #ifdef BCM_WARM_BOOT_SUPPORT 878 SOC_CONTROL_LOCK(unit); 879 SOC_CONTROL(unit)->scache_dirty = 1; 880 SOC_CONTROL_UNLOCK(unit); 881 #endif 882 883 return BCM_E_NONE; 884 885 cleanup: 886 887 for (;priority >= 0; priority--) { 888 (void) READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ALL, (vp_base+priority), &dvp); 889 if ((soc_feature(unit, soc_feature_lltag)) && 890 (config->flags & BCM_SUBPORT_GROUP_TYPE_SUBPORT_PKTTAG)) { 891 if (soc_ING_DVP_TABLEm_field32_get(unit, &dvp, NHI_GROUP_ENf)) { 892 nh_group = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, NHI_GROUPf); 893 nh_profile_idx = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, 894 TC_PROFILE_INDEXf); 895 (void) READ_NHI_GROUP_TC_PROFILEm(unit, MEM_BLOCK_ALL, 896 nh_profile_idx*16 + priority, &nhi_entry); 897 nh_index = nh_group + soc_NHI_GROUP_TC_PROFILEm_field32_get(unit, 898 &nhi_entry, NHI_OFFSETf); 899 } else { 900 nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, NEXT_HOP_INDEXf); 901 } 902 } else { 903 nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, NEXT_HOP_INDEXf); 904 } 905 906 if (nh_index != -1) { 907 nh_flags = _BCM_L3_SHR_WRITE_DISABLE; 908 (void) bcm_xgs3_nh_del(unit, nh_flags, nh_index); 909 } 910 } 911 if (vp_base != -1) { 912 (void) _bcm_tr2_subport_vp_free(unit, vp_base); 913 } 914 return rv; 915 } 916 917 STATIC int 918 _bcm_tr2_subport_group_destroy(int unit, int vp_base) 919 { 920 int i, nh_index=-1, nh_group=-1, nh_profile_idx=0, rv; 921 initial_ing_l3_next_hop_entry_t initial_ing_nh; 922 ing_l3_next_hop_entry_t ing_nh; 923 egr_l3_next_hop_entry_t egr_nh; 924 ing_dvp_table_entry_t dvp; 925 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 926 ing_dvp_2_table_entry_t dvp_2; 927 #endif 928 source_vp_entry_t svp; 929 nhi_group_tc_profile_entry_t nhi_entry; 930 bcm_port_t port = 0; 931 bcm_module_t my_modid, modid = -1; 932 933 BCM_IF_ERROR_RETURN (bcm_esw_stk_my_modid_get(unit, &my_modid)); 934 935 if (soc_feature(unit, soc_feature_subport_enhanced)) { 936 /* Get the next-hop index from the base VP */ 937 rv = READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ALL, vp_base, &dvp); 938 BCM_IF_ERROR_RETURN(rv); 939 940 if (soc_feature(unit, soc_feature_lltag)) { 941 if (soc_ING_DVP_TABLEm_field32_get(unit, &dvp, NHI_GROUP_ENf)) { 942 nh_group = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, NHI_GROUPf); 943 nh_profile_idx = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, 944 TC_PROFILE_INDEXf); 945 rv = READ_NHI_GROUP_TC_PROFILEm(unit, MEM_BLOCK_ALL, 946 nh_profile_idx*16, &nhi_entry); 947 BCM_IF_ERROR_RETURN(rv); 948 nh_index = nh_group + soc_NHI_GROUP_TC_PROFILEm_field32_get(unit, 949 &nhi_entry, NHI_OFFSETf); 950 } else { 951 nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, NEXT_HOP_INDEXf); 952 } 953 } else { 954 nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, NEXT_HOP_INDEXf); 955 } 956 957 BCM_IF_ERROR_RETURN (soc_mem_read(unit, ING_L3_NEXT_HOPm, MEM_BLOCK_ANY, 958 nh_index, &ing_nh)); 959 960 if (soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, ENTRY_TYPEf) != 0x3) { 961 /* Entry type is not GPON DVP */ 962 return BCM_E_NOT_FOUND; 963 } 964 } 965 966 if (soc_feature(unit, soc_feature_subport_enhanced)) { 967 968 for (i = 0; i < 8; i++) { 969 970 /* Obtain nh_index from DVP_TABLE entry */ 971 rv = READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ALL, (vp_base + i), &dvp); 972 BCM_IF_ERROR_RETURN(rv); 973 if (soc_feature(unit, soc_feature_lltag)) { 974 if (soc_ING_DVP_TABLEm_field32_get(unit, &dvp, NHI_GROUP_ENf)) { 975 nh_group = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, NHI_GROUPf); 976 nh_profile_idx = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, 977 TC_PROFILE_INDEXf); 978 rv = READ_NHI_GROUP_TC_PROFILEm(unit, MEM_BLOCK_ALL, 979 nh_profile_idx*16 + i, &nhi_entry); 980 BCM_IF_ERROR_RETURN(rv); 981 nh_index = nh_group + soc_NHI_GROUP_TC_PROFILEm_field32_get(unit, 982 &nhi_entry, NHI_OFFSETf); 983 } else { 984 nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, 985 NEXT_HOP_INDEXf); 986 } 987 } else { 988 nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, NEXT_HOP_INDEXf); 989 } 990 /* Clear EGR_L3_NEXT_HOP entry */ 991 sal_memset(&egr_nh, 0, sizeof(egr_l3_next_hop_entry_t)); 992 rv = soc_mem_write(unit, EGR_L3_NEXT_HOPm, 993 MEM_BLOCK_ALL, nh_index, &egr_nh); 994 BCM_IF_ERROR_RETURN(rv); 995 996 /* Get the modid/port number from ING_L3_NEXT_HOP entry */ 997 rv = soc_mem_read(unit, ING_L3_NEXT_HOPm, 998 MEM_BLOCK_ALL, nh_index, &ing_nh); 999 BCM_IF_ERROR_RETURN(rv); 1000 if (soc_feature(unit, soc_feature_generic_dest)) { 1001 uint32 dest_type = SOC_MEM_FIF_DEST_INVALID, dest = 0; 1002 dest = soc_mem_field32_dest_get(unit, ING_L3_NEXT_HOPm, &ing_nh, 1003 DESTINATIONf, &dest_type); 1004 if (dest_type == SOC_MEM_FIF_DEST_DGPP) { 1005 port = (dest & SOC_MEM_FIF_DGPP_PORT_MASK); 1006 modid = (dest & SOC_MEM_FIF_DGPP_MOD_ID_MASK) >> 1007 SOC_MEM_FIF_DGPP_MOD_ID_SHIFT_BITS; 1008 } 1009 } else { 1010 modid = soc_mem_field32_get(unit, ING_L3_NEXT_HOPm, 1011 &ing_nh, MODULE_IDf); 1012 port = soc_mem_field32_get(unit, ING_L3_NEXT_HOPm, 1013 &ing_nh, PORT_NUMf); 1014 } 1015 if (modid == my_modid) { 1016 if (--_tr2_subport_group_count[unit][port] == 0) { 1017 1018 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 1019 if (soc_feature(unit, soc_feature_egr_ipmc_cfg2_is_memory)) { 1020 SOC_IF_ERROR_RETURN 1021 (soc_mem_field32_modify(unit, EGR_IPMC_CFG2m, port, 1022 DISABLE_TTL_CHECKf, 1)); 1023 } else 1024 #endif 1025 if (SOC_REG_IS_VALID(unit, EGR_IPMC_CFG2r)) { 1026 SOC_IF_ERROR_RETURN 1027 (soc_reg_field32_modify(unit, EGR_IPMC_CFG2r, 1028 port, DISABLE_TTL_CHECKf, 0)); 1029 } 1030 } 1031 } 1032 1033 #ifdef BCM_KATANA2_SUPPORT 1034 if (soc_feature(unit, soc_feature_extended_queueing)) { 1035 ing_queue_map_entry_t queue_map_entry; 1036 int queue_base; 1037 if (_EH_TAG_TYPE_ING_QUEUE_MAP == soc_mem_field32_get(unit, 1038 ING_L3_NEXT_HOPm, &ing_nh, EH_TAG_TYPEf)) { 1039 /* Clear ING_QUEUE_MAP entry */ 1040 sal_memset(&queue_map_entry, 0, sizeof(ing_queue_map_entry_t)); 1041 queue_base = soc_mem_field32_get(unit, ING_L3_NEXT_HOPm, 1042 &ing_nh, EH_QUEUE_TAGf); 1043 BCM_IF_ERROR_RETURN(soc_mem_write (unit, ING_QUEUE_MAPm, 1044 MEM_BLOCK_ALL, queue_base, &queue_map_entry)); 1045 } 1046 } 1047 #endif /* BCM_KATANA2_SUPPORT */ 1048 1049 /* Clear ING_L3_NEXT_HOP entry */ 1050 sal_memset(&ing_nh, 0, sizeof(ing_l3_next_hop_entry_t)); 1051 rv = soc_mem_write (unit, ING_L3_NEXT_HOPm, 1052 MEM_BLOCK_ALL, nh_index, &ing_nh); 1053 BCM_IF_ERROR_RETURN(rv); 1054 1055 /* Clear INITIAL_ING_L3_NEXT_HOP entry */ 1056 sal_memset(&initial_ing_nh, 0, sizeof(initial_ing_l3_next_hop_entry_t)); 1057 rv = soc_mem_write(unit, INITIAL_ING_L3_NEXT_HOPm, 1058 MEM_BLOCK_ALL, nh_index, &initial_ing_nh); 1059 BCM_IF_ERROR_RETURN(rv); 1060 1061 1062 /* Free the next-hop index */ 1063 rv = bcm_xgs3_nh_del(unit, _BCM_L3_SHR_WRITE_DISABLE, nh_index); 1064 BCM_IF_ERROR_RETURN(rv); 1065 1066 /* Clear SOURCE_VP table entry */ 1067 sal_memset(&svp, 0, sizeof(svp)); 1068 rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, (vp_base+i), &svp); 1069 BCM_IF_ERROR_RETURN(rv); 1070 1071 /* Clear ING_DVP_TABLE entry */ 1072 sal_memset(&dvp, 0, sizeof(dvp)); 1073 rv = WRITE_ING_DVP_TABLEm(unit, MEM_BLOCK_ALL, (vp_base+i), &dvp); 1074 BCM_IF_ERROR_RETURN(rv); 1075 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 1076 if (soc_feature(unit, soc_feature_dvp_2_config_required)) { 1077 sal_memset(&dvp_2, 0, sizeof(dvp_2)); 1078 rv = WRITE_ING_DVP_2_TABLEm(unit, MEM_BLOCK_ALL, (vp_base+i), &dvp_2); 1079 BCM_IF_ERROR_RETURN(rv); 1080 } 1081 #endif 1082 } 1083 } 1084 1085 if (soc_feature(unit, soc_feature_gport_service_counters)) { 1086 bcm_gport_t gport; 1087 1088 /* Release Service counter, if any */ 1089 BCM_GPORT_SUBPORT_GROUP_SET(gport, vp_base); 1090 _bcm_esw_flex_stat_handle_free(unit, _bcmFlexStatTypeGport, gport); 1091 } 1092 1093 /* Free the VP */ 1094 rv = _bcm_tr2_subport_vp_free(unit, vp_base); 1095 BCM_IF_ERROR_RETURN(rv); 1096 1097 #ifdef BCM_WARM_BOOT_SUPPORT 1098 SOC_CONTROL_LOCK(unit); 1099 SOC_CONTROL(unit)->scache_dirty = 1; 1100 SOC_CONTROL_UNLOCK(unit); 1101 #endif 1102 1103 return rv; 1104 } 1105 1106 /* 1107 * Function: 1108 * bcm_subport_group_destroy 1109 * Purpose: 1110 * Destroy a subport group 1111 * Parameters: 1112 * unit - (IN) Device Number 1113 * group - (IN) GPORT (generic port) identifier 1114 * Returns: 1115 * BCM_E_XXX 1116 */ 1117 int 1118 bcm_tr2_subport_group_destroy(int unit, bcm_gport_t group) 1119 { 1120 int vp_base; 1121 1122 _TR2_SUBPORT_CHECK_INIT(unit); 1123 1124 vp_base = BCM_GPORT_SUBPORT_GROUP_GET(group); 1125 if (vp_base == -1) { 1126 return BCM_E_PARAM; 1127 } 1128 1129 return _bcm_tr2_subport_group_destroy(unit, vp_base); 1130 } 1131 1132 /* 1133 * Function: 1134 * bcm_subport_group_get 1135 * Purpose: 1136 * Get a subport group 1137 * Parameters: 1138 * unit - (IN) Device Number 1139 * group - (IN) GPORT (generic port) identifier 1140 * config - (OUT) Subport group config information 1141 * Returns: 1142 * BCM_E_XXX 1143 */ 1144 int 1145 bcm_tr2_subport_group_get(int unit, bcm_gport_t group, 1146 bcm_subport_group_config_t *config) 1147 { 1148 int rv = BCM_E_NONE; 1149 egr_l3_next_hop_entry_t egr_nh; 1150 ing_l3_next_hop_entry_t ing_nh; 1151 ing_dvp_table_entry_t dvp; 1152 source_vp_entry_t svp; 1153 nhi_group_tc_profile_entry_t nhi_entry; 1154 int nh_index = -1, nh_group = -1, nh_profile_idx = 0, vp_base; 1155 bcm_port_t port_in, port_out; 1156 bcm_module_t mod_in, mod_out; 1157 bcm_trunk_t trunk_id; 1158 1159 _TR2_SUBPORT_CHECK_INIT(unit); 1160 1161 if (config == NULL) { 1162 return BCM_E_PARAM; 1163 } 1164 1165 vp_base = BCM_GPORT_SUBPORT_GROUP_GET(group); 1166 if (vp_base == -1) { 1167 return BCM_E_PARAM; 1168 } 1169 1170 if (soc_feature(unit, soc_feature_subport_enhanced)) { 1171 rv = READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ALL, vp_base, &dvp); 1172 BCM_IF_ERROR_RETURN(rv); 1173 if (soc_feature(unit, soc_feature_lltag)) { 1174 if (soc_ING_DVP_TABLEm_field32_get(unit, &dvp, NHI_GROUP_ENf)) { 1175 nh_group = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, NHI_GROUPf); 1176 nh_profile_idx = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, 1177 TC_PROFILE_INDEXf); 1178 rv = READ_NHI_GROUP_TC_PROFILEm(unit, MEM_BLOCK_ALL, 1179 nh_profile_idx*16, &nhi_entry); 1180 BCM_IF_ERROR_RETURN(rv); 1181 nh_index = nh_group + soc_NHI_GROUP_TC_PROFILEm_field32_get(unit, 1182 &nhi_entry, NHI_OFFSETf); 1183 config->flags |= BCM_SUBPORT_GROUP_TYPE_SUBPORT_PKTTAG; 1184 } else { 1185 nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, NEXT_HOP_INDEXf); 1186 } 1187 } else { 1188 nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, NEXT_HOP_INDEXf); 1189 } 1190 nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, NEXT_HOP_INDEXf); 1191 BCM_IF_ERROR_RETURN (soc_mem_read(unit, ING_L3_NEXT_HOPm, MEM_BLOCK_ANY, 1192 nh_index, &ing_nh)); 1193 1194 if (soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, ENTRY_TYPEf) != 0x3) { 1195 /* Entry type is not GPON DVP */ 1196 return BCM_E_NOT_FOUND; 1197 } 1198 } 1199 1200 /* Get the physical gport information from the ingress next-hop entry */ 1201 if (soc_feature(unit, soc_feature_generic_dest)) { 1202 uint32 dest_type, dest; 1203 dest = soc_mem_field32_dest_get(unit, ING_L3_NEXT_HOPm, 1204 &ing_nh, DESTINATIONf, &dest_type); 1205 if (dest_type == SOC_MEM_FIF_DEST_LAG) { 1206 trunk_id = (dest & SOC_MEM_FIF_DGPP_TGID_MASK); 1207 BCM_GPORT_TRUNK_SET(config->port, trunk_id); 1208 } else { 1209 port_in = (dest & SOC_MEM_FIF_DGPP_PORT_MASK); 1210 mod_in = (dest & SOC_MEM_FIF_DGPP_MOD_ID_MASK) >> 1211 SOC_MEM_FIF_DGPP_MOD_ID_SHIFT_BITS; 1212 BCM_IF_ERROR_RETURN(_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, 1213 mod_in, port_in, 1214 &mod_out, &port_out)); 1215 BCM_GPORT_MODPORT_SET(config->port, mod_out, port_out); 1216 } 1217 } else { 1218 if (soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, Tf)) { 1219 trunk_id = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, TGIDf); 1220 BCM_GPORT_TRUNK_SET(config->port, trunk_id); 1221 } else { 1222 mod_in = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, MODULE_IDf); 1223 port_in = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, PORT_NUMf); 1224 BCM_IF_ERROR_RETURN(_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, 1225 mod_in, port_in, 1226 &mod_out, &port_out)); 1227 BCM_GPORT_MODPORT_SET(config->port, mod_out, port_out); 1228 } 1229 } 1230 1231 if (soc_feature(unit, soc_feature_subport_enhanced)) { 1232 /* Get the group's OVID from the group's egress next-hop entry */ 1233 rv = soc_mem_read(unit, EGR_L3_NEXT_HOPm, 1234 MEM_BLOCK_ALL, nh_index, &egr_nh); 1235 BCM_IF_ERROR_RETURN(rv); 1236 if ((config->flags & BCM_SUBPORT_GROUP_TYPE_SUBPORT_PKTTAG) && 1237 soc_feature(unit, soc_feature_lltag)) { 1238 config->vlan = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, 1239 SD_TAG__SD_TAG_VIDf); 1240 } else { 1241 if (soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, L3__OVIDf)) { 1242 config->vlan = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, L3__OVIDf); 1243 } else { 1244 config->vlan = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, OVIDf); 1245 } 1246 } 1247 } 1248 1249 if (soc_feature(unit, soc_feature_subport_enhanced)) { 1250 /* Get the class-ID from the SOURCE_VP table entry */ 1251 rv = READ_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp_base, &svp); 1252 BCM_IF_ERROR_RETURN(rv); 1253 config->if_class = soc_SOURCE_VPm_field32_get(unit, &svp, CLASS_IDf); 1254 } 1255 1256 #ifdef BCM_KATANA2_SUPPORT 1257 if (soc_feature(unit, soc_feature_extended_queueing)) { 1258 ing_queue_map_entry_t queue_map_entry; 1259 int queue_base; 1260 if (_EH_TAG_TYPE_ING_QUEUE_MAP == soc_mem_field32_get(unit, 1261 ING_L3_NEXT_HOPm, &ing_nh, EH_TAG_TYPEf)) { 1262 config->flags |= BCM_SUBPORT_GROUP_QUEUE; 1263 queue_base = soc_mem_field32_get(unit, ING_L3_NEXT_HOPm, 1264 &ing_nh, EH_QUEUE_TAGf); 1265 BCM_GPORT_UCAST_SUBSCRIBER_QUEUE_GROUP_SYSQID_SET(config->queue_base, 1266 config->port, queue_base); 1267 BCM_IF_ERROR_RETURN(soc_mem_read(unit, ING_QUEUE_MAPm, MEM_BLOCK_ANY, 1268 queue_base, &queue_map_entry)); 1269 config->qos_map_id = soc_mem_field32_get(unit, ING_QUEUE_MAPm, 1270 &queue_map_entry, QUEUE_OFFSET_PROFILE_INDEXf) | 1271 (_BCM_QOS_MAP_TYPE_ING_QUEUE_OFFSET_MAP_TABLE << _BCM_QOS_MAP_SHIFT); 1272 } 1273 } 1274 #endif /* BCM_KATANA2_SUPPORT */ 1275 1276 return BCM_E_NONE; 1277 } 1278 1279 /* 1280 * Function: 1281 * bcm_subport_port_add 1282 * Purpose: 1283 * Add a subport to a subport group 1284 * Parameters: 1285 * unit - (IN) Device Number 1286 * config - (IN) Subport config information 1287 * port - (OUT) GPORT (generic port) identifier 1288 * Returns: 1289 * BCM_E_XXX 1290 */ 1291 int 1292 bcm_tr2_subport_port_add(int unit, bcm_subport_config_t *config, 1293 bcm_gport_t *port) 1294 { 1295 int rv, l3_idx = -1, nh_index=-1, vp_base, vp; 1296 int nh_group=-1, nh_profile_idx=0; 1297 ing_dvp_table_entry_t dvp; 1298 source_vp_entry_t svp; 1299 egr_l3_next_hop_entry_t egr_nh; 1300 ing_l3_next_hop_entry_t ing_nh; 1301 egr_l3_intf_entry_t l3_intf; 1302 nhi_group_tc_profile_entry_t nhi_entry; 1303 port_tab_entry_t port_tab; 1304 bcm_vlan_t ovid = 0; 1305 bcm_port_t local_port = 0; 1306 bcm_module_t my_modid, modid = 0; 1307 bcm_vlan_action_set_t action; 1308 uint32 egr_profile_idx = 0xffffffff; 1309 uint32 ing_profile_idx = 0xffffffff; 1310 int key_type_value; 1311 uint32 egr_vent[SOC_MAX_MEM_FIELD_WORDS]; /* HW entry buffer. */ 1312 uint32 ing_vent[SOC_MAX_MEM_FIELD_WORDS]; /* HW entry buffer. */ 1313 soc_mem_t egr_mem = EGR_VLAN_XLATEm, ing_mem = VLAN_XLATEm; 1314 1315 sal_memset(egr_vent, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32)); 1316 sal_memset(ing_vent, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32)); 1317 1318 1319 _TR2_SUBPORT_CHECK_INIT(unit); 1320 1321 if ((config->int_pri < 0) || (config->int_pri > 7)) { 1322 return BCM_E_PARAM; 1323 } 1324 1325 /* Check Vlan range */ 1326 if ((config->pkt_vlan >= BCM_VLAN_INVALID) || ( config->pkt_vlan == BCM_VLAN_DEFAULT)) { 1327 return BCM_E_PARAM; 1328 } 1329 1330 if ((config->criteria == BCM_SUBPORT_MATCH_PKT_VID_OUTER_VLAN) && 1331 ((config->outer_vlan >= BCM_VLAN_INVALID) || 1332 ( config->outer_vlan == BCM_VLAN_DEFAULT))) { 1333 return BCM_E_PARAM; 1334 } 1335 1336 if ((config->criteria == BCM_SUBPORT_MATCH_PKT_VID_INNER_VLAN) && 1337 ((config->inner_vlan >= BCM_VLAN_INVALID) || 1338 ( config->inner_vlan == BCM_VLAN_DEFAULT))) { 1339 return BCM_E_PARAM; 1340 } 1341 1342 BCM_IF_ERROR_RETURN (bcm_esw_stk_my_modid_get(unit, &my_modid)); 1343 1344 /* Make sure the group exists */ 1345 vp_base = BCM_GPORT_SUBPORT_GROUP_GET(config->group); 1346 if (vp_base == -1) { 1347 return BCM_E_PARAM; 1348 } 1349 1350 if (!_BCM_TR2_GROUP_USED_GET(unit, vp_base / 8)) { 1351 return BCM_E_NOT_FOUND; 1352 } 1353 1354 /* See if this entry already exists */ 1355 vp = vp_base + config->int_pri; 1356 if (_BCM_TR2_SUBPORT_ID_GET(unit, vp) != 0xffff) { 1357 return BCM_E_EXISTS; 1358 } 1359 1360 1361 /* ***************************************************** */ 1362 /* --- Get the group's NHI from ING_DVP_TABLE--------------- */ 1363 /* ***************************************************** */ 1364 1365 1366 if (soc_feature(unit, soc_feature_subport_enhanced)) { 1367 rv = READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ALL, vp_base, &dvp); 1368 BCM_IF_ERROR_RETURN(rv); 1369 if (soc_feature(unit, soc_feature_lltag)) { 1370 if (soc_ING_DVP_TABLEm_field32_get(unit, &dvp, NHI_GROUP_ENf)) { 1371 nh_group = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, NHI_GROUPf); 1372 nh_profile_idx = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, 1373 TC_PROFILE_INDEXf); 1374 rv = READ_NHI_GROUP_TC_PROFILEm(unit, MEM_BLOCK_ALL, 1375 nh_profile_idx*16, &nhi_entry); 1376 BCM_IF_ERROR_RETURN(rv); 1377 nh_index = nh_group + soc_NHI_GROUP_TC_PROFILEm_field32_get(unit, 1378 &nhi_entry, NHI_OFFSETf); 1379 } else { 1380 nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, NEXT_HOP_INDEXf); 1381 } 1382 } else { 1383 nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, NEXT_HOP_INDEXf); 1384 } 1385 } 1386 1387 if (nh_index == -1) { 1388 return BCM_E_INTERNAL; 1389 } 1390 1391 /* Get the modid and port_class for the destination port */ 1392 rv = soc_mem_read(unit, ING_L3_NEXT_HOPm, 1393 MEM_BLOCK_ALL, nh_index, &ing_nh); 1394 if (rv < 0) { 1395 goto cleanup; 1396 } 1397 1398 if (soc_feature(unit, soc_feature_generic_dest)) { 1399 uint32 dt, dv; 1400 dv = soc_mem_field32_dest_get(unit, ING_L3_NEXT_HOPm, 1401 &ing_nh, DESTINATIONf, &dt); 1402 if (dt != SOC_MEM_FIF_DEST_LAG) { 1403 modid = (dv & SOC_MEM_FIF_DGPP_MOD_ID_MASK) >> 1404 SOC_MEM_FIF_DGPP_MOD_ID_SHIFT_BITS; 1405 if (modid != my_modid) { 1406 /* No local state is required for groups on remoted devices */ 1407 return BCM_E_NONE; 1408 } 1409 local_port = dv & SOC_MEM_FIF_DGPP_PORT_MASK; 1410 } 1411 } else { 1412 if (!soc_mem_field32_get(unit, ING_L3_NEXT_HOPm, &ing_nh, Tf)) { 1413 modid = soc_mem_field32_get(unit, ING_L3_NEXT_HOPm, &ing_nh, MODULE_IDf); 1414 if (modid != my_modid) { 1415 /* No local state is required for groups on remoted devices */ 1416 return BCM_E_NONE; 1417 } 1418 local_port = soc_mem_field32_get(unit, ING_L3_NEXT_HOPm, 1419 &ing_nh, PORT_NUMf); 1420 /* TBD: Algorithm to compute DVP_RES_INFO */ 1421 } 1422 } 1423 /* Get the group's OVID from the group's egress next-hop entry */ 1424 rv = soc_mem_read(unit, EGR_L3_NEXT_HOPm, 1425 MEM_BLOCK_ALL, nh_index, &egr_nh); 1426 if (rv < 0) { 1427 goto cleanup; 1428 } 1429 1430 if ((soc_feature(unit, soc_feature_lltag)) && 1431 (config->criteria > BCM_SUBPORT_MATCH_INVALID) && 1432 (config->criteria < BCM_SUBPORT_MATCH_COUNT)) { 1433 ovid = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, 1434 SD_TAG__SD_TAG_VIDf); 1435 } else { 1436 if (soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, L3__OVIDf)) 1437 ovid = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, L3__OVIDf); 1438 else 1439 ovid = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, OVIDf); 1440 } 1441 /* *********************************************************** */ 1442 /* ---- For each Priority, Update the fields within EGR_L3_NEXT_HOP ---- */ 1443 /* *********************************************************** */ 1444 1445 if (soc_feature(unit, soc_feature_subport_enhanced)) { 1446 /* Obtain the nh_index from DVP_Table for each Priority */ 1447 rv = READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ALL, (vp_base + config->int_pri), &dvp); 1448 BCM_IF_ERROR_RETURN(rv); 1449 if (soc_feature(unit, soc_feature_lltag)) { 1450 if (soc_ING_DVP_TABLEm_field32_get(unit, &dvp, NHI_GROUP_ENf)) { 1451 nh_group = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, NHI_GROUPf); 1452 nh_profile_idx = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, 1453 TC_PROFILE_INDEXf); 1454 rv = READ_NHI_GROUP_TC_PROFILEm(unit, MEM_BLOCK_ALL, 1455 nh_profile_idx*16 + config->int_pri, &nhi_entry); 1456 BCM_IF_ERROR_RETURN(rv); 1457 nh_index = nh_group + soc_NHI_GROUP_TC_PROFILEm_field32_get(unit, 1458 &nhi_entry, NHI_OFFSETf); 1459 } else { 1460 nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, NEXT_HOP_INDEXf); 1461 } 1462 } else { 1463 nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, NEXT_HOP_INDEXf); 1464 } 1465 1466 rv = soc_mem_read(unit, EGR_L3_NEXT_HOPm, 1467 MEM_BLOCK_ALL, nh_index, &egr_nh); 1468 BCM_IF_ERROR_RETURN(rv); 1469 #if defined(BCM_TRIDENT3_SUPPORT) 1470 if (SOC_MEM_FIELD_VALID(unit, EGR_L3_NEXT_HOPm, DATA_TYPEf)) { 1471 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, DATA_TYPEf, 2); 1472 } else 1473 #endif 1474 { 1475 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 1476 &egr_nh, ENTRY_TYPEf, 0x2); 1477 } 1478 if (soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, DVPf)) { 1479 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 1480 &egr_nh, DVPf, (vp_base + config->int_pri)); 1481 } else { /* use SD_TAG view becuase the ENTRY_TYPE is 2 */ 1482 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 1483 &egr_nh, SD_TAG__DVPf, 1484 (vp_base + config->int_pri)); 1485 } 1486 if (soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, HG_HDR_SELf)) { 1487 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, HG_HDR_SELf, 1488 1); 1489 } else { /* use SD_TAG view becuase the ENTRY_TYPE is 2 */ 1490 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 1491 SD_TAG__HG_HDR_SELf, 1); 1492 } 1493 1494 if ((soc_feature(unit, soc_feature_lltag)) && 1495 (config->criteria > BCM_SUBPORT_MATCH_INVALID) && 1496 (config->criteria < BCM_SUBPORT_MATCH_COUNT)) { 1497 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 1498 SD_TAG__SD_TAG_VIDf, ovid); 1499 } 1500 1501 rv = soc_mem_write(unit, EGR_L3_NEXT_HOPm, 1502 MEM_BLOCK_ALL, nh_index, &egr_nh); 1503 if (rv < 0) { 1504 goto cleanup; 1505 } 1506 } 1507 1508 /* 1509 * For each subport, we need to allocate an L3_INTF entry. 1510 * This is needed for multicast replication. MMU replicates 1511 * multicast packets to each subport by sending a copy to 1512 * the subport's L3_INTF index. 1513 */ 1514 1515 /* Search for unused index. */ 1516 MEM_LOCK(unit, EGR_L3_INTFm); 1517 for (l3_idx = 0; l3_idx < BCM_XGS3_L3_IF_TBL_SIZE(unit); l3_idx++) { 1518 /* Check if interface index is used. */ 1519 if (!BCM_L3_INTF_USED_GET(unit, l3_idx)) { 1520 /* Free index found. */ 1521 BCM_L3_INTF_USED_SET(unit, l3_idx); 1522 break; 1523 } 1524 } 1525 if (l3_idx == BCM_XGS3_L3_IF_TBL_SIZE(unit)) { 1526 MEM_UNLOCK(unit, EGR_L3_INTFm); 1527 return BCM_E_FULL; 1528 } 1529 1530 /* Write EGR_L3_INTF entry */ 1531 sal_memset(&l3_intf, 0, sizeof(egr_l3_intf_entry_t)); 1532 soc_mem_field32_set(unit, EGR_L3_INTFm, &l3_intf, OVIDf, ovid); 1533 1534 /* IVID field is used as the DVP */ 1535 if (soc_feature(unit, soc_feature_subport_enhanced)) { 1536 soc_mem_field32_set(unit, EGR_L3_INTFm, &l3_intf, IVIDf, vp); 1537 } 1538 1539 if (soc_mem_field_valid(unit, EGR_L3_INTFm, IVID_VALIDf)) { 1540 soc_mem_field32_set(unit, EGR_L3_INTFm, &l3_intf, IVID_VALIDf, 1); 1541 } else { 1542 soc_mem_field32_set(unit, EGR_L3_INTFm, &l3_intf, IVID_PRESENT_ACTIONf, 1543 1); 1544 soc_mem_field32_set(unit, EGR_L3_INTFm, &l3_intf, IVID_ABSENT_ACTIONf, 1545 1); 1546 } 1547 rv = soc_mem_write(unit, EGR_L3_INTFm, MEM_BLOCK_ALL, l3_idx, &l3_intf); 1548 if (rv < 0) { 1549 MEM_UNLOCK(unit, EGR_L3_INTFm); 1550 goto cleanup; 1551 } 1552 MEM_UNLOCK(unit, EGR_L3_INTFm); 1553 1554 /* the LLTAG subport uses EGR_L3_NEXT_HOP table instead of EGR_VLAN_XLATE table 1555 * to add LLTAG 1556 */ 1557 if (soc_feature(unit, soc_feature_lltag) && 1558 ((config->criteria == BCM_SUBPORT_MATCH_PKT_VID) || 1559 (config->criteria == BCM_SUBPORT_MATCH_PKT_VID_INNER_VLAN) || 1560 (config->criteria == BCM_SUBPORT_MATCH_PKT_VID_OUTER_VLAN))) { 1561 /* Obtain the nh_index from DVP_Table for each Priority */ 1562 rv = soc_mem_read(unit, EGR_L3_NEXT_HOPm, 1563 MEM_BLOCK_ALL, nh_index, &egr_nh); 1564 BCM_IF_ERROR_RETURN(rv); 1565 1566 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, ENTRY_TYPEf, 0x2); 1567 1568 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, SD_TAG__DVPf, 1569 (vp_base + config->int_pri)); 1570 1571 /* use SD_TAG view becuase the ENTRY_TYPE is 2 */ 1572 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 1573 SD_TAG__HG_HDR_SELf, 1); 1574 1575 /* Must set DVP to 0 to avoid the Entry type being forced to 0 */ 1576 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 1577 SD_TAG__DVPf, 0); 1578 1579 /* Add the LLTAG for outgoing packets */ 1580 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 1581 SD_TAG__LLTAG_VIDf, config->pkt_vlan); 1582 1583 /* Set the LLTAG ACTION as ADDLLTAG */ 1584 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 1585 SD_TAG__LLTAG_ACTIONSf, 0x04); 1586 1587 rv = soc_mem_write(unit, EGR_L3_NEXT_HOPm, 1588 MEM_BLOCK_ALL, nh_index, &egr_nh); 1589 BCM_IF_ERROR_RETURN(rv); 1590 /*use DVP in SOURCE_VP table to store the match inner VLAN or outer VLAN. */ 1591 rv = soc_mem_read(unit, SOURCE_VPm, 1592 MEM_BLOCK_ALL, vp_base + config->int_pri, &svp); 1593 BCM_IF_ERROR_RETURN(rv); 1594 if (config->criteria == BCM_SUBPORT_MATCH_PKT_VID_INNER_VLAN) { 1595 soc_mem_field32_set(unit, SOURCE_VPm, &svp, 1596 DVPf, config->inner_vlan); 1597 } else if (config->criteria == BCM_SUBPORT_MATCH_PKT_VID_OUTER_VLAN) { 1598 soc_mem_field32_set(unit, SOURCE_VPm, &svp, 1599 DVPf, config->outer_vlan); 1600 } 1601 rv = soc_mem_write(unit, SOURCE_VPm, 1602 MEM_BLOCK_ALL, vp_base + config->int_pri, &svp); 1603 if (rv < 0) { 1604 goto cleanup; 1605 } 1606 } else { 1607 /* ************************* */ 1608 /* Write EGR_VLAN_XLATE table */ 1609 /* ************************* */ 1610 1611 bcm_vlan_action_set_t_init(&action); 1612 /* Create a profile entry that replaces the outer vid 1613 * with the new 16-bit vlan tag. 1614 */ 1615 action.ot_outer = bcmVlanActionReplace; 1616 action.dt_outer = bcmVlanActionReplace; 1617 action.dt_inner = bcmVlanActionDelete; 1618 rv = _bcm_trx_egr_vlan_action_profile_entry_add(unit, &action, &egr_profile_idx); 1619 if (rv < 0) { 1620 goto cleanup; 1621 } 1622 #ifdef BCM_TRIDENT3_SUPPORT 1623 if (SOC_MEM_IS_VALID(unit, EGR_VLAN_XLATE_1_DOUBLEm)) { 1624 egr_mem = EGR_VLAN_XLATE_1_DOUBLEm; 1625 } else 1626 #endif 1627 { 1628 egr_mem = EGR_VLAN_XLATEm; 1629 } 1630 #ifdef BCM_TRIDENT3_SUPPORT 1631 if (soc_feature(unit, soc_feature_base_valid)) { 1632 soc_mem_field32_set(unit, egr_mem, egr_vent, BASE_VALID_0f, 3); 1633 soc_mem_field32_set(unit, egr_mem, egr_vent, BASE_VALID_1f, 7); 1634 soc_mem_field32_set(unit, egr_mem, egr_vent, KEY_TYPEf, 0x01); 1635 soc_mem_field32_set(unit, egr_mem, egr_vent, DATA_TYPEf, 1); 1636 } else 1637 #endif 1638 { 1639 soc_mem_field32_set(unit, egr_mem, egr_vent, VALIDf, 1); 1640 #ifdef BCM_TRIUMPH3_SUPPORT 1641 if (SOC_IS_TRIUMPH3(unit)) { 1642 soc_mem_field32_set(unit, egr_mem, egr_vent, KEY_TYPEf, 0x01); 1643 } else 1644 #endif 1645 { 1646 soc_mem_field32_set(unit, egr_mem, egr_vent, ENTRY_TYPEf, 0x01); 1647 } 1648 } 1649 1650 soc_mem_field32_set(unit, egr_mem, egr_vent, OVIDf, ovid); 1651 soc_mem_field32_set(unit, egr_mem, egr_vent, DVPf, (vp_base + config->int_pri)); 1652 1653 soc_mem_field32_set(unit, egr_mem, egr_vent, TAG_ACTION_PROFILE_PTRf, egr_profile_idx); 1654 soc_mem_field32_set(unit, egr_mem, egr_vent, NEW_OTAG_VPTAGf, config->pkt_vlan); 1655 soc_mem_field32_set(unit, egr_mem, egr_vent, NEW_OTAG_VPTAG_SELf, 1); 1656 1657 rv = soc_mem_insert_return_old(unit, egr_mem, MEM_BLOCK_ALL, 1658 egr_vent, egr_vent); 1659 if (rv == SOC_E_EXISTS) { 1660 /* Delete the old vlan translate profile entry */ 1661 1662 egr_profile_idx = soc_mem_field32_get(unit, egr_mem, egr_vent, 1663 TAG_ACTION_PROFILE_PTRf); 1664 rv = _bcm_trx_egr_vlan_action_profile_entry_delete(unit, egr_profile_idx); 1665 } 1666 1667 if (rv < 0) { 1668 goto cleanup; 1669 } 1670 } 1671 /* ************************** */ 1672 /* Write Ingress VLAN_XLATE table */ 1673 /* ************************** */ 1674 bcm_vlan_action_set_t_init(&action); 1675 switch (config->criteria) { 1676 case BCM_SUBPORT_MATCH_PKT_VID: 1677 action.ut_outer = bcmVlanActionAdd; 1678 action.ut_outer_pkt_prio = bcmVlanActionAdd; 1679 action.ot_outer = bcmVlanActionReplace; 1680 action.ot_outer_prio = bcmVlanActionAdd; 1681 action.ot_outer_pkt_prio = bcmVlanActionReplace; 1682 action.dt_outer = bcmVlanActionReplace; 1683 action.dt_outer_prio = bcmVlanActionAdd; 1684 action.dt_outer_pkt_prio = bcmVlanActionReplace; 1685 break; 1686 case BCM_SUBPORT_MATCH_PKT_VID_INNER_VLAN: 1687 action.ut_outer = bcmVlanActionAdd; 1688 action.ut_outer_pkt_prio = bcmVlanActionAdd; 1689 action.ot_outer = bcmVlanActionReplace; 1690 action.ot_outer_prio = bcmVlanActionAdd; 1691 action.ot_outer_pkt_prio = bcmVlanActionReplace; 1692 action.dt_outer = bcmVlanActionReplace; 1693 action.dt_outer_prio = bcmVlanActionAdd; 1694 action.dt_outer_pkt_prio = bcmVlanActionReplace; 1695 action.it_outer = bcmVlanActionAdd; 1696 action.it_outer_pkt_prio = bcmVlanActionAdd; 1697 action.it_inner = bcmVlanActionDelete; 1698 action.it_inner_prio = bcmVlanActionDelete; 1699 action.dt_inner = bcmVlanActionDelete; 1700 action.dt_inner_prio = bcmVlanActionDelete; 1701 break; 1702 case BCM_SUBPORT_MATCH_PKT_VID_OUTER_VLAN: 1703 action.ot_outer = bcmVlanActionReplace; 1704 action.ot_outer_prio = bcmVlanActionAdd; 1705 action.ot_outer_pkt_prio = bcmVlanActionReplace; 1706 action.dt_outer = bcmVlanActionReplace; 1707 action.dt_outer_prio = bcmVlanActionAdd; 1708 action.dt_outer_pkt_prio = bcmVlanActionReplace; 1709 break; 1710 default: 1711 action.ot_outer = bcmVlanActionReplace; 1712 action.ot_outer_prio = bcmVlanActionReplace; 1713 action.dt_outer = bcmVlanActionReplace; 1714 action.dt_outer_prio = bcmVlanActionReplace; 1715 break; 1716 } 1717 1718 rv = _bcm_trx_vlan_action_profile_entry_add(unit, &action, &ing_profile_idx); 1719 if (rv < 0) { 1720 goto cleanup; 1721 } 1722 rv = _bcm_esw_vlan_xlate_key_type_value_get(unit, 1723 VLXLT_HASH_KEY_TYPE_OVID, &key_type_value); 1724 if (rv < 0) { 1725 goto cleanup; 1726 } 1727 #ifdef BCM_TRIDENT3_SUPPORT 1728 if (SOC_MEM_IS_VALID(unit, VLAN_XLATE_1_DOUBLEm)) { 1729 ing_mem = VLAN_XLATE_1_DOUBLEm; 1730 } else 1731 #endif 1732 { 1733 ing_mem = VLAN_XLATEm; 1734 } 1735 #ifdef BCM_TRIDENT3_SUPPORT 1736 if (soc_feature(unit, soc_feature_base_valid)) { 1737 soc_mem_field32_set(unit, ing_mem, ing_vent, BASE_VALID_0f, 3); 1738 soc_mem_field32_set(unit, ing_mem, ing_vent, BASE_VALID_1f, 7); 1739 } else 1740 #endif 1741 { 1742 soc_mem_field32_set(unit, ing_mem, ing_vent, VALIDf, 1); 1743 } 1744 1745 if (SOC_MEM_FIELD_VALID(unit, ing_mem, VLAN_ACTION_VALIDf)) { 1746 soc_mem_field32_set(unit, ing_mem, ing_vent, VLAN_ACTION_VALIDf, 1); 1747 } 1748 1749 if ((soc_feature(unit, soc_feature_lltag)) && 1750 ((BCM_SUBPORT_MATCH_PKT_VID == config->criteria) || 1751 (BCM_SUBPORT_MATCH_PKT_VID_INNER_VLAN == config->criteria) || 1752 (BCM_SUBPORT_MATCH_PKT_VID_OUTER_VLAN == config->criteria))) { 1753 if (BCM_SUBPORT_MATCH_PKT_VID == config->criteria) { 1754 soc_mem_field32_set(unit, ing_mem, ing_vent, KEY_TYPEf, 1755 KT2_PT_XLT_KEY_TYPE_LLVID); 1756 } else if (BCM_SUBPORT_MATCH_PKT_VID_INNER_VLAN == config->criteria) { 1757 soc_mem_field32_set(unit, ing_mem, ing_vent, KEY_TYPEf, 1758 KT2_PT_XLT_KEY_TYPE_LLVID_IVID); 1759 soc_mem_field32_set(unit, ing_mem, ing_vent, LLTAG__IVIDf, 1760 config->inner_vlan); 1761 } else if (BCM_SUBPORT_MATCH_PKT_VID_OUTER_VLAN == config->criteria) { 1762 soc_mem_field32_set(unit, ing_mem, ing_vent, KEY_TYPEf, 1763 KT2_PT_XLT_KEY_TYPE_LLVID_OVID); 1764 soc_mem_field32_set(unit, ing_mem, ing_vent, LLTAG__OVIDf, 1765 config->outer_vlan); 1766 } 1767 1768 soc_mem_field32_set(unit, ing_mem, ing_vent, LLTAG__LLVIDf, config->pkt_vlan); 1769 soc_mem_field32_set(unit, ing_mem, ing_vent, LLTAG__MODULE_IDf, modid); 1770 soc_mem_field32_set(unit, ing_mem, ing_vent, LLTAG__PORT_NUMf, local_port); 1771 soc_mem_field32_set(unit, ing_mem, ing_vent, LLTAG__TAG_ACTION_PROFILE_PTRf, 1772 ing_profile_idx); 1773 soc_mem_field32_set(unit, ing_mem, ing_vent, LLTAG__NEW_OVIDf, ovid); 1774 soc_mem_field32_set(unit, ing_mem, ing_vent, LLTAG__NEW_OPRIf, config->int_pri); 1775 /* Group VP */ 1776 soc_mem_field32_set(unit, ing_mem, ing_vent, LLTAG__SOURCE_VPf, vp_base); 1777 } else { 1778 soc_mem_field32_set(unit, ing_mem, ing_vent, KEY_TYPEf, key_type_value); 1779 soc_mem_field32_set(unit, ing_mem, ing_vent, OVIDf, config->pkt_vlan); 1780 soc_mem_field32_set(unit, ing_mem, ing_vent, MODULE_IDf, modid); 1781 soc_mem_field32_set(unit, ing_mem, ing_vent, PORT_NUMf, local_port); 1782 if (SOC_MEM_FIELD_VALID(unit, ing_mem, RPEf)) { 1783 soc_mem_field32_set(unit, ing_mem, ing_vent, RPEf, 1); 1784 soc_mem_field32_set(unit, ing_mem, ing_vent, PRIf, config->int_pri); 1785 } 1786 soc_mem_field32_set(unit, ing_mem, ing_vent, TAG_ACTION_PROFILE_PTRf, ing_profile_idx); 1787 soc_mem_field32_set(unit, ing_mem, ing_vent, NEW_OVIDf, ovid); 1788 soc_mem_field32_set(unit, ing_mem, ing_vent, SOURCE_VPf, vp_base); /* Group VP */ 1789 } 1790 /* TD2 type of device indicating Source Field as SGLP */ 1791 if (SOC_MEM_FIELD_VALID(unit, ing_mem, SOURCE_TYPEf)) { 1792 soc_mem_field32_set(unit, ing_mem, ing_vent, SOURCE_TYPEf, 1); 1793 } 1794 1795 #ifdef BCM_TRIUMPH3_SUPPORT 1796 if (SOC_IS_TRIUMPH3(unit)) { 1797 soc_mem_field32_set(unit, ing_mem, ing_vent, SVP_VALIDf, 1); /* L2 SVP */ 1798 } else 1799 #endif 1800 { 1801 soc_mem_field32_set(unit, ing_mem, ing_vent, MPLS_ACTIONf, 1); /* L2 SVP */ 1802 } 1803 1804 rv = soc_mem_insert_return_old(unit, ing_mem, MEM_BLOCK_ALL, 1805 ing_vent, ing_vent); 1806 if (rv == SOC_E_EXISTS) { 1807 /* Delete the old vlan translate profile entry */ 1808 ing_profile_idx = soc_mem_field32_get(unit, ing_mem, ing_vent, 1809 TAG_ACTION_PROFILE_PTRf); 1810 rv = _bcm_trx_vlan_action_profile_entry_delete(unit, ing_profile_idx); 1811 } 1812 1813 if (rv < 0) { 1814 goto cleanup; 1815 } 1816 1817 _BCM_TR2_SUBPORT_ID_SET(unit, vp, l3_idx); 1818 BCM_GPORT_SUBPORT_PORT_SET(*port, ((my_modid << 12) | l3_idx)); 1819 1820 /* we must set the VT_KEY the same as this subport's property, since the not API avaiable to change the VT_KEY 1821 * wheh it involves LLTAG 1822 */ 1823 if (soc_feature(unit, soc_feature_lltag)) { 1824 rv = soc_mem_read(unit, PORT_TABm, MEM_BLOCK_ALL, local_port, &port_tab); 1825 if (rv < 0) { 1826 goto cleanup; 1827 } 1828 1829 if (BCM_SUBPORT_MATCH_PKT_VID == config->criteria) { 1830 soc_mem_field32_set(unit, PORT_TABm, &port_tab, VT_KEY_TYPEf, 1831 KT2_PT_XLT_KEY_TYPE_LLVID); 1832 } else if(BCM_SUBPORT_MATCH_PKT_VID_INNER_VLAN == config->criteria){ 1833 soc_mem_field32_set(unit, PORT_TABm, &port_tab, VT_KEY_TYPEf, 1834 KT2_PT_XLT_KEY_TYPE_LLVID_IVID); 1835 } else if(BCM_SUBPORT_MATCH_PKT_VID_OUTER_VLAN == config->criteria){ 1836 soc_mem_field32_set(unit, PORT_TABm, &port_tab, VT_KEY_TYPEf, 1837 KT2_PT_XLT_KEY_TYPE_LLVID_OVID); 1838 } 1839 1840 rv = soc_mem_write(unit, PORT_TABm, 1841 MEM_BLOCK_ALL, local_port, &port_tab); 1842 if (rv < 0) { 1843 goto cleanup; 1844 } 1845 } 1846 return BCM_E_NONE; 1847 cleanup: 1848 if (l3_idx != -1) { 1849 BCM_L3_INTF_USED_CLR(unit, l3_idx); 1850 } 1851 1852 #ifdef BCM_WARM_BOOT_SUPPORT 1853 SOC_CONTROL_LOCK(unit); 1854 SOC_CONTROL(unit)->scache_dirty = 1; 1855 SOC_CONTROL_UNLOCK(unit); 1856 #endif 1857 1858 return rv; 1859 } 1860 1861 STATIC int 1862 _bcm_tr2_subport_port_get(int unit, int l3_idx, 1863 bcm_subport_config_t *config); 1864 1865 STATIC int 1866 _bcm_tr2_subport_port_delete(int unit, int l3_idx, int vp) 1867 { 1868 int rv, vp_base, vt_index, nh_index=-1,nhi_group_en=0; 1869 int nh_group=-1, nh_profile_idx=0; 1870 egr_l3_intf_entry_t l3_intf; 1871 ing_l3_next_hop_entry_t ing_nh; 1872 egr_l3_next_hop_entry_t egr_nh; 1873 ing_dvp_table_entry_t dvp; 1874 nhi_group_tc_profile_entry_t nhi_entry; 1875 bcm_port_t port = 0; 1876 bcm_module_t modid = 0; 1877 bcm_vlan_t pkt_vlan = 0, ovid = 0; 1878 uint32 egr_profile_idx, ing_profile_idx, port_class = 0; 1879 bcm_subport_config_t config; 1880 int key_type_value; 1881 uint32 egr_vent[SOC_MAX_MEM_FIELD_WORDS]; /* HW entry buffer. */ 1882 uint32 ing_vent[SOC_MAX_MEM_FIELD_WORDS]; /* HW entry buffer. */ 1883 soc_mem_t egr_mem = EGR_VLAN_XLATEm, ing_mem = VLAN_XLATEm; 1884 1885 sal_memset(egr_vent, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32)); 1886 sal_memset(ing_vent, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32)); 1887 1888 1889 _TR2_SUBPORT_CHECK_INIT(unit); 1890 1891 sal_memset(&config, 0x0, sizeof(bcm_subport_config_t)); 1892 rv = soc_mem_read(unit, EGR_L3_INTFm, MEM_BLOCK_ALL, l3_idx, &l3_intf); 1893 BCM_IF_ERROR_RETURN(rv); 1894 1895 /* Get the base group VP */ 1896 vp_base = vp & ~(0x7); 1897 1898 if (soc_feature(unit, soc_feature_subport_enhanced)) { 1899 #if defined(BCM_KATANA2_SUPPORT) 1900 if (SOC_IS_KATANA2(unit)) { 1901 vp_base = vp; 1902 } 1903 #endif /* defined(BCM_KATANA2_SUPPORT) */ 1904 /* Get the group's next-hop index */ 1905 rv = READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ALL, vp_base, &dvp); 1906 BCM_IF_ERROR_RETURN(rv); 1907 if (soc_feature(unit, soc_feature_lltag)) { 1908 if (soc_ING_DVP_TABLEm_field32_get(unit, &dvp, NHI_GROUP_ENf)) { 1909 1910 nhi_group_en = 1; 1911 nh_group = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, NHI_GROUPf); 1912 nh_profile_idx = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, 1913 TC_PROFILE_INDEXf); 1914 rv = READ_NHI_GROUP_TC_PROFILEm(unit, MEM_BLOCK_ALL, 1915 nh_profile_idx*16 + vp - vp_base, &nhi_entry); 1916 BCM_IF_ERROR_RETURN(rv); 1917 rv = _bcm_tr2_subport_port_get(unit, l3_idx, &config); 1918 BCM_IF_ERROR_RETURN(rv); 1919 nh_index = nh_group + soc_NHI_GROUP_TC_PROFILEm_field32_get(unit, 1920 &nhi_entry, NHI_OFFSETf); 1921 } else { 1922 nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, NEXT_HOP_INDEXf); 1923 } 1924 } else { 1925 nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, NEXT_HOP_INDEXf); 1926 } 1927 /* Get the group's OVID from the group's egress next-hop entry */ 1928 rv = soc_mem_read(unit, EGR_L3_NEXT_HOPm, 1929 MEM_BLOCK_ALL, nh_index, &egr_nh); 1930 BCM_IF_ERROR_RETURN(rv); 1931 if (soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, L3__OVIDf)) { 1932 ovid = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, L3__OVIDf); 1933 } else { 1934 ovid = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, OVIDf); 1935 } 1936 } 1937 1938 if (nh_index == -1) { 1939 return BCM_E_INTERNAL; 1940 } 1941 1942 /* Get the egress port class */ 1943 BCM_IF_ERROR_RETURN (soc_mem_read(unit, ING_L3_NEXT_HOPm, MEM_BLOCK_ANY, 1944 nh_index, &ing_nh)); 1945 1946 if (soc_feature(unit, soc_feature_generic_dest)) { 1947 uint32 dt, dv; 1948 dv = soc_mem_field32_dest_get(unit, ING_L3_NEXT_HOPm, 1949 &ing_nh, DESTINATIONf, &dt); 1950 if (dt != SOC_MEM_FIF_DEST_LAG) { 1951 modid = (dv & SOC_MEM_FIF_DGPP_MOD_ID_MASK) >> 1952 SOC_MEM_FIF_DGPP_MOD_ID_SHIFT_BITS; 1953 port = dv & SOC_MEM_FIF_DGPP_PORT_MASK; 1954 rv = bcm_esw_port_class_get(unit, port, bcmPortClassVlanTranslateEgress, 1955 &port_class); 1956 BCM_IF_ERROR_RETURN(rv); 1957 } 1958 } else { 1959 1960 if (!soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, Tf)) { 1961 modid = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, MODULE_IDf); 1962 port = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, PORT_NUMf); 1963 rv = bcm_esw_port_class_get(unit, port, bcmPortClassVlanTranslateEgress, 1964 &port_class); 1965 BCM_IF_ERROR_RETURN(rv); 1966 } 1967 } 1968 1969 #ifdef BCM_TRIDENT3_SUPPORT 1970 if (SOC_MEM_IS_VALID(unit, EGR_VLAN_XLATE_1_DOUBLEm)) { 1971 egr_mem = EGR_VLAN_XLATE_1_DOUBLEm; 1972 } else 1973 #endif 1974 { 1975 egr_mem = EGR_VLAN_XLATEm; 1976 } 1977 1978 /*We think only LLTAG subport uses NHI_GROUP_TC_PROFILE table*/ 1979 if (!(soc_feature(unit, soc_feature_lltag) && (nhi_group_en == 1))) { 1980 /* Find the egress vlan translate entry */ 1981 soc_mem_field32_set(unit, egr_mem, egr_vent, OVIDf, ovid); 1982 soc_mem_field32_set(unit, egr_mem, egr_vent, DVPf, vp); 1983 #ifdef BCM_TRIDENT3_SUPPORT 1984 if (soc_feature(unit, soc_feature_base_valid)) { 1985 soc_mem_field32_set(unit, egr_mem, egr_vent, BASE_VALID_0f, 3); 1986 soc_mem_field32_set(unit, egr_mem, egr_vent, BASE_VALID_1f, 7); 1987 soc_mem_field32_set(unit, egr_mem, egr_vent, KEY_TYPEf, 0x01); 1988 soc_mem_field32_set(unit, egr_mem, egr_vent, DATA_TYPEf, 1); 1989 } else 1990 #endif 1991 { 1992 soc_mem_field32_set(unit, egr_mem, egr_vent, VALIDf, 1); 1993 #ifdef BCM_TRIUMPH3_SUPPORT 1994 if (SOC_IS_TRIUMPH3(unit)) { 1995 soc_mem_field32_set(unit, egr_mem, egr_vent, KEY_TYPEf, 0x01); 1996 } else 1997 #endif 1998 { 1999 soc_mem_field32_set(unit, egr_mem, egr_vent, ENTRY_TYPEf, 0x01); 2000 } 2001 } 2002 2003 MEM_LOCK(unit, egr_mem); 2004 rv = soc_mem_search(unit, egr_mem, MEM_BLOCK_ALL, &vt_index, 2005 egr_vent, egr_vent, 0); 2006 if (rv < 0) { 2007 MEM_UNLOCK(unit, egr_mem); 2008 return rv; 2009 } 2010 2011 /* Get the old vlan translate profile entry */ 2012 egr_profile_idx = soc_mem_field32_get(unit, egr_mem, egr_vent, 2013 TAG_ACTION_PROFILE_PTRf); 2014 2015 /* Delete the egress vlan translate entry */ 2016 rv = soc_mem_delete(unit, egr_mem, MEM_BLOCK_ALL, &egr_vent); 2017 MEM_UNLOCK(unit, egr_mem); 2018 BCM_IF_ERROR_RETURN(rv); 2019 2020 /* Delete the old vlan translate profile entry */ 2021 rv = _bcm_trx_egr_vlan_action_profile_entry_delete(unit, egr_profile_idx); 2022 BCM_IF_ERROR_RETURN(rv); 2023 2024 /* Find vlan translate entry */ 2025 pkt_vlan = soc_mem_field32_get(unit, egr_mem, egr_vent, NEW_OTAG_VPTAGf); 2026 rv = _bcm_esw_vlan_xlate_key_type_value_get(unit, 2027 VLXLT_HASH_KEY_TYPE_OVID, &key_type_value); 2028 BCM_IF_ERROR_RETURN(rv); 2029 } 2030 2031 sal_memset(ing_vent, 0, sizeof(ing_vent)); 2032 #ifdef BCM_TRIDENT3_SUPPORT 2033 if (SOC_MEM_IS_VALID(unit, VLAN_XLATE_1_DOUBLEm)) { 2034 ing_mem = VLAN_XLATE_1_DOUBLEm; 2035 } else 2036 #endif 2037 { 2038 ing_mem = VLAN_XLATEm; 2039 } 2040 #ifdef BCM_TRIDENT3_SUPPORT 2041 if (soc_feature(unit, soc_feature_base_valid)) { 2042 soc_mem_field32_set(unit, ing_mem, ing_vent, BASE_VALID_0f, 3); 2043 soc_mem_field32_set(unit, ing_mem, ing_vent, BASE_VALID_1f, 7); 2044 } else 2045 #endif 2046 { 2047 soc_mem_field32_set(unit, ing_mem, ing_vent, VALIDf, 1); 2048 } 2049 2050 if ((soc_feature(unit, soc_feature_lltag)) && 2051 (config.criteria > BCM_SUBPORT_MATCH_INVALID) && 2052 (config.criteria < BCM_SUBPORT_MATCH_COUNT)) { 2053 if (config.criteria == BCM_SUBPORT_MATCH_PKT_VID) { 2054 soc_mem_field32_set(unit, ing_mem, ing_vent, KEY_TYPEf, 2055 KT2_PT_XLT_KEY_TYPE_LLVID); 2056 soc_mem_field32_set(unit, ing_mem, ing_vent, LLTAG__LLVIDf, 2057 config.pkt_vlan); 2058 } else if (config.criteria == BCM_SUBPORT_MATCH_PKT_VID_INNER_VLAN) { 2059 soc_mem_field32_set(unit, ing_mem, ing_vent, KEY_TYPEf, 2060 KT2_PT_XLT_KEY_TYPE_LLVID_IVID); 2061 soc_mem_field32_set(unit, ing_mem, ing_vent, LLTAG__LLVIDf, 2062 config.pkt_vlan); 2063 soc_mem_field32_set(unit, ing_mem, ing_vent, LLTAG__IVIDf, 2064 config.inner_vlan); 2065 } else { 2066 soc_mem_field32_set(unit, ing_mem, ing_vent, KEY_TYPEf, 2067 KT2_PT_XLT_KEY_TYPE_LLVID_OVID); 2068 soc_mem_field32_set(unit, ing_mem, ing_vent, LLTAG__LLVIDf, 2069 config.pkt_vlan); 2070 soc_mem_field32_set(unit, ing_mem, ing_vent, LLTAG__OVIDf, 2071 config.outer_vlan); 2072 } 2073 } else { 2074 soc_mem_field32_set(unit, ing_mem, ing_vent, KEY_TYPEf, 2075 key_type_value); 2076 soc_mem_field32_set(unit, ing_mem, ing_vent, OVIDf, pkt_vlan); 2077 } 2078 2079 soc_mem_field32_set(unit, ing_mem, ing_vent, MODULE_IDf, modid); 2080 soc_mem_field32_set(unit, ing_mem, ing_vent, PORT_NUMf, port); 2081 2082 /* TD2 type of device indicating Source Field as SGLP */ 2083 if (SOC_MEM_FIELD_VALID(unit, ing_mem, SOURCE_TYPEf)) { 2084 soc_mem_field32_set(unit, ing_mem, ing_vent, SOURCE_TYPEf, 1); 2085 } 2086 2087 MEM_LOCK(unit, ing_mem); 2088 2089 rv = soc_mem_search(unit, ing_mem, MEM_BLOCK_ALL, &vt_index, 2090 ing_vent, ing_vent, 0); 2091 if (rv < 0) { 2092 MEM_UNLOCK(unit, ing_mem); 2093 return rv; 2094 } 2095 2096 /* Get the old vlan translate profile entry */ 2097 ing_profile_idx = soc_mem_field32_get(unit, ing_mem, ing_vent, 2098 TAG_ACTION_PROFILE_PTRf); 2099 2100 /* Delete the ingress vlan translate entry */ 2101 rv = soc_mem_delete(unit, ing_mem, MEM_BLOCK_ALL, ing_vent); 2102 MEM_UNLOCK(unit, ing_mem); 2103 BCM_IF_ERROR_RETURN(rv); 2104 2105 /* Delete the old vlan translate profile entry */ 2106 rv = _bcm_trx_vlan_action_profile_entry_delete(unit, ing_profile_idx); 2107 BCM_IF_ERROR_RETURN(rv); 2108 2109 /* Clear the EGR_L3_INTF entry */ 2110 sal_memset(&l3_intf, 0, sizeof(egr_l3_intf_entry_t)); 2111 rv = soc_mem_write(unit, EGR_L3_INTFm, MEM_BLOCK_ALL, l3_idx, &l3_intf); 2112 2113 /* Free the L3_INTF index */ 2114 BCM_L3_INTF_USED_CLR(unit, l3_idx); 2115 2116 if (soc_feature(unit, soc_feature_gport_service_counters)) { 2117 bcm_gport_t gport; 2118 2119 /* Release Service counter, if any */ 2120 BCM_GPORT_SUBPORT_PORT_SET(gport, vp); 2121 _bcm_esw_flex_stat_handle_free(unit, _bcmFlexStatTypeGport, gport); 2122 } 2123 2124 /* Clear the subport usage SW state */ 2125 _BCM_TR2_SUBPORT_ID_CLR(unit, vp); 2126 2127 #ifdef BCM_WARM_BOOT_SUPPORT 2128 SOC_CONTROL_LOCK(unit); 2129 SOC_CONTROL(unit)->scache_dirty = 1; 2130 SOC_CONTROL_UNLOCK(unit); 2131 #endif 2132 2133 return BCM_E_NONE; 2134 } 2135 2136 /* 2137 * Function: 2138 * bcm_subport_port_delete 2139 * Purpose: 2140 * Delete a subport 2141 * Parameters: 2142 * unit - (IN) Device Number 2143 * port - (IN) GPORT (generic port) identifier 2144 * Returns: 2145 * BCM_E_XXX 2146 */ 2147 int 2148 bcm_tr2_subport_port_delete(int unit, bcm_gport_t port) 2149 { 2150 egr_l3_intf_entry_t l3_intf; 2151 int l3_idx, vp=-1, rv; 2152 bcm_module_t modid, my_modid; 2153 2154 _TR2_SUBPORT_CHECK_INIT(unit); 2155 2156 BCM_IF_ERROR_RETURN (bcm_esw_stk_my_modid_get(unit, &my_modid)); 2157 modid = (BCM_GPORT_SUBPORT_PORT_GET(port) >> 12) & SOC_MODID_MAX(unit); 2158 if (modid != my_modid) { 2159 return BCM_E_PORT; 2160 } 2161 2162 l3_idx = BCM_GPORT_SUBPORT_PORT_GET(port) & 0xfff; 2163 if (l3_idx >= BCM_XGS3_L3_IF_TBL_SIZE(unit)) { 2164 return (BCM_E_PARAM); 2165 } 2166 2167 rv = soc_mem_read(unit, EGR_L3_INTFm, MEM_BLOCK_ALL, l3_idx, &l3_intf); 2168 BCM_IF_ERROR_RETURN(rv); 2169 2170 2171 vp = soc_mem_field32_get(unit, EGR_L3_INTFm, &l3_intf, IVIDf); 2172 if (_BCM_TR2_SUBPORT_ID_GET(unit, vp) != l3_idx) { 2173 return BCM_E_NOT_FOUND; 2174 } 2175 2176 2177 if (vp == -1) { 2178 return BCM_E_INTERNAL; 2179 } 2180 2181 return _bcm_tr2_subport_port_delete(unit, l3_idx, vp); 2182 } 2183 2184 STATIC int 2185 _bcm_tr2_subport_port_get(int unit, int l3_idx, 2186 bcm_subport_config_t *config) 2187 { 2188 int vp=-1, rv, vp_base = 0, vt_index, nh_index=-1, nh_group=-1, group_en = 0, nh_profile_idx=0; 2189 egr_l3_intf_entry_t l3_intf; 2190 egr_l3_next_hop_entry_t egr_nh; 2191 nhi_group_tc_profile_entry_t nhi_entry; 2192 ing_dvp_table_entry_t dvp; 2193 source_vp_entry_t svp; 2194 bcm_vlan_t ovid = 0; 2195 port_tab_entry_t port_tab; 2196 ing_l3_next_hop_entry_t ing_nh; 2197 bcm_port_t local_port = 0; 2198 uint32 egr_vent[SOC_MAX_MEM_FIELD_WORDS]; /* HW entry buffer. */ 2199 soc_mem_t egr_mem = EGR_VLAN_XLATEm; 2200 uint32 dest_type, dest_val; 2201 2202 rv = soc_mem_read(unit, EGR_L3_INTFm, MEM_BLOCK_ALL, l3_idx, &l3_intf); 2203 BCM_IF_ERROR_RETURN(rv); 2204 2205 if (soc_feature(unit, soc_feature_subport_enhanced)) { 2206 vp = soc_mem_field32_get(unit, EGR_L3_INTFm, &l3_intf, IVIDf); 2207 if (_BCM_TR2_SUBPORT_ID_GET(unit, vp) != l3_idx) { 2208 return BCM_E_NOT_FOUND; 2209 } 2210 } 2211 2212 if (vp == -1) { 2213 return BCM_E_INTERNAL; 2214 } 2215 2216 /* Get the base group VP */ 2217 rv = READ_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp); 2218 BCM_IF_ERROR_RETURN(rv); 2219 if (soc_feature(unit, soc_feature_lltag)) { 2220 rv = READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ALL, vp, &dvp); 2221 BCM_IF_ERROR_RETURN(rv); 2222 if (soc_ING_DVP_TABLEm_field32_get(unit, &dvp, NHI_GROUP_ENf)) { 2223 vp_base = vp - (vp%8); 2224 } else { 2225 vp_base = soc_SOURCE_VPm_field32_get(unit, &svp, DVPf); 2226 } 2227 } else { 2228 if (soc_feature(unit, soc_feature_generic_dest)) { 2229 dest_val = soc_mem_field32_dest_get(unit, SOURCE_VPm, 2230 &svp, DESTINATIONf, &dest_type); 2231 if (dest_type == SOC_MEM_FIF_DEST_DVP) { 2232 vp_base = dest_val; 2233 } 2234 } else { 2235 vp_base = soc_SOURCE_VPm_field32_get(unit, &svp, DVPf); 2236 } 2237 } 2238 /* Set the config data to be returned */ 2239 config->int_pri = vp - vp_base; 2240 2241 /* Get the group's next-hop index */ 2242 if (soc_feature(unit, soc_feature_subport_enhanced)) { 2243 rv = READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ALL, vp_base, &dvp); 2244 BCM_IF_ERROR_RETURN(rv); 2245 if (soc_feature(unit, soc_feature_lltag)) { 2246 if (soc_ING_DVP_TABLEm_field32_get(unit, &dvp, NHI_GROUP_ENf)) { 2247 group_en = 1; 2248 nh_group = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, NHI_GROUPf); 2249 nh_profile_idx = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, 2250 TC_PROFILE_INDEXf); 2251 rv = READ_NHI_GROUP_TC_PROFILEm(unit, MEM_BLOCK_ALL, 2252 nh_profile_idx*16 + config->int_pri, &nhi_entry); 2253 BCM_IF_ERROR_RETURN(rv); 2254 nh_index = nh_group + soc_NHI_GROUP_TC_PROFILEm_field32_get(unit, 2255 &nhi_entry, NHI_OFFSETf); 2256 } else { 2257 nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, NEXT_HOP_INDEXf); 2258 } 2259 } else { 2260 nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, NEXT_HOP_INDEXf); 2261 } 2262 2263 /* Get the group's OVID from the group's egress next-hop entry */ 2264 rv = soc_mem_read(unit, EGR_L3_NEXT_HOPm, 2265 MEM_BLOCK_ALL, nh_index, &egr_nh); 2266 BCM_IF_ERROR_RETURN(rv); 2267 2268 if (soc_feature(unit, soc_feature_lltag) && (group_en == 1)) { 2269 /* Get the modid and port_class for the destination port */ 2270 rv = soc_mem_read(unit, ING_L3_NEXT_HOPm, 2271 MEM_BLOCK_ALL, nh_index, &ing_nh); 2272 BCM_IF_ERROR_RETURN(rv); 2273 if (!soc_mem_field32_get(unit, ING_L3_NEXT_HOPm, &ing_nh, Tf)) { 2274 local_port = soc_mem_field32_get(unit, ING_L3_NEXT_HOPm, 2275 &ing_nh, PORT_NUMf); 2276 } 2277 2278 rv = soc_mem_read(unit, PORT_TABm, MEM_BLOCK_ALL, local_port, &port_tab); 2279 BCM_IF_ERROR_RETURN(rv); 2280 switch (soc_PORT_TABm_field32_get(unit, &port_tab, VT_KEY_TYPEf)) { 2281 case KT2_PT_XLT_KEY_TYPE_LLVID: 2282 config->criteria = BCM_SUBPORT_MATCH_PKT_VID; 2283 config->pkt_vlan = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, 2284 &egr_nh, SD_TAG__LLTAG_VIDf); 2285 break; 2286 case KT2_PT_XLT_KEY_TYPE_LLVID_IVID: 2287 config->criteria = BCM_SUBPORT_MATCH_PKT_VID_INNER_VLAN; 2288 config->pkt_vlan = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, 2289 &egr_nh, SD_TAG__LLTAG_VIDf); 2290 config->inner_vlan= soc_SOURCE_VPm_field32_get(unit, &svp, DVPf); 2291 break; 2292 case KT2_PT_XLT_KEY_TYPE_LLVID_OVID: 2293 config->criteria = BCM_SUBPORT_MATCH_PKT_VID_OUTER_VLAN; 2294 config->pkt_vlan = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, 2295 &egr_nh, SD_TAG__LLTAG_VIDf); 2296 config->outer_vlan = soc_SOURCE_VPm_field32_get(unit, &svp, DVPf); 2297 break; 2298 default: 2299 break; 2300 } 2301 } else { 2302 if (soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, L3__OVIDf)) { 2303 ovid = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, L3__OVIDf); 2304 } else { 2305 ovid = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, OVIDf); 2306 } 2307 /* Find the egress vlan translate entry */ 2308 #ifdef BCM_TRIDENT3_SUPPORT 2309 if (SOC_MEM_IS_VALID(unit, EGR_VLAN_XLATE_1_DOUBLEm)) { 2310 egr_mem = EGR_VLAN_XLATE_1_DOUBLEm; 2311 } else 2312 #endif 2313 { 2314 egr_mem = EGR_VLAN_XLATEm; 2315 } 2316 sal_memset(egr_vent, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32)); 2317 #ifdef BCM_TRIDENT3_SUPPORT 2318 if (soc_feature(unit, soc_feature_base_valid)) { 2319 soc_mem_field32_set(unit, egr_mem, egr_vent, BASE_VALID_0f, 3); 2320 soc_mem_field32_set(unit, egr_mem, egr_vent, BASE_VALID_1f, 7); 2321 soc_mem_field32_set(unit, egr_mem, egr_vent, KEY_TYPEf, 1); 2322 soc_mem_field32_set(unit, egr_mem, egr_vent, DATA_TYPEf, 1); 2323 } else 2324 #endif 2325 { 2326 soc_mem_field32_set(unit, egr_mem, egr_vent, VALIDf, 1); 2327 #ifdef BCM_TRIUMPH3_SUPPORT 2328 if (SOC_IS_TRIUMPH3(unit)) { 2329 soc_mem_field32_set(unit, egr_mem, egr_vent, KEY_TYPEf, 0x01); 2330 } else 2331 #endif 2332 { 2333 soc_mem_field32_set(unit, egr_mem, egr_vent, ENTRY_TYPEf, 0x01); 2334 } 2335 } 2336 soc_mem_field32_set(unit, egr_mem, egr_vent, OVIDf, ovid); 2337 soc_mem_field32_set(unit, egr_mem, egr_vent, DVPf, vp); 2338 2339 rv = soc_mem_search(unit, egr_mem, MEM_BLOCK_ALL, &vt_index, 2340 egr_vent, egr_vent, 0); 2341 if (rv < 0) { 2342 return rv; 2343 } 2344 2345 /* Find pkt_vlan from egress vlan translate entry */ 2346 2347 config->pkt_vlan = soc_mem_field32_get(unit, egr_mem, egr_vent, 2348 NEW_OTAG_VPTAGf); 2349 } 2350 } 2351 /* Get the subport group ID */ 2352 BCM_GPORT_SUBPORT_GROUP_SET(config->group, vp_base); 2353 2354 return BCM_E_NONE; 2355 } 2356 2357 /* 2358 * Function: 2359 * bcm_subport_port_get 2360 * Purpose: 2361 * Get a subport 2362 * Parameters: 2363 * unit - (IN) Device Number 2364 * port - (IN) GPORT (generic port) identifier 2365 * config - (OUT) Subport config information 2366 * Returns: 2367 * BCM_E_XXX 2368 */ 2369 int 2370 bcm_tr2_subport_port_get(int unit, bcm_gport_t port, 2371 bcm_subport_config_t *config) 2372 { 2373 int l3_idx; 2374 bcm_module_t modid, my_modid; 2375 2376 _TR2_SUBPORT_CHECK_INIT(unit); 2377 2378 if (config == NULL) { 2379 return BCM_E_PARAM; 2380 } 2381 2382 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_modid)); 2383 modid = (BCM_GPORT_SUBPORT_PORT_GET(port) >> 12) & SOC_MODID_MAX(unit); 2384 if (modid != my_modid) { 2385 return BCM_E_PORT; 2386 } 2387 2388 l3_idx = BCM_GPORT_SUBPORT_PORT_GET(port) & 0xfff; 2389 if (l3_idx >= BCM_XGS3_L3_IF_TBL_SIZE(unit)) { 2390 return (BCM_E_PARAM); 2391 } 2392 2393 return _bcm_tr2_subport_port_get(unit, l3_idx, config); 2394 } 2395 2396 /* 2397 * Function: 2398 * bcm_subport_port_traverse 2399 * Purpose: 2400 * Traverse all valid subports and call the 2401 * supplied callback routine. 2402 * Parameters: 2403 * unit - Device Number 2404 * cb - User callback function, called once per subport. 2405 * user_data - cookie 2406 * Returns: 2407 * BCM_E_XXX 2408 */ 2409 int 2410 bcm_tr2_subport_port_traverse(int unit, 2411 bcm_subport_port_traverse_cb cb, 2412 void *user_data) 2413 { 2414 int rv, vp, l3_idx; 2415 bcm_subport_config_t config; 2416 bcm_gport_t gport; 2417 bcm_module_t my_modid; 2418 2419 _TR2_SUBPORT_CHECK_INIT(unit); 2420 2421 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_modid)); 2422 2423 for (vp = 0; vp < _TR2_SUBPORT_NUM_VP; vp++) { 2424 l3_idx = _BCM_TR2_SUBPORT_ID_GET(unit, vp); 2425 if (l3_idx != 0xffff) { 2426 rv = _bcm_tr2_subport_port_get(unit, l3_idx, &config); 2427 BCM_IF_ERROR_RETURN(rv); 2428 2429 BCM_GPORT_SUBPORT_PORT_SET(gport, ((my_modid << 12) | l3_idx)); 2430 /* coverity[dead_error_begin] */ 2431 rv = cb(unit, gport, &config, user_data); 2432 /* coverity[dead_error_begin] */ 2433 #ifdef BCM_CB_ABORT_ON_ERR 2434 if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) { 2435 return rv; 2436 } 2437 #endif 2438 } 2439 } 2440 return BCM_E_NONE; 2441 } 2442 2443 /* 2444 * Function: 2445 * _bcm_tr_subport_group_resolve 2446 * Purpose: 2447 * Get the modid, port, trunk values for a subport group GPORT 2448 * Returns: 2449 * BCM_E_XXX 2450 */ 2451 int 2452 _bcm_tr2_subport_group_resolve(int unit, bcm_gport_t gport, 2453 bcm_module_t *modid, bcm_port_t *port, 2454 bcm_trunk_t *trunk_id, int *id) 2455 { 2456 int rv = BCM_E_NONE; 2457 ing_l3_next_hop_entry_t ing_nh; 2458 ing_dvp_table_entry_t dvp; 2459 int nh_index, vp_base; 2460 2461 _TR2_SUBPORT_CHECK_INIT(unit); 2462 2463 vp_base = BCM_GPORT_SUBPORT_GROUP_GET(gport); 2464 if (vp_base == -1) { 2465 return BCM_E_PARAM; 2466 } 2467 2468 if (soc_feature(unit, soc_feature_subport_enhanced)) { 2469 rv = READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ALL, vp_base, &dvp); 2470 BCM_IF_ERROR_RETURN(rv); 2471 nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, NEXT_HOP_INDEXf); 2472 BCM_IF_ERROR_RETURN (soc_mem_read(unit, ING_L3_NEXT_HOPm, MEM_BLOCK_ANY, 2473 nh_index, &ing_nh)); 2474 if (soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, ENTRY_TYPEf) != 0x3) { 2475 /* Entry type is not GPON DVP */ 2476 return BCM_E_NOT_FOUND; 2477 } 2478 } 2479 2480 if (soc_feature(unit, soc_feature_generic_dest)) { 2481 uint32 dest_type, dest; 2482 dest = soc_mem_field32_dest_get(unit, ING_L3_NEXT_HOPm, 2483 &ing_nh, DESTINATIONf, &dest_type); 2484 if (dest_type == SOC_MEM_FIF_DEST_LAG) { 2485 *trunk_id = (dest & SOC_MEM_FIF_DGPP_TGID_MASK); 2486 } else { 2487 *port = (dest & SOC_MEM_FIF_DGPP_PORT_MASK); 2488 *modid = (dest & SOC_MEM_FIF_DGPP_MOD_ID_MASK) >> 2489 SOC_MEM_FIF_DGPP_MOD_ID_SHIFT_BITS; 2490 } 2491 } else { 2492 if (soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, Tf)) { 2493 *trunk_id = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, TGIDf); 2494 } else { 2495 *modid = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, MODULE_IDf); 2496 *port = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, PORT_NUMf); 2497 } 2498 } 2499 *id = vp_base; 2500 return rv; 2501 } 2502 2503 /* 2504 * Function: 2505 * _bcm_tr_subport_port_resolve 2506 * Purpose: 2507 * Get the modid, port, trunk values for a subport port GPORT 2508 * Returns: 2509 * BCM_E_XXX 2510 */ 2511 int 2512 _bcm_tr2_subport_port_resolve(int unit, bcm_gport_t gport, 2513 bcm_module_t *modid, bcm_port_t *port, 2514 bcm_trunk_t *trunk_id, int *id) 2515 { 2516 int rv = BCM_E_NONE, l3_idx; 2517 ing_l3_next_hop_entry_t ing_nh; 2518 egr_l3_intf_entry_t l3_intf; 2519 ing_dvp_table_entry_t dvp; 2520 int nh_index, vp, vp_base; 2521 bcm_module_t my_modid; 2522 2523 _TR2_SUBPORT_CHECK_INIT(unit); 2524 2525 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_modid)); 2526 2527 *id = BCM_GPORT_SUBPORT_PORT_GET(gport); 2528 *modid = (*id >> 12) & SOC_MODID_MAX(unit); 2529 if (*modid != my_modid) { 2530 return (BCM_E_PORT); 2531 } 2532 2533 l3_idx = BCM_GPORT_SUBPORT_PORT_GET(gport) & 0xfff; 2534 if (l3_idx >= BCM_XGS3_L3_IF_TBL_SIZE(unit)) { 2535 return (BCM_E_PARAM); 2536 } 2537 rv = soc_mem_read(unit, EGR_L3_INTFm, MEM_BLOCK_ALL, l3_idx, &l3_intf); 2538 BCM_IF_ERROR_RETURN(rv); 2539 2540 2541 if (soc_feature(unit, soc_feature_subport_enhanced)) { 2542 vp = soc_mem_field32_get(unit, EGR_L3_INTFm, &l3_intf, IVIDf); 2543 vp_base = vp & ~(0x7); 2544 rv = READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ALL, vp_base, &dvp); 2545 BCM_IF_ERROR_RETURN(rv); 2546 nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, NEXT_HOP_INDEXf); 2547 BCM_IF_ERROR_RETURN (soc_mem_read(unit, ING_L3_NEXT_HOPm, MEM_BLOCK_ANY, 2548 nh_index, &ing_nh)); 2549 if (soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, ENTRY_TYPEf) != 0x3) { 2550 /* Entry type is not GPON DVP */ 2551 return BCM_E_NOT_FOUND; 2552 } 2553 } 2554 2555 if (soc_feature(unit, soc_feature_generic_dest)) { 2556 uint32 dest_type, dest; 2557 dest = soc_mem_field32_dest_get(unit, ING_L3_NEXT_HOPm, 2558 &ing_nh, DESTINATIONf, &dest_type); 2559 if (dest_type == SOC_MEM_FIF_DEST_LAG) { 2560 *trunk_id = (dest & SOC_MEM_FIF_DGPP_TGID_MASK); 2561 } else { 2562 *port = (dest & SOC_MEM_FIF_DGPP_PORT_MASK); 2563 } 2564 } else { 2565 if (soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, Tf)) { 2566 *trunk_id = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, TGIDf); 2567 } else { 2568 *port = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, PORT_NUMf); 2569 } 2570 } 2571 return rv; 2572 } 2573 2574 /* 2575 * Function: 2576 * bcm_tr_subport_learn_set 2577 * Purpose: 2578 * Set the CML bits for a subport group. 2579 * Returns: 2580 * BCM_E_XXX 2581 */ 2582 int 2583 bcm_tr2_subport_learn_set(int unit, bcm_gport_t group, uint32 flags) 2584 { 2585 int vp_base, cml = 0, rv = BCM_E_NONE; 2586 source_vp_entry_t svp; 2587 2588 _TR2_SUBPORT_CHECK_INIT(unit); 2589 2590 cml = 0; 2591 if (!(flags & BCM_PORT_LEARN_FWD)) { 2592 cml |= (1 << 0); 2593 } 2594 if (flags & BCM_PORT_LEARN_CPU) { 2595 cml |= (1 << 1); 2596 } 2597 if (flags & BCM_PORT_LEARN_PENDING) { 2598 cml |= (1 << 2); 2599 } 2600 if (flags & BCM_PORT_LEARN_ARL) { 2601 cml |= (1 << 3); 2602 } 2603 2604 vp_base = BCM_GPORT_SUBPORT_GROUP_GET(group); 2605 if (vp_base == -1) { 2606 return BCM_E_PARAM; 2607 } 2608 2609 if (!_BCM_TR2_GROUP_USED_GET(unit, vp_base / 8)) { 2610 return BCM_E_NOT_FOUND; 2611 } 2612 MEM_LOCK(unit, SOURCE_VPm); 2613 rv = READ_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp_base, &svp); 2614 if (soc_SOURCE_VPm_field32_get(unit, &svp, ENTRY_TYPEf) != 0x3) { 2615 MEM_UNLOCK(unit, SOURCE_VPm); 2616 return BCM_E_INTERNAL; 2617 } 2618 soc_SOURCE_VPm_field32_set(unit, &svp, CML_FLAGS_MOVEf, cml); 2619 soc_SOURCE_VPm_field32_set(unit, &svp, CML_FLAGS_NEWf, cml); 2620 rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp_base, &svp); 2621 MEM_UNLOCK(unit, SOURCE_VPm); 2622 return rv; 2623 } 2624 2625 /* 2626 * Function: 2627 * bcm_tr_subport_learn_get 2628 * Purpose: 2629 * Get the CML bits for a subport group. 2630 * Returns: 2631 * BCM_E_XXX 2632 */ 2633 int 2634 bcm_tr2_subport_learn_get(int unit, bcm_gport_t group, uint32 *flags) 2635 { 2636 int vp_base, cml; 2637 source_vp_entry_t svp; 2638 2639 _TR2_SUBPORT_CHECK_INIT(unit); 2640 2641 vp_base = BCM_GPORT_SUBPORT_GROUP_GET(group); 2642 if (vp_base == -1) { 2643 return BCM_E_PARAM; 2644 } 2645 2646 if (!_BCM_TR2_GROUP_USED_GET(unit, vp_base / 8)) { 2647 return BCM_E_NOT_FOUND; 2648 } 2649 BCM_IF_ERROR_RETURN 2650 (READ_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp_base, &svp)); 2651 if (soc_SOURCE_VPm_field32_get(unit, &svp, ENTRY_TYPEf) != 0x3) { 2652 return BCM_E_INTERNAL; 2653 } 2654 cml = soc_SOURCE_VPm_field32_get(unit, &svp, CML_FLAGS_NEWf); 2655 2656 *flags = 0; 2657 if (!(cml & (1 << 0))) { 2658 *flags |= BCM_PORT_LEARN_FWD; 2659 } 2660 if (cml & (1 << 1)) { 2661 *flags |= BCM_PORT_LEARN_CPU; 2662 } 2663 if (cml & (1 << 2)) { 2664 *flags |= BCM_PORT_LEARN_PENDING; 2665 } 2666 if (cml & (1 << 3)) { 2667 *flags |= BCM_PORT_LEARN_ARL; 2668 } 2669 2670 return BCM_E_NONE; 2671 } 2672 2673 STATIC int 2674 _bcm_esw_subport_port_flex_stat_index_set(int unit, bcm_gport_t gport, 2675 int fs_idx, uint32 flags) 2676 { 2677 int rv, vp, vp_base, vt_index, nh_index=-1; 2678 ing_l3_next_hop_entry_t ing_nh; 2679 egr_l3_next_hop_entry_t egr_nh; 2680 ing_dvp_table_entry_t dvp; 2681 bcm_port_t port = 0; 2682 bcm_vlan_t ovid = 0; 2683 uint32 port_class = 0; 2684 uint32 egr_vent[SOC_MAX_MEM_FIELD_WORDS]; /* HW entry buffer. */ 2685 soc_mem_t egr_mem = EGR_VLAN_XLATEm; 2686 2687 2688 /* Subport ports only make sense on egress */ 2689 if (!(flags & _BCM_FLEX_STAT_HW_EGRESS)) { 2690 return BCM_E_PARAM; 2691 } 2692 2693 vp = BCM_GPORT_SUBPORT_PORT_GET(gport); 2694 2695 /* Get the base group VP */ 2696 vp_base = vp & ~(0x7); 2697 2698 /* Get the group's next-hop index */ 2699 rv = READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ALL, vp_base, &dvp); 2700 BCM_IF_ERROR_RETURN(rv); 2701 nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, NEXT_HOP_INDEXf); 2702 /* Get the group's OVID from the group's egress next-hop entry */ 2703 rv = soc_mem_read(unit, EGR_L3_NEXT_HOPm, 2704 MEM_BLOCK_ALL, nh_index, &egr_nh); 2705 BCM_IF_ERROR_RETURN(rv); 2706 ovid = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, OVIDf); 2707 2708 /* Get the egress port class */ 2709 BCM_IF_ERROR_RETURN (soc_mem_read(unit, ING_L3_NEXT_HOPm, MEM_BLOCK_ANY, 2710 nh_index, &ing_nh)); 2711 2712 if (soc_feature(unit, soc_feature_generic_dest)) { 2713 uint32 dt, dv; 2714 dv = soc_mem_field32_dest_get(unit, ING_L3_NEXT_HOPm, 2715 &ing_nh, DESTINATIONf, &dt); 2716 if (dt != SOC_MEM_FIF_DEST_LAG) { 2717 port = dv & SOC_MEM_FIF_DGPP_PORT_MASK; 2718 rv = bcm_esw_port_class_get(unit, port, bcmPortClassVlanTranslateEgress, 2719 &port_class); 2720 BCM_IF_ERROR_RETURN(rv); 2721 } 2722 } else { 2723 if (!soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, Tf)) { 2724 port = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, PORT_NUMf); 2725 rv = bcm_esw_port_class_get(unit, port, bcmPortClassVlanTranslateEgress, 2726 &port_class); 2727 BCM_IF_ERROR_RETURN(rv); 2728 } 2729 } 2730 /* Find the egress vlan translate entry */ 2731 #ifdef BCM_TRIDENT3_SUPPORT 2732 if (SOC_MEM_IS_VALID(unit, EGR_VLAN_XLATE_1_DOUBLEm)) { 2733 egr_mem = EGR_VLAN_XLATE_1_DOUBLEm; 2734 } else 2735 #endif 2736 { 2737 egr_mem = EGR_VLAN_XLATEm; 2738 } 2739 sal_memset(egr_vent, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32)); 2740 #ifdef BCM_TRIDENT3_SUPPORT 2741 if (soc_feature(unit, soc_feature_base_valid)) { 2742 soc_mem_field32_set(unit, egr_mem, egr_vent, BASE_VALID_0f, 3); 2743 soc_mem_field32_set(unit, egr_mem, egr_vent, BASE_VALID_1f, 7); 2744 } else 2745 #endif 2746 { 2747 soc_mem_field32_set(unit, egr_mem, egr_vent, VALIDf, 1); 2748 } 2749 soc_mem_field32_set(unit, egr_mem, egr_vent, OVIDf, ovid); 2750 if (soc_feature(unit, soc_feature_subport_enhanced)) { 2751 soc_mem_field32_set(unit, egr_mem, egr_vent, IVIDf, vp); 2752 } 2753 soc_mem_field32_set(unit, egr_mem, egr_vent, PORT_GROUP_IDf, port_class); 2754 2755 MEM_LOCK(unit, egr_mem); 2756 rv = soc_mem_search(unit, egr_mem, MEM_BLOCK_ALL, &vt_index, 2757 egr_vent, egr_vent, 0); 2758 if (rv < 0) { 2759 MEM_UNLOCK(unit, egr_mem); 2760 return rv; 2761 } 2762 2763 /* Subport ports only make sense on egress */ 2764 if (soc_mem_field_valid(unit, egr_mem, USE_VINTF_CTR_IDXf)) { 2765 soc_mem_field32_set(unit, egr_mem, egr_vent, 2766 USE_VINTF_CTR_IDXf, fs_idx > 0 ? 1 : 0); 2767 } 2768 soc_mem_field32_set(unit, egr_mem, egr_vent, VINTF_CTR_IDXf, 2769 fs_idx); 2770 rv = soc_mem_write(unit, egr_mem, MEM_BLOCK_ALL, vt_index, 2771 egr_vent); 2772 MEM_UNLOCK(unit, egr_mem); 2773 return rv; 2774 } 2775 2776 STATIC int 2777 _bcm_esw_subport_group_flex_stat_index_set(int unit, bcm_gport_t port, 2778 int fs_idx, uint32 flags) 2779 { 2780 int vp_base, rv; 2781 source_vp_entry_t vp_ent; 2782 2783 vp_base = BCM_GPORT_SUBPORT_GROUP_GET(port); 2784 if (vp_base == -1) { 2785 return BCM_E_PARAM; 2786 } 2787 2788 if (!_BCM_TR2_GROUP_USED_GET(unit, (vp_base / 8))) { 2789 return BCM_E_NOT_FOUND; 2790 } 2791 2792 if (!(flags & _BCM_FLEX_STAT_HW_INGRESS)) { 2793 return BCM_E_PARAM; 2794 } 2795 2796 /* Subport groups only make sense on ingress */ 2797 /* Write stat index to SOURCE_VP table entry */ 2798 rv = soc_mem_read(unit, SOURCE_VPm, MEM_BLOCK_ALL, vp_base, &vp_ent); 2799 if (BCM_SUCCESS(rv)) { 2800 if (soc_mem_field_valid(unit, SOURCE_VPm, USE_VINTF_CTR_IDXf)) { 2801 soc_mem_field32_set(unit, SOURCE_VPm, &vp_ent, USE_VINTF_CTR_IDXf, 2802 fs_idx > 0 ? 1 : 0); 2803 } 2804 soc_mem_field32_set(unit, SOURCE_VPm, &vp_ent, VINTF_CTR_IDXf, fs_idx); 2805 rv = soc_mem_write(unit, SOURCE_VPm, MEM_BLOCK_ALL, vp_base, &vp_ent); 2806 } 2807 return rv; 2808 } 2809 2810 int 2811 _bcm_esw_subport_flex_stat_index_set(int unit, bcm_gport_t port, 2812 int fs_idx,uint32 flags) 2813 { 2814 int rv = BCM_E_NONE; 2815 2816 2817 2818 _TR2_SUBPORT_VP_MEM_LOCK(unit); 2819 2820 if (BCM_GPORT_IS_SUBPORT_PORT(port)) { 2821 rv = _bcm_esw_subport_port_flex_stat_index_set(unit, port, fs_idx,flags); 2822 } else if (BCM_GPORT_IS_SUBPORT_GROUP(port)) { 2823 rv = _bcm_esw_subport_group_flex_stat_index_set(unit, port, fs_idx,flags); 2824 } 2825 2826 _TR2_SUBPORT_VP_MEM_UNLOCK(unit); 2827 return rv; 2828 } 2829 2830 #ifdef BCM_WARM_BOOT_SUPPORT_SW_DUMP 2831 /* 2832 * Function: 2833 * _bcm_tr2_subport_sw_dump 2834 * Purpose: 2835 * Print Subport module s/w state 2836 * Returns: 2837 * void 2838 */ 2839 void 2840 _bcm_tr2_subport_sw_dump(int unit) 2841 { 2842 int idx, sub_prt; 2843 2844 if (_tr2_subport_id[unit] == NULL || _tr2_group_bitmap[unit] == NULL) { 2845 LOG_CLI((BSL_META_U(unit, 2846 "\nSubport feature is not initialized\n"))); 2847 return; 2848 } 2849 2850 2851 LOG_CLI((BSL_META_U(unit, 2852 "SOC Feature: Subport Enhanced.\n"))); 2853 LOG_CLI((BSL_META_U(unit, 2854 "Subport Groups:\n"))); 2855 for(idx = 0; idx < _TR2_SUBPORT_NUM_GROUP; idx++) { 2856 if(_BCM_TR2_GROUP_USED_GET(unit, idx)) { 2857 LOG_CLI((BSL_META_U(unit, 2858 "%d "), idx)); 2859 } 2860 } 2861 2862 LOG_CLI((BSL_META_U(unit, 2863 "\n----\n"))); 2864 2865 LOG_CLI((BSL_META_U(unit, 2866 "Subport IDs used:\n"))); 2867 for(idx = 0; idx < _TR2_SUBPORT_NUM_VP; idx++) { 2868 if((sub_prt = _BCM_TR2_SUBPORT_ID_GET(unit, idx)) != 0xffff) { 2869 LOG_CLI((BSL_META_U(unit, 2870 "Subport ID=%d, VP=%d \n"), sub_prt, idx)); 2871 } 2872 } 2873 } 2874 #endif /* BCM_WARM_BOOT_SUPPORT_SW_DUMP */ 2875 2876 #else /* INCLUDE_L3 && BCM_TRIUMPH2_SUPPORT */ 2877 int bcm_esw_triumph2_subport_not_empty; 2878 #endif /* INCLUDE_L3 && BCM_TRIUMPH2_SUPPORT */